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