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 #include "qgsvertexid.h"
24
25 #include <nlohmann/json.hpp>
26 #include <limits>
27 #include <QTransform>
28
QgsAbstractGeometry(const QgsAbstractGeometry & geom)29 QgsAbstractGeometry::QgsAbstractGeometry( const QgsAbstractGeometry &geom )
30 {
31 mWkbType = geom.mWkbType;
32 }
33
operator =(const QgsAbstractGeometry & geom)34 QgsAbstractGeometry &QgsAbstractGeometry::operator=( const QgsAbstractGeometry &geom )
35 {
36 if ( &geom != this )
37 {
38 clear();
39 mWkbType = geom.mWkbType;
40 }
41 return *this;
42 }
43
compareTo(const QgsAbstractGeometry * other) const44 int QgsAbstractGeometry::compareTo( const QgsAbstractGeometry *other ) const
45 {
46 // compare to self
47 if ( this == other )
48 {
49 return 0;
50 }
51
52 if ( sortIndex() != other->sortIndex() )
53 {
54 //different geometry types
55 const int diff = sortIndex() - other->sortIndex();
56 return ( diff > 0 ) - ( diff < 0 );
57 }
58
59 // same types
60 if ( isEmpty() && other->isEmpty() )
61 {
62 return 0;
63 }
64
65 if ( isEmpty() )
66 {
67 return -1;
68 }
69 if ( other->isEmpty() )
70 {
71 return 1;
72 }
73
74 return compareToSameClass( other );
75 }
76
setZMTypeFromSubGeometry(const QgsAbstractGeometry * subgeom,QgsWkbTypes::Type baseGeomType)77 void QgsAbstractGeometry::setZMTypeFromSubGeometry( const QgsAbstractGeometry *subgeom, QgsWkbTypes::Type baseGeomType )
78 {
79 if ( !subgeom )
80 {
81 return;
82 }
83
84 //special handling for 25d types:
85 if ( baseGeomType == QgsWkbTypes::LineString &&
86 ( subgeom->wkbType() == QgsWkbTypes::Point25D || subgeom->wkbType() == QgsWkbTypes::LineString25D ) )
87 {
88 mWkbType = QgsWkbTypes::LineString25D;
89 return;
90 }
91 else if ( baseGeomType == QgsWkbTypes::Polygon &&
92 ( subgeom->wkbType() == QgsWkbTypes::Point25D || subgeom->wkbType() == QgsWkbTypes::LineString25D ) )
93 {
94 mWkbType = QgsWkbTypes::Polygon25D;
95 return;
96 }
97
98 const bool hasZ = subgeom->is3D();
99 const bool hasM = subgeom->isMeasure();
100
101 if ( hasZ && hasM )
102 {
103 mWkbType = QgsWkbTypes::addM( QgsWkbTypes::addZ( baseGeomType ) );
104 }
105 else if ( hasZ )
106 {
107 mWkbType = QgsWkbTypes::addZ( baseGeomType );
108 }
109 else if ( hasM )
110 {
111 mWkbType = QgsWkbTypes::addM( baseGeomType );
112 }
113 else
114 {
115 mWkbType = baseGeomType;
116 }
117 }
118
calculateBoundingBox() const119 QgsRectangle QgsAbstractGeometry::calculateBoundingBox() const
120 {
121 double xmin = std::numeric_limits<double>::max();
122 double ymin = std::numeric_limits<double>::max();
123 double xmax = -std::numeric_limits<double>::max();
124 double ymax = -std::numeric_limits<double>::max();
125
126 QgsVertexId id;
127 QgsPoint vertex;
128 double x, y;
129 while ( nextVertex( id, vertex ) )
130 {
131 x = vertex.x();
132 y = vertex.y();
133 if ( x < xmin )
134 xmin = x;
135 if ( x > xmax )
136 xmax = x;
137 if ( y < ymin )
138 ymin = y;
139 if ( y > ymax )
140 ymax = y;
141 }
142
143 return QgsRectangle( xmin, ymin, xmax, ymax );
144 }
145
clearCache() const146 void QgsAbstractGeometry::clearCache() const
147 {
148 }
149
nCoordinates() const150 int QgsAbstractGeometry::nCoordinates() const
151 {
152 int nCoords = 0;
153
154 const QgsCoordinateSequence seq = coordinateSequence();
155 for ( const QgsRingSequence &r : seq )
156 {
157 for ( const QgsPointSequence &p : r )
158 {
159 nCoords += p.size();
160 }
161 }
162
163 return nCoords;
164 }
165
length() const166 double QgsAbstractGeometry::length() const
167 {
168 return 0.0;
169 }
170
perimeter() const171 double QgsAbstractGeometry::perimeter() const
172 {
173 return 0.0;
174 }
175
area() const176 double QgsAbstractGeometry::area() const
177 {
178 return 0.0;
179 }
180
wktTypeStr() const181 QString QgsAbstractGeometry::wktTypeStr() const
182 {
183 QString wkt = geometryType();
184 if ( is3D() )
185 wkt += 'Z';
186 if ( isMeasure() )
187 wkt += 'M';
188 return wkt;
189 }
190
asJson(int precision)191 QString QgsAbstractGeometry::asJson( int precision )
192 {
193 return QString::fromStdString( asJsonObject( precision ).dump() );
194 }
195
asJsonObject(int precision) const196 json QgsAbstractGeometry::asJsonObject( int precision ) const
197 {
198 Q_UNUSED( precision ) return nullptr;
199 }
200
centroid() const201 QgsPoint QgsAbstractGeometry::centroid() const
202 {
203 if ( isEmpty() )
204 return QgsPoint();
205
206 // http://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon
207 // Pick the first ring of first part for the moment
208
209 const int n = vertexCount( 0, 0 );
210 if ( n == 1 )
211 {
212 return vertexAt( QgsVertexId( 0, 0, 0 ) );
213 }
214
215 double A = 0.;
216 double Cx = 0.;
217 double Cy = 0.;
218 const QgsPoint v0 = vertexAt( QgsVertexId( 0, 0, 0 ) );
219 int i = 0, j = 1;
220 if ( vertexAt( QgsVertexId( 0, 0, 0 ) ) != vertexAt( QgsVertexId( 0, 0, n - 1 ) ) )
221 {
222 i = n - 1;
223 j = 0;
224 }
225 for ( ; j < n; i = j++ )
226 {
227 QgsPoint vi = vertexAt( QgsVertexId( 0, 0, i ) );
228 QgsPoint vj = vertexAt( QgsVertexId( 0, 0, j ) );
229 vi.rx() -= v0.x();
230 vi.ry() -= v0.y();
231 vj.rx() -= v0.x();
232 vj.ry() -= v0.y();
233 const double d = vi.x() * vj.y() - vj.x() * vi.y();
234 A += d;
235 Cx += ( vi.x() + vj.x() ) * d;
236 Cy += ( vi.y() + vj.y() ) * d;
237 }
238
239 if ( A < 1E-12 )
240 {
241 Cx = Cy = 0.;
242 for ( int i = 0; i < n - 1; ++i )
243 {
244 const QgsPoint vi = vertexAt( QgsVertexId( 0, 0, i ) );
245 Cx += vi.x();
246 Cy += vi.y();
247 }
248 return QgsPoint( Cx / ( n - 1 ), Cy / ( n - 1 ) );
249 }
250 else
251 {
252 return QgsPoint( v0.x() + Cx / ( 3. * A ), v0.y() + Cy / ( 3. * A ) );
253 }
254 }
255
convertTo(QgsWkbTypes::Type type)256 bool QgsAbstractGeometry::convertTo( QgsWkbTypes::Type type )
257 {
258 if ( type == mWkbType )
259 return true;
260
261 if ( QgsWkbTypes::flatType( type ) != QgsWkbTypes::flatType( mWkbType ) )
262 return false;
263
264 const bool needZ = QgsWkbTypes::hasZ( type );
265 const bool needM = QgsWkbTypes::hasM( type );
266 if ( !needZ )
267 {
268 dropZValue();
269 }
270 else if ( !is3D() )
271 {
272 addZValue( std::numeric_limits<double>::quiet_NaN() );
273 }
274
275 if ( !needM )
276 {
277 dropMValue();
278 }
279 else if ( !isMeasure() )
280 {
281 addMValue( std::numeric_limits<double>::quiet_NaN() );
282 }
283
284 return true;
285 }
286
simplifiedTypeRef() const287 const QgsAbstractGeometry *QgsAbstractGeometry::simplifiedTypeRef() const
288 {
289 return this;
290 }
291
filterVertices(const std::function<bool (const QgsPoint &)> &)292 void QgsAbstractGeometry::filterVertices( const std::function<bool ( const QgsPoint & )> & )
293 {
294 // Ideally this would be pure virtual, but SIP has issues with that
295 }
296
transformVertices(const std::function<QgsPoint (const QgsPoint &)> &)297 void QgsAbstractGeometry::transformVertices( const std::function<QgsPoint( const QgsPoint & )> & )
298 {
299 // Ideally this would be pure virtual, but SIP has issues with that
300 }
301
parts_end()302 QgsAbstractGeometry::part_iterator QgsAbstractGeometry::parts_end()
303 {
304 const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( this );
305 return part_iterator( this, collection ? collection->partCount() : 1 );
306 }
307
parts()308 QgsGeometryPartIterator QgsAbstractGeometry::parts()
309 {
310 return QgsGeometryPartIterator( this );
311 }
312
parts() const313 QgsGeometryConstPartIterator QgsAbstractGeometry::parts() const
314 {
315 return QgsGeometryConstPartIterator( this );
316 }
317
const_parts_end() const318 QgsAbstractGeometry::const_part_iterator QgsAbstractGeometry::const_parts_end() const
319 {
320 const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( this );
321 return const_part_iterator( this, collection ? collection->partCount() : 1 );
322 }
323
vertices() const324 QgsVertexIterator QgsAbstractGeometry::vertices() const
325 {
326 return QgsVertexIterator( this );
327 }
328
sortIndex() const329 int QgsAbstractGeometry::sortIndex() const
330 {
331 switch ( QgsWkbTypes::flatType( mWkbType ) )
332 {
333 case QgsWkbTypes::Point:
334 return 0;
335 case QgsWkbTypes::MultiPoint:
336 return 1;
337 case QgsWkbTypes::LineString:
338 return 2;
339 case QgsWkbTypes::CircularString:
340 return 3;
341 case QgsWkbTypes::CompoundCurve:
342 return 4;
343 case QgsWkbTypes::MultiLineString:
344 return 5;
345 case QgsWkbTypes::MultiCurve:
346 return 6;
347 case QgsWkbTypes::Polygon:
348 case QgsWkbTypes::Triangle:
349 return 7;
350 case QgsWkbTypes::CurvePolygon:
351 return 8;
352 case QgsWkbTypes::MultiPolygon:
353 return 9;
354 case QgsWkbTypes::MultiSurface:
355 return 10;
356 case QgsWkbTypes::GeometryCollection:
357 return 11;
358 case QgsWkbTypes::Unknown:
359 return 12;
360 case QgsWkbTypes::NoGeometry:
361 default:
362 break;
363 }
364 return 13;
365 }
366
hasChildGeometries() const367 bool QgsAbstractGeometry::hasChildGeometries() const
368 {
369 return QgsWkbTypes::isMultiType( wkbType() ) || dimension() == 2;
370 }
371
childPoint(int index) const372 QgsPoint QgsAbstractGeometry::childPoint( int index ) const
373 {
374 Q_UNUSED( index )
375 return QgsPoint();
376 }
377
isEmpty() const378 bool QgsAbstractGeometry::isEmpty() const
379 {
380 QgsVertexId vId;
381 QgsPoint vertex;
382 return !nextVertex( vId, vertex );
383 }
384
hasCurvedSegments() const385 bool QgsAbstractGeometry::hasCurvedSegments() const
386 {
387 return false;
388 }
389
boundingBoxIntersects(const QgsRectangle & rectangle) const390 bool QgsAbstractGeometry::boundingBoxIntersects( const QgsRectangle &rectangle ) const
391 {
392 return boundingBox().intersects( rectangle );
393 }
394
segmentize(double tolerance,SegmentationToleranceType toleranceType) const395 QgsAbstractGeometry *QgsAbstractGeometry::segmentize( double tolerance, SegmentationToleranceType toleranceType ) const
396 {
397 Q_UNUSED( tolerance )
398 Q_UNUSED( toleranceType )
399 return clone();
400 }
401
402
vertex_iterator(const QgsAbstractGeometry * g,int index)403 QgsAbstractGeometry::vertex_iterator::vertex_iterator( const QgsAbstractGeometry *g, int index )
404 : depth( 0 )
405 {
406 levels.fill( Level() );
407 levels[0].g = g;
408 levels[0].index = index;
409
410 digDown(); // go to the leaf level of the first vertex
411 }
412
operator ++()413 QgsAbstractGeometry::vertex_iterator &QgsAbstractGeometry::vertex_iterator::operator++()
414 {
415 if ( depth == 0 && levels[0].index >= levels[0].g->childCount() )
416 return *this; // end of geometry - nowhere else to go
417
418 Q_ASSERT( !levels[depth].g->hasChildGeometries() ); // we should be at a leaf level
419
420 ++levels[depth].index;
421
422 // traverse up if we are at the end in the current level
423 while ( depth > 0 && levels[depth].index >= levels[depth].g->childCount() )
424 {
425 --depth;
426 ++levels[depth].index;
427 }
428
429 digDown(); // go to the leaf level again
430
431 return *this;
432 }
433
operator ++(int)434 QgsAbstractGeometry::vertex_iterator QgsAbstractGeometry::vertex_iterator::operator++( int )
435 {
436 vertex_iterator it( *this );
437 ++*this;
438 return it;
439 }
440
operator *() const441 QgsPoint QgsAbstractGeometry::vertex_iterator::operator*() const
442 {
443 Q_ASSERT( !levels[depth].g->hasChildGeometries() );
444 return levels[depth].g->childPoint( levels[depth].index );
445 }
446
vertexId() const447 QgsVertexId QgsAbstractGeometry::vertex_iterator::vertexId() const
448 {
449 int part = 0, ring = 0, vertex = levels[depth].index;
450 if ( depth == 0 )
451 {
452 // nothing else to do
453 }
454 else if ( depth == 1 )
455 {
456 if ( QgsWkbTypes::isMultiType( levels[0].g->wkbType() ) )
457 part = levels[0].index;
458 else
459 ring = levels[0].index;
460 }
461 else if ( depth == 2 )
462 {
463 part = levels[0].index;
464 ring = levels[1].index;
465 }
466 else
467 {
468 Q_ASSERT( false );
469 return QgsVertexId();
470 }
471
472 // get the vertex type: find out from the leaf geometry
473 Qgis::VertexType vertexType = Qgis::VertexType::Segment;
474 if ( const QgsCurve *curve = dynamic_cast<const QgsCurve *>( levels[depth].g ) )
475 {
476 QgsPoint p;
477 curve->pointAt( vertex, p, vertexType );
478 }
479
480 return QgsVertexId( part, ring, vertex, vertexType );
481 }
482
operator ==(const QgsAbstractGeometry::vertex_iterator & other) const483 bool QgsAbstractGeometry::vertex_iterator::operator==( const QgsAbstractGeometry::vertex_iterator &other ) const
484 {
485 if ( depth != other.depth )
486 return false;
487 return std::equal( std::begin( levels ), std::begin( levels ) + depth + 1, std::begin( other.levels ) );
488 }
489
digDown()490 void QgsAbstractGeometry::vertex_iterator::digDown()
491 {
492 if ( levels[depth].g->hasChildGeometries() && levels[depth].index >= levels[depth].g->childCount() )
493 return; // first check we are not already at the end
494
495 // while not "final" depth for the geom: go one level down.
496 while ( levels[depth].g->hasChildGeometries() )
497 {
498 ++depth;
499 Q_ASSERT( depth < 3 ); // that's capacity of the levels array
500 levels[depth].index = 0;
501 levels[depth].g = levels[depth - 1].g->childGeometry( levels[depth - 1].index );
502 }
503 }
504
next()505 QgsPoint QgsVertexIterator::next()
506 {
507 n = i++;
508 return *n;
509 }
510
part_iterator(QgsAbstractGeometry * g,int index)511 QgsAbstractGeometry::part_iterator::part_iterator( QgsAbstractGeometry *g, int index )
512 : mIndex( index )
513 , mGeometry( g )
514 {
515 }
516
operator ++()517 QgsAbstractGeometry::part_iterator &QgsAbstractGeometry::part_iterator::operator++()
518 {
519 const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( mGeometry );
520 if ( !collection )
521 {
522 mIndex = 1;
523 return *this; // end of geometry -- nowhere else to go
524 }
525
526 if ( mIndex >= collection->partCount() )
527 return *this; // end of geometry - nowhere else to go
528
529 mIndex++;
530 return *this;
531 }
532
operator ++(int)533 QgsAbstractGeometry::part_iterator QgsAbstractGeometry::part_iterator::operator++( int )
534 {
535 part_iterator it( *this );
536 ++*this;
537 return it;
538 }
539
operator *() const540 QgsAbstractGeometry *QgsAbstractGeometry::part_iterator::operator*() const
541 {
542 QgsGeometryCollection *collection = qgsgeometry_cast< QgsGeometryCollection * >( mGeometry );
543 if ( !collection )
544 {
545 return mGeometry;
546 }
547
548 return collection->geometryN( mIndex );
549 }
550
partNumber() const551 int QgsAbstractGeometry::part_iterator::partNumber() const
552 {
553 return mIndex;
554 }
555
operator ==(QgsAbstractGeometry::part_iterator other) const556 bool QgsAbstractGeometry::part_iterator::operator==( QgsAbstractGeometry::part_iterator other ) const
557 {
558 return mGeometry == other.mGeometry && mIndex == other.mIndex;
559 }
560
next()561 QgsAbstractGeometry *QgsGeometryPartIterator::next()
562 {
563 n = i++;
564 return *n;
565 }
566
567
568
const_part_iterator(const QgsAbstractGeometry * g,int index)569 QgsAbstractGeometry::const_part_iterator::const_part_iterator( const QgsAbstractGeometry *g, int index )
570 : mIndex( index )
571 , mGeometry( g )
572 {
573 }
574
operator ++()575 QgsAbstractGeometry::const_part_iterator &QgsAbstractGeometry::const_part_iterator::operator++()
576 {
577 const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( mGeometry );
578 if ( !collection )
579 {
580 mIndex = 1;
581 return *this; // end of geometry -- nowhere else to go
582 }
583
584 if ( mIndex >= collection->partCount() )
585 return *this; // end of geometry - nowhere else to go
586
587 mIndex++;
588 return *this;
589 }
590
operator ++(int)591 QgsAbstractGeometry::const_part_iterator QgsAbstractGeometry::const_part_iterator::operator++( int )
592 {
593 const_part_iterator it( *this );
594 ++*this;
595 return it;
596 }
597
operator *() const598 const QgsAbstractGeometry *QgsAbstractGeometry::const_part_iterator::operator*() const
599 {
600 const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( mGeometry );
601 if ( !collection )
602 {
603 return mGeometry;
604 }
605
606 return collection->geometryN( mIndex );
607 }
608
partNumber() const609 int QgsAbstractGeometry::const_part_iterator::partNumber() const
610 {
611 return mIndex;
612 }
613
operator ==(QgsAbstractGeometry::const_part_iterator other) const614 bool QgsAbstractGeometry::const_part_iterator::operator==( QgsAbstractGeometry::const_part_iterator other ) const
615 {
616 return mGeometry == other.mGeometry && mIndex == other.mIndex;
617 }
618
next()619 const QgsAbstractGeometry *QgsGeometryConstPartIterator::next()
620 {
621 n = i++;
622 return *n;
623 }
624
operator ==(const QgsAbstractGeometry::vertex_iterator::Level & other) const625 bool QgsAbstractGeometry::vertex_iterator::Level::operator==( const QgsAbstractGeometry::vertex_iterator::Level &other ) const
626 {
627 return g == other.g && index == other.index;
628 }
629