Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsabstractgeometry.cpp
3 : : -------------------------------------------------------------------
4 : : Date : 04 Sept 2014
5 : : Copyright : (C) 2014 by Marco Hugentobler
6 : : email : marco.hugentobler at sourcepole dot com
7 : : ***************************************************************************
8 : : * *
9 : : * This program is free software; you can redistribute it and/or modify *
10 : : * it under the terms of the GNU General Public License as published by *
11 : : * the Free Software Foundation; either version 2 of the License, or *
12 : : * (at your option) any later version. *
13 : : * *
14 : : ***************************************************************************/
15 : :
16 : : #include "qgsapplication.h"
17 : : #include "qgsabstractgeometry.h"
18 : : #include "qgswkbptr.h"
19 : : #include "qgsgeos.h"
20 : : #include "qgsmaptopixel.h"
21 : : #include "qgspoint.h"
22 : : #include "qgsgeometrycollection.h"
23 : :
24 : : #include <nlohmann/json.hpp>
25 : : #include <limits>
26 : : #include <QTransform>
27 : :
28 : 97738 : QgsAbstractGeometry::QgsAbstractGeometry( const QgsAbstractGeometry &geom )
29 : 97738 : {
30 : 97738 : mWkbType = geom.mWkbType;
31 : 97738 : }
32 : :
33 : 21777 : QgsAbstractGeometry &QgsAbstractGeometry::operator=( const QgsAbstractGeometry &geom )
34 : : {
35 : 21777 : if ( &geom != this )
36 : : {
37 : 21777 : clear();
38 : 21777 : mWkbType = geom.mWkbType;
39 : 21777 : }
40 : 21777 : return *this;
41 : : }
42 : :
43 : 4198 : void QgsAbstractGeometry::setZMTypeFromSubGeometry( const QgsAbstractGeometry *subgeom, QgsWkbTypes::Type baseGeomType )
44 : : {
45 : 4198 : if ( !subgeom )
46 : : {
47 : 0 : return;
48 : : }
49 : :
50 : : //special handling for 25d types:
51 : 5260 : if ( baseGeomType == QgsWkbTypes::LineString &&
52 : 1077 : ( subgeom->wkbType() == QgsWkbTypes::Point25D || subgeom->wkbType() == QgsWkbTypes::LineString25D ) )
53 : : {
54 : 16 : mWkbType = QgsWkbTypes::LineString25D;
55 : 16 : return;
56 : : }
57 : 5383 : else if ( baseGeomType == QgsWkbTypes::Polygon &&
58 : 1201 : ( subgeom->wkbType() == QgsWkbTypes::Point25D || subgeom->wkbType() == QgsWkbTypes::LineString25D ) )
59 : : {
60 : 4 : mWkbType = QgsWkbTypes::Polygon25D;
61 : 4 : return;
62 : : }
63 : :
64 : 4178 : bool hasZ = subgeom->is3D();
65 : 4178 : bool hasM = subgeom->isMeasure();
66 : :
67 : 4178 : if ( hasZ && hasM )
68 : : {
69 : 435 : mWkbType = QgsWkbTypes::addM( QgsWkbTypes::addZ( baseGeomType ) );
70 : 435 : }
71 : 3743 : else if ( hasZ )
72 : : {
73 : 263 : mWkbType = QgsWkbTypes::addZ( baseGeomType );
74 : 263 : }
75 : 3480 : else if ( hasM )
76 : : {
77 : 157 : mWkbType = QgsWkbTypes::addM( baseGeomType );
78 : 157 : }
79 : : else
80 : : {
81 : 3323 : mWkbType = baseGeomType;
82 : : }
83 : 4198 : }
84 : :
85 : 0 : QgsRectangle QgsAbstractGeometry::calculateBoundingBox() const
86 : : {
87 : 0 : double xmin = std::numeric_limits<double>::max();
88 : 0 : double ymin = std::numeric_limits<double>::max();
89 : 0 : double xmax = -std::numeric_limits<double>::max();
90 : 0 : double ymax = -std::numeric_limits<double>::max();
91 : :
92 : 0 : QgsVertexId id;
93 : 0 : QgsPoint vertex;
94 : : double x, y;
95 : 0 : while ( nextVertex( id, vertex ) )
96 : : {
97 : 0 : x = vertex.x();
98 : 0 : y = vertex.y();
99 : 0 : if ( x < xmin )
100 : 0 : xmin = x;
101 : 0 : if ( x > xmax )
102 : 0 : xmax = x;
103 : 0 : if ( y < ymin )
104 : 0 : ymin = y;
105 : 0 : if ( y > ymax )
106 : 0 : ymax = y;
107 : : }
108 : :
109 : 0 : return QgsRectangle( xmin, ymin, xmax, ymax );
110 : 0 : }
111 : :
112 : 42531 : void QgsAbstractGeometry::clearCache() const
113 : : {
114 : 42531 : }
115 : :
116 : 54 : int QgsAbstractGeometry::nCoordinates() const
117 : : {
118 : 54 : int nCoords = 0;
119 : :
120 : 54 : const QgsCoordinateSequence seq = coordinateSequence();
121 : 108 : for ( const QgsRingSequence &r : seq )
122 : : {
123 : 108 : for ( const QgsPointSequence &p : r )
124 : : {
125 : 54 : nCoords += p.size();
126 : : }
127 : : }
128 : :
129 : 54 : return nCoords;
130 : 54 : }
131 : :
132 : 1 : double QgsAbstractGeometry::length() const
133 : : {
134 : 1 : return 0.0;
135 : : }
136 : :
137 : 17 : double QgsAbstractGeometry::perimeter() const
138 : : {
139 : 17 : return 0.0;
140 : : }
141 : :
142 : 17 : double QgsAbstractGeometry::area() const
143 : : {
144 : 17 : return 0.0;
145 : : }
146 : :
147 : 5616 : QString QgsAbstractGeometry::wktTypeStr() const
148 : : {
149 : 5616 : QString wkt = geometryType();
150 : 5616 : if ( is3D() )
151 : 2671 : wkt += 'Z';
152 : 5616 : if ( isMeasure() )
153 : 2632 : wkt += 'M';
154 : 5616 : return wkt;
155 : 5616 : }
156 : :
157 : 42 : QString QgsAbstractGeometry::asJson( int precision )
158 : : {
159 : 42 : return QString::fromStdString( asJsonObject( precision ).dump() );
160 : 0 : }
161 : :
162 : 0 : json QgsAbstractGeometry::asJsonObject( int precision ) const
163 : : {
164 : 0 : Q_UNUSED( precision ) return nullptr;
165 : : }
166 : :
167 : 95 : QgsPoint QgsAbstractGeometry::centroid() const
168 : : {
169 : : // http://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon
170 : : // Pick the first ring of first part for the moment
171 : :
172 : 95 : int n = vertexCount( 0, 0 );
173 : 95 : if ( n == 1 )
174 : : {
175 : 14 : return vertexAt( QgsVertexId( 0, 0, 0 ) );
176 : : }
177 : :
178 : 81 : double A = 0.;
179 : 81 : double Cx = 0.;
180 : 81 : double Cy = 0.;
181 : 81 : QgsPoint v0 = vertexAt( QgsVertexId( 0, 0, 0 ) );
182 : 81 : int i = 0, j = 1;
183 : 81 : if ( vertexAt( QgsVertexId( 0, 0, 0 ) ) != vertexAt( QgsVertexId( 0, 0, n - 1 ) ) )
184 : : {
185 : 13 : i = n - 1;
186 : 13 : j = 0;
187 : 13 : }
188 : 408 : for ( ; j < n; i = j++ )
189 : : {
190 : 327 : QgsPoint vi = vertexAt( QgsVertexId( 0, 0, i ) );
191 : 327 : QgsPoint vj = vertexAt( QgsVertexId( 0, 0, j ) );
192 : 327 : vi.rx() -= v0.x();
193 : 327 : vi.ry() -= v0.y();
194 : 327 : vj.rx() -= v0.x();
195 : 327 : vj.ry() -= v0.y();
196 : 327 : double d = vi.x() * vj.y() - vj.x() * vi.y();
197 : 327 : A += d;
198 : 327 : Cx += ( vi.x() + vj.x() ) * d;
199 : 327 : Cy += ( vi.y() + vj.y() ) * d;
200 : 327 : }
201 : :
202 : 81 : if ( A < 1E-12 )
203 : : {
204 : 70 : Cx = Cy = 0.;
205 : 346 : for ( int i = 0; i < n - 1; ++i )
206 : : {
207 : 276 : QgsPoint vi = vertexAt( QgsVertexId( 0, 0, i ) );
208 : 276 : Cx += vi.x();
209 : 276 : Cy += vi.y();
210 : 276 : }
211 : 70 : return QgsPoint( Cx / ( n - 1 ), Cy / ( n - 1 ) );
212 : : }
213 : : else
214 : : {
215 : 11 : return QgsPoint( v0.x() + Cx / ( 3. * A ), v0.y() + Cy / ( 3. * A ) );
216 : : }
217 : 95 : }
218 : :
219 : 21 : bool QgsAbstractGeometry::convertTo( QgsWkbTypes::Type type )
220 : : {
221 : 21 : if ( type == mWkbType )
222 : 2 : return true;
223 : :
224 : 19 : if ( QgsWkbTypes::flatType( type ) != QgsWkbTypes::flatType( mWkbType ) )
225 : 3 : return false;
226 : :
227 : 16 : bool needZ = QgsWkbTypes::hasZ( type );
228 : 16 : bool needM = QgsWkbTypes::hasM( type );
229 : 16 : if ( !needZ )
230 : : {
231 : 10 : dropZValue();
232 : 10 : }
233 : 6 : else if ( !is3D() )
234 : : {
235 : 3 : addZValue( std::numeric_limits<double>::quiet_NaN() );
236 : 3 : }
237 : :
238 : 16 : if ( !needM )
239 : : {
240 : 8 : dropMValue();
241 : 8 : }
242 : 8 : else if ( !isMeasure() )
243 : : {
244 : 5 : addMValue( std::numeric_limits<double>::quiet_NaN() );
245 : 5 : }
246 : :
247 : 16 : return true;
248 : 21 : }
249 : :
250 : 0 : void QgsAbstractGeometry::filterVertices( const std::function<bool ( const QgsPoint & )> & )
251 : : {
252 : : // Ideally this would be pure virtual, but SIP has issues with that
253 : 0 : }
254 : :
255 : 0 : void QgsAbstractGeometry::transformVertices( const std::function<QgsPoint( const QgsPoint & )> & )
256 : : {
257 : : // Ideally this would be pure virtual, but SIP has issues with that
258 : 0 : }
259 : :
260 : 43 : QgsAbstractGeometry::part_iterator QgsAbstractGeometry::parts_end()
261 : : {
262 : 43 : const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( this );
263 : 43 : return part_iterator( this, collection ? collection->partCount() : 1 );
264 : : }
265 : :
266 : 5 : QgsGeometryPartIterator QgsAbstractGeometry::parts()
267 : : {
268 : 5 : return QgsGeometryPartIterator( this );
269 : : }
270 : :
271 : 0 : QgsGeometryConstPartIterator QgsAbstractGeometry::parts() const
272 : : {
273 : 0 : return QgsGeometryConstPartIterator( this );
274 : : }
275 : :
276 : 3 : QgsAbstractGeometry::const_part_iterator QgsAbstractGeometry::const_parts_end() const
277 : : {
278 : 3 : const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( this );
279 : 3 : return const_part_iterator( this, collection ? collection->partCount() : 1 );
280 : : }
281 : :
282 : 2 : QgsVertexIterator QgsAbstractGeometry::vertices() const
283 : : {
284 : 2 : return QgsVertexIterator( this );
285 : : }
286 : :
287 : 886 : bool QgsAbstractGeometry::hasChildGeometries() const
288 : : {
289 : 886 : return QgsWkbTypes::isMultiType( wkbType() ) || dimension() == 2;
290 : : }
291 : :
292 : 0 : QgsPoint QgsAbstractGeometry::childPoint( int index ) const
293 : : {
294 : : Q_UNUSED( index )
295 : 0 : return QgsPoint();
296 : : }
297 : :
298 : 0 : bool QgsAbstractGeometry::isEmpty() const
299 : : {
300 : 0 : QgsVertexId vId;
301 : 0 : QgsPoint vertex;
302 : 0 : return !nextVertex( vId, vertex );
303 : 0 : }
304 : :
305 : 1416 : bool QgsAbstractGeometry::hasCurvedSegments() const
306 : : {
307 : 1416 : return false;
308 : : }
309 : :
310 : 6 : bool QgsAbstractGeometry::boundingBoxIntersects( const QgsRectangle &rectangle ) const
311 : : {
312 : 6 : return boundingBox().intersects( rectangle );
313 : : }
314 : :
315 : 1 : QgsAbstractGeometry *QgsAbstractGeometry::segmentize( double tolerance, SegmentationToleranceType toleranceType ) const
316 : : {
317 : : Q_UNUSED( tolerance )
318 : : Q_UNUSED( toleranceType )
319 : 1 : return clone();
320 : : }
321 : :
322 : :
323 : 323 : QgsAbstractGeometry::vertex_iterator::vertex_iterator( const QgsAbstractGeometry *g, int index )
324 : 323 : : depth( 0 )
325 : : {
326 : 323 : levels.fill( Level() );
327 : 323 : levels[0].g = g;
328 : 323 : levels[0].index = index;
329 : :
330 : 323 : digDown(); // go to the leaf level of the first vertex
331 : 323 : }
332 : :
333 : 233 : QgsAbstractGeometry::vertex_iterator &QgsAbstractGeometry::vertex_iterator::operator++()
334 : : {
335 : 233 : if ( depth == 0 && levels[0].index >= levels[0].g->childCount() )
336 : 0 : return *this; // end of geometry - nowhere else to go
337 : :
338 : : Q_ASSERT( !levels[depth].g->hasChildGeometries() ); // we should be at a leaf level
339 : :
340 : 233 : ++levels[depth].index;
341 : :
342 : : // traverse up if we are at the end in the current level
343 : 307 : while ( depth > 0 && levels[depth].index >= levels[depth].g->childCount() )
344 : : {
345 : 74 : --depth;
346 : 74 : ++levels[depth].index;
347 : : }
348 : :
349 : 233 : digDown(); // go to the leaf level again
350 : :
351 : 233 : return *this;
352 : 233 : }
353 : :
354 : 206 : QgsAbstractGeometry::vertex_iterator QgsAbstractGeometry::vertex_iterator::operator++( int )
355 : : {
356 : 206 : vertex_iterator it( *this );
357 : 206 : ++*this;
358 : 206 : return it;
359 : : }
360 : :
361 : 233 : QgsPoint QgsAbstractGeometry::vertex_iterator::operator*() const
362 : : {
363 : : Q_ASSERT( !levels[depth].g->hasChildGeometries() );
364 : 233 : return levels[depth].g->childPoint( levels[depth].index );
365 : : }
366 : :
367 : 27 : QgsVertexId QgsAbstractGeometry::vertex_iterator::vertexId() const
368 : : {
369 : 27 : int part = 0, ring = 0, vertex = levels[depth].index;
370 : 27 : if ( depth == 0 )
371 : : {
372 : : // nothing else to do
373 : 3 : }
374 : 24 : else if ( depth == 1 )
375 : : {
376 : 8 : if ( QgsWkbTypes::isMultiType( levels[0].g->wkbType() ) )
377 : 8 : part = levels[0].index;
378 : : else
379 : 0 : ring = levels[0].index;
380 : 8 : }
381 : 16 : else if ( depth == 2 )
382 : : {
383 : 16 : part = levels[0].index;
384 : 16 : ring = levels[1].index;
385 : 16 : }
386 : : else
387 : : {
388 : : Q_ASSERT( false );
389 : 0 : return QgsVertexId();
390 : : }
391 : :
392 : : // get the vertex type: find out from the leaf geometry
393 : 27 : QgsVertexId::VertexType vertexType = QgsVertexId::SegmentVertex;
394 : 27 : if ( const QgsCurve *curve = dynamic_cast<const QgsCurve *>( levels[depth].g ) )
395 : : {
396 : 24 : QgsPoint p;
397 : 24 : curve->pointAt( vertex, p, vertexType );
398 : 24 : }
399 : :
400 : 27 : return QgsVertexId( part, ring, vertex, vertexType );
401 : 27 : }
402 : :
403 : 247 : bool QgsAbstractGeometry::vertex_iterator::operator==( const QgsAbstractGeometry::vertex_iterator &other ) const
404 : : {
405 : 247 : if ( depth != other.depth )
406 : 201 : return false;
407 : 46 : return std::equal( std::begin( levels ), std::begin( levels ) + depth + 1, std::begin( other.levels ) );
408 : 247 : }
409 : :
410 : 556 : void QgsAbstractGeometry::vertex_iterator::digDown()
411 : : {
412 : 556 : if ( levels[depth].g->hasChildGeometries() && levels[depth].index >= levels[depth].g->childCount() )
413 : 300 : return; // first check we are not already at the end
414 : :
415 : : // while not "final" depth for the geom: go one level down.
416 : 330 : while ( levels[depth].g->hasChildGeometries() )
417 : : {
418 : 74 : ++depth;
419 : : Q_ASSERT( depth < 3 ); // that's capacity of the levels array
420 : 74 : levels[depth].index = 0;
421 : 74 : levels[depth].g = levels[depth - 1].g->childGeometry( levels[depth - 1].index );
422 : : }
423 : 556 : }
424 : :
425 : 206 : QgsPoint QgsVertexIterator::next()
426 : : {
427 : 206 : n = i++;
428 : 206 : return *n;
429 : : }
430 : :
431 : 49 : QgsAbstractGeometry::part_iterator::part_iterator( QgsAbstractGeometry *g, int index )
432 : 49 : : mIndex( index )
433 : 49 : , mGeometry( g )
434 : : {
435 : 49 : }
436 : :
437 : 31 : QgsAbstractGeometry::part_iterator &QgsAbstractGeometry::part_iterator::operator++()
438 : : {
439 : 31 : const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( mGeometry );
440 : 31 : if ( !collection )
441 : : {
442 : 1 : mIndex = 1;
443 : 1 : return *this; // end of geometry -- nowhere else to go
444 : : }
445 : :
446 : 30 : if ( mIndex >= collection->partCount() )
447 : 0 : return *this; // end of geometry - nowhere else to go
448 : :
449 : 30 : mIndex++;
450 : 30 : return *this;
451 : 31 : }
452 : :
453 : 31 : QgsAbstractGeometry::part_iterator QgsAbstractGeometry::part_iterator::operator++( int )
454 : : {
455 : 31 : part_iterator it( *this );
456 : 31 : ++*this;
457 : 31 : return it;
458 : : }
459 : :
460 : 31 : QgsAbstractGeometry *QgsAbstractGeometry::part_iterator::operator*() const
461 : : {
462 : 31 : QgsGeometryCollection *collection = qgsgeometry_cast< QgsGeometryCollection * >( mGeometry );
463 : 31 : if ( !collection )
464 : : {
465 : 1 : return mGeometry;
466 : : }
467 : :
468 : 30 : return collection->geometryN( mIndex );
469 : 31 : }
470 : :
471 : 0 : int QgsAbstractGeometry::part_iterator::partNumber() const
472 : : {
473 : 0 : return mIndex;
474 : : }
475 : :
476 : 37 : bool QgsAbstractGeometry::part_iterator::operator==( QgsAbstractGeometry::part_iterator other ) const
477 : : {
478 : 37 : return mGeometry == other.mGeometry && mIndex == other.mIndex;
479 : : }
480 : :
481 : 31 : QgsAbstractGeometry *QgsGeometryPartIterator::next()
482 : : {
483 : 31 : n = i++;
484 : 31 : return *n;
485 : : }
486 : :
487 : :
488 : :
489 : 4 : QgsAbstractGeometry::const_part_iterator::const_part_iterator( const QgsAbstractGeometry *g, int index )
490 : 4 : : mIndex( index )
491 : 4 : , mGeometry( g )
492 : : {
493 : 4 : }
494 : :
495 : 1 : QgsAbstractGeometry::const_part_iterator &QgsAbstractGeometry::const_part_iterator::operator++()
496 : : {
497 : 1 : const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( mGeometry );
498 : 1 : if ( !collection )
499 : : {
500 : 1 : mIndex = 1;
501 : 1 : return *this; // end of geometry -- nowhere else to go
502 : : }
503 : :
504 : 0 : if ( mIndex >= collection->partCount() )
505 : 0 : return *this; // end of geometry - nowhere else to go
506 : :
507 : 0 : mIndex++;
508 : 0 : return *this;
509 : 1 : }
510 : :
511 : 1 : QgsAbstractGeometry::const_part_iterator QgsAbstractGeometry::const_part_iterator::operator++( int )
512 : : {
513 : 1 : const_part_iterator it( *this );
514 : 1 : ++*this;
515 : 1 : return it;
516 : : }
517 : :
518 : 1 : const QgsAbstractGeometry *QgsAbstractGeometry::const_part_iterator::operator*() const
519 : : {
520 : 1 : const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( mGeometry );
521 : 1 : if ( !collection )
522 : : {
523 : 1 : return mGeometry;
524 : : }
525 : :
526 : 0 : return collection->geometryN( mIndex );
527 : 1 : }
528 : :
529 : 0 : int QgsAbstractGeometry::const_part_iterator::partNumber() const
530 : : {
531 : 0 : return mIndex;
532 : : }
533 : :
534 : 2 : bool QgsAbstractGeometry::const_part_iterator::operator==( QgsAbstractGeometry::const_part_iterator other ) const
535 : : {
536 : 2 : return mGeometry == other.mGeometry && mIndex == other.mIndex;
537 : : }
538 : :
539 : 1 : const QgsAbstractGeometry *QgsGeometryConstPartIterator::next()
540 : : {
541 : 1 : n = i++;
542 : 1 : return *n;
543 : : }
544 : :
545 : 46 : bool QgsAbstractGeometry::vertex_iterator::Level::operator==( const QgsAbstractGeometry::vertex_iterator::Level &other ) const
546 : : {
547 : 46 : return g == other.g && index == other.index;
548 : : }
|