QGIS API Documentation  2.99.0-Master (9f5e33a)
qgsgeometry.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgeometry.cpp - Geometry (stored as Open Geospatial Consortium WKB)
3  -------------------------------------------------------------------
4 Date : 02 May 2005
5 Copyright : (C) 2005 by Brendan Morley
6 email : morb at ozemail dot com dot au
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 <limits>
17 #include <cstdarg>
18 #include <cstdio>
19 #include <cmath>
20 
21 #include "qgis.h"
22 #include "qgsgeometry.h"
23 #include "qgsgeometryeditutils.h"
24 #include "qgsgeometryfactory.h"
25 #include "qgsgeometrymakevalid.h"
26 #include "qgsgeometryutils.h"
28 #include "qgsgeos.h"
29 #include "qgsapplication.h"
30 #include "qgslogger.h"
31 #include "qgsmaptopixel.h"
32 #include "qgsmessagelog.h"
33 #include "qgspointxy.h"
34 #include "qgsrectangle.h"
35 
36 #include "qgsvectorlayer.h"
37 #include "qgsgeometryvalidator.h"
38 
39 #include "qgsmulticurve.h"
40 #include "qgsmultilinestring.h"
41 #include "qgsmultipoint.h"
42 #include "qgsmultipolygon.h"
43 #include "qgsmultisurface.h"
44 #include "qgspoint.h"
45 #include "qgspolygon.h"
46 #include "qgslinestring.h"
47 
49 {
50  QgsGeometryPrivate(): ref( 1 ), geometry( nullptr ) {}
52  QAtomicInt ref;
54 };
55 
57 {
58 }
59 
61 {
62  if ( !d->ref.deref() )
63  delete d;
64 }
65 
67 {
68  d->geometry = geom;
69  d->ref = QAtomicInt( 1 );
70 }
71 
73 {
74  d = other.d;
75  d->ref.ref();
76 }
77 
79 {
80  if ( !d->ref.deref() )
81  {
82  delete d;
83  }
84 
85  d = other.d;
86  d->ref.ref();
87  return *this;
88 }
89 
90 void QgsGeometry::detach( bool cloneGeom )
91 {
92  if ( d->ref > 1 )
93  {
94  ( void )d->ref.deref();
95  QgsAbstractGeometry *cGeom = nullptr;
96 
97  if ( d->geometry && cloneGeom )
98  {
99  cGeom = d->geometry->clone();
100  }
101 
102  d = new QgsGeometryPrivate();
103  d->geometry = cGeom;
104  }
105 }
106 
108 {
109  return d->geometry;
110 }
111 
113 {
114  if ( d->geometry == geometry )
115  {
116  return;
117  }
118 
119  detach( false );
120  if ( d->geometry )
121  {
122  delete d->geometry;
123  d->geometry = nullptr;
124  }
125 
126  d->geometry = geometry;
127 }
128 
130 {
131  return !d->geometry;
132 }
133 
134 QgsGeometry QgsGeometry::fromWkt( const QString &wkt )
135 {
137  if ( !geom )
138  {
139  return QgsGeometry();
140  }
141  return QgsGeometry( geom );
142 }
143 
145 {
147  if ( geom )
148  {
149  return QgsGeometry( geom );
150  }
151  return QgsGeometry();
152 }
153 
155 {
157  if ( geom )
158  {
159  return QgsGeometry( geom );
160  }
161  return QgsGeometry();
162 }
163 
165 {
167  if ( geom )
168  {
169  return QgsGeometry( geom );
170  }
171  return QgsGeometry();
172 }
173 
175 {
177  if ( geom )
178  {
179  return QgsGeometry( geom );
180  }
181  return QgsGeometry();
182 }
183 
185 {
187  if ( geom )
188  {
189  return QgsGeometry( geom );
190  }
191  return QgsGeometry();
192 }
193 
195 {
197  if ( geom )
198  {
199  return QgsGeometry( geom );
200  }
201  return QgsGeometry();
202 }
203 
205 {
206  QgsPolyline ring;
207  ring.append( QgsPointXY( rect.xMinimum(), rect.yMinimum() ) );
208  ring.append( QgsPointXY( rect.xMaximum(), rect.yMinimum() ) );
209  ring.append( QgsPointXY( rect.xMaximum(), rect.yMaximum() ) );
210  ring.append( QgsPointXY( rect.xMinimum(), rect.yMaximum() ) );
211  ring.append( QgsPointXY( rect.xMinimum(), rect.yMinimum() ) );
212 
213  QgsPolygon polygon;
214  polygon.append( ring );
215 
216  return fromPolygon( polygon );
217 }
218 
219 QgsGeometry QgsGeometry::collectGeometry( const QList< QgsGeometry > &geometries )
220 {
221  QgsGeometry collected;
222 
223  QList< QgsGeometry >::const_iterator git = geometries.constBegin();
224  for ( ; git != geometries.constEnd(); ++git )
225  {
226  if ( collected.isNull() )
227  {
228  collected = QgsGeometry( *git );
229  collected.convertToMultiType();
230  }
231  else
232  {
233  collected.addPart( *git );
234  }
235  }
236  return collected;
237 }
238 
239 void QgsGeometry::fromWkb( unsigned char *wkb, int length )
240 {
241  detach( false );
242 
243  if ( d->geometry )
244  {
245  delete d->geometry;
246  }
247  QgsConstWkbPtr ptr( wkb, length );
249  delete [] wkb;
250 }
251 
252 void QgsGeometry::fromWkb( const QByteArray &wkb )
253 {
254  detach( false );
255 
256  if ( d->geometry )
257  {
258  delete d->geometry;
259  }
260  QgsConstWkbPtr ptr( wkb );
262 }
263 
264 GEOSGeometry *QgsGeometry::exportToGeos( double precision ) const
265 {
266  if ( !d->geometry )
267  {
268  return nullptr;
269  }
270 
271  return QgsGeos::asGeos( d->geometry, precision );
272 }
273 
274 
276 {
277  if ( !d->geometry )
278  {
279  return QgsWkbTypes::Unknown;
280  }
281  else
282  {
283  return d->geometry->wkbType();
284  }
285 }
286 
287 
289 {
290  if ( !d->geometry )
291  {
293  }
294  return static_cast< QgsWkbTypes::GeometryType >( QgsWkbTypes::geometryType( d->geometry->wkbType() ) );
295 }
296 
298 {
299  if ( !d->geometry )
300  {
301  return true;
302  }
303 
304  return d->geometry->isEmpty();
305 }
306 
308 {
309  if ( !d->geometry )
310  {
311  return false;
312  }
313  return QgsWkbTypes::isMultiType( d->geometry->wkbType() );
314 }
315 
316 void QgsGeometry::fromGeos( GEOSGeometry *geos )
317 {
318  detach( false );
319  delete d->geometry;
320  d->geometry = QgsGeos::fromGeos( geos );
321  GEOSGeom_destroy_r( QgsGeos::getGEOSHandler(), geos );
322 }
323 
324 QgsPointXY QgsGeometry::closestVertex( const QgsPointXY &point, int &atVertex, int &beforeVertex, int &afterVertex, double &sqrDist ) const
325 {
326  if ( !d->geometry )
327  {
328  sqrDist = -1;
329  return QgsPointXY( 0, 0 );
330  }
331 
332  QgsPoint pt( point.x(), point.y() );
333  QgsVertexId id;
334 
335  QgsPoint vp = QgsGeometryUtils::closestVertex( *( d->geometry ), pt, id );
336  if ( !id.isValid() )
337  {
338  sqrDist = -1;
339  return QgsPointXY( 0, 0 );
340  }
341  sqrDist = QgsGeometryUtils::sqrDistance2D( pt, vp );
342 
343  atVertex = vertexNrFromVertexId( id );
344  adjacentVertices( atVertex, beforeVertex, afterVertex );
345  return QgsPointXY( vp.x(), vp.y() );
346 }
347 
348 double QgsGeometry::distanceToVertex( int vertex ) const
349 {
350  if ( !d->geometry )
351  {
352  return -1;
353  }
354 
355  QgsVertexId id;
356  if ( !vertexIdFromVertexNr( vertex, id ) )
357  {
358  return -1;
359  }
360 
361  return QgsGeometryUtils::distanceToVertex( *( d->geometry ), id );
362 }
363 
364 double QgsGeometry::angleAtVertex( int vertex ) const
365 {
366  if ( !d->geometry )
367  {
368  return 0;
369  }
370 
371  QgsVertexId v2;
372  if ( !vertexIdFromVertexNr( vertex, v2 ) )
373  {
374  return 0;
375  }
376 
377  QgsVertexId v1;
378  QgsVertexId v3;
379  QgsGeometryUtils::adjacentVertices( *d->geometry, v2, v1, v3 );
380  if ( v1.isValid() && v3.isValid() )
381  {
382  QgsPoint p1 = d->geometry->vertexAt( v1 );
383  QgsPoint p2 = d->geometry->vertexAt( v2 );
384  QgsPoint p3 = d->geometry->vertexAt( v3 );
385  double angle1 = QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
386  double angle2 = QgsGeometryUtils::lineAngle( p2.x(), p2.y(), p3.x(), p3.y() );
387  return QgsGeometryUtils::averageAngle( angle1, angle2 );
388  }
389  else if ( v3.isValid() )
390  {
391  QgsPoint p1 = d->geometry->vertexAt( v2 );
392  QgsPoint p2 = d->geometry->vertexAt( v3 );
393  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
394  }
395  else if ( v1.isValid() )
396  {
397  QgsPoint p1 = d->geometry->vertexAt( v1 );
398  QgsPoint p2 = d->geometry->vertexAt( v2 );
399  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
400  }
401  return 0.0;
402 }
403 
404 void QgsGeometry::adjacentVertices( int atVertex, int &beforeVertex, int &afterVertex ) const
405 {
406  if ( !d->geometry )
407  {
408  return;
409  }
410 
411  QgsVertexId id;
412  if ( !vertexIdFromVertexNr( atVertex, id ) )
413  {
414  beforeVertex = -1;
415  afterVertex = -1;
416  return;
417  }
418 
419  QgsVertexId beforeVertexId, afterVertexId;
420  QgsGeometryUtils::adjacentVertices( *( d->geometry ), id, beforeVertexId, afterVertexId );
421  beforeVertex = vertexNrFromVertexId( beforeVertexId );
422  afterVertex = vertexNrFromVertexId( afterVertexId );
423 }
424 
425 bool QgsGeometry::moveVertex( double x, double y, int atVertex )
426 {
427  if ( !d->geometry )
428  {
429  return false;
430  }
431 
432  QgsVertexId id;
433  if ( !vertexIdFromVertexNr( atVertex, id ) )
434  {
435  return false;
436  }
437 
438  detach( true );
439 
440  return d->geometry->moveVertex( id, QgsPoint( x, y ) );
441 }
442 
443 bool QgsGeometry::moveVertex( const QgsPoint &p, int atVertex )
444 {
445  if ( !d->geometry )
446  {
447  return false;
448  }
449 
450  QgsVertexId id;
451  if ( !vertexIdFromVertexNr( atVertex, id ) )
452  {
453  return false;
454  }
455 
456  detach( true );
457 
458  return d->geometry->moveVertex( id, p );
459 }
460 
461 bool QgsGeometry::deleteVertex( int atVertex )
462 {
463  if ( !d->geometry )
464  {
465  return false;
466  }
467 
468  //maintain compatibility with < 2.10 API
470  {
471  detach( true );
472  //delete geometry instead of point
473  return static_cast< QgsGeometryCollection * >( d->geometry )->removeGeometry( atVertex );
474  }
475 
476  //if it is a point, set the geometry to nullptr
478  {
479  detach( false );
480  delete d->geometry;
481  d->geometry = nullptr;
482  return true;
483  }
484 
485  QgsVertexId id;
486  if ( !vertexIdFromVertexNr( atVertex, id ) )
487  {
488  return false;
489  }
490 
491  detach( true );
492 
493  return d->geometry->deleteVertex( id );
494 }
495 
496 bool QgsGeometry::insertVertex( double x, double y, int beforeVertex )
497 {
498  if ( !d->geometry )
499  {
500  return false;
501  }
502 
503  //maintain compatibility with < 2.10 API
505  {
506  detach( true );
507  //insert geometry instead of point
508  return static_cast< QgsGeometryCollection * >( d->geometry )->insertGeometry( new QgsPoint( x, y ), beforeVertex );
509  }
510 
511  QgsVertexId id;
512  if ( !vertexIdFromVertexNr( beforeVertex, id ) )
513  {
514  return false;
515  }
516 
517  detach( true );
518 
519  return d->geometry->insertVertex( id, QgsPoint( x, y ) );
520 }
521 
522 bool QgsGeometry::insertVertex( const QgsPoint &point, int beforeVertex )
523 {
524  if ( !d->geometry )
525  {
526  return false;
527  }
528 
529  //maintain compatibility with < 2.10 API
531  {
532  detach( true );
533  //insert geometry instead of point
534  return static_cast< QgsGeometryCollection * >( d->geometry )->insertGeometry( new QgsPoint( point ), beforeVertex );
535  }
536 
537  QgsVertexId id;
538  if ( !vertexIdFromVertexNr( beforeVertex, id ) )
539  {
540  return false;
541  }
542 
543  detach( true );
544 
545  return d->geometry->insertVertex( id, point );
546 }
547 
548 QgsPointXY QgsGeometry::vertexAt( int atVertex ) const
549 {
550  if ( !d->geometry )
551  {
552  return QgsPointXY( 0, 0 );
553  }
554 
555  QgsVertexId vId;
556  ( void )vertexIdFromVertexNr( atVertex, vId );
557  if ( vId.vertex < 0 )
558  {
559  return QgsPointXY( 0, 0 );
560  }
561  QgsPoint pt = d->geometry->vertexAt( vId );
562  return QgsPointXY( pt.x(), pt.y() );
563 }
564 
565 double QgsGeometry::sqrDistToVertexAt( QgsPointXY &point, int atVertex ) const
566 {
567  QgsPointXY vertexPoint = vertexAt( atVertex );
568  return QgsGeometryUtils::sqrDistance2D( QgsPoint( vertexPoint.x(), vertexPoint.y() ), QgsPoint( point.x(), point.y() ) );
569 }
570 
572 {
573  QgsGeos geos( d->geometry );
574  return geos.closestPoint( other );
575 }
576 
578 {
579  QgsGeos geos( d->geometry );
580  return geos.shortestLine( other );
581 }
582 
583 double QgsGeometry::closestVertexWithContext( const QgsPointXY &point, int &atVertex ) const
584 {
585  if ( !d->geometry )
586  {
587  return -1;
588  }
589 
590  QgsVertexId vId;
591  QgsPoint pt( point.x(), point.y() );
592  QgsPoint closestPoint = QgsGeometryUtils::closestVertex( *( d->geometry ), pt, vId );
593  if ( !vId.isValid() )
594  return -1;
595  atVertex = vertexNrFromVertexId( vId );
596  return QgsGeometryUtils::sqrDistance2D( closestPoint, pt );
597 }
598 
600  const QgsPointXY &point,
601  QgsPointXY &minDistPoint,
602  int &afterVertex,
603  double *leftOf,
604  double epsilon ) const
605 {
606  if ( !d->geometry )
607  {
608  return -1;
609  }
610 
611  QgsPoint segmentPt;
612  QgsVertexId vertexAfter;
613  bool leftOfBool;
614 
615  double sqrDist = d->geometry->closestSegment( QgsPoint( point.x(), point.y() ), segmentPt, vertexAfter, &leftOfBool, epsilon );
616  if ( sqrDist < 0 )
617  return -1;
618 
619  minDistPoint.setX( segmentPt.x() );
620  minDistPoint.setY( segmentPt.y() );
621  afterVertex = vertexNrFromVertexId( vertexAfter );
622  if ( leftOf )
623  {
624  *leftOf = leftOfBool ? 1.0 : -1.0;
625  }
626  return sqrDist;
627 }
628 
629 int QgsGeometry::addRing( const QList<QgsPointXY> &ring )
630 {
631  detach( true );
632 
633  QgsLineString *ringLine = new QgsLineString( ring );
634  return addRing( ringLine );
635 }
636 
638 {
639  if ( !d->geometry )
640  {
641  delete ring;
642  return 1;
643  }
644 
645  detach( true );
646 
647  return QgsGeometryEditUtils::addRing( d->geometry, ring );
648 }
649 
650 int QgsGeometry::addPart( const QList<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType )
651 {
653  convertPointList( points, l );
654  return addPart( l, geomType );
655 }
656 
658 {
659  QgsAbstractGeometry *partGeom = nullptr;
660  if ( points.size() == 1 )
661  {
662  partGeom = new QgsPoint( points[0] );
663  }
664  else if ( points.size() > 1 )
665  {
666  QgsLineString *ringLine = new QgsLineString();
667  ringLine->setPoints( points );
668  partGeom = ringLine;
669  }
670  return addPart( partGeom, geomType );
671 }
672 
674 {
675  if ( !d->geometry )
676  {
677  detach( false );
678  switch ( geomType )
679  {
681  d->geometry = new QgsMultiPointV2();
682  break;
684  d->geometry = new QgsMultiLineString();
685  break;
687  d->geometry = new QgsMultiPolygonV2();
688  break;
689  default:
690  return 1;
691  }
692  }
693  else
694  {
695  detach( true );
696  }
697 
699  return QgsGeometryEditUtils::addPart( d->geometry, part );
700 }
701 
702 int QgsGeometry::addPart( const QgsGeometry &newPart )
703 {
704  if ( !d->geometry || !newPart.d || !newPart.d->geometry )
705  {
706  return 1;
707  }
708 
709  return addPart( newPart.d->geometry->clone() );
710 }
711 
712 QgsGeometry QgsGeometry::removeInteriorRings( double minimumRingArea ) const
713 {
714  if ( !d->geometry || type() != QgsWkbTypes::PolygonGeometry )
715  {
716  return QgsGeometry();
717  }
718 
720  {
721  QList<QgsGeometry> parts = asGeometryCollection();
722  QList<QgsGeometry> results;
723  Q_FOREACH ( const QgsGeometry &part, parts )
724  {
725  QgsGeometry result = part.removeInteriorRings( minimumRingArea );
726  if ( result )
727  results << result;
728  }
729  if ( results.isEmpty() )
730  return QgsGeometry();
731 
732  QgsGeometry first = results.takeAt( 0 );
733  Q_FOREACH ( const QgsGeometry &result, results )
734  {
735  first.addPart( result );
736  }
737  return first;
738  }
739  else
740  {
741  QgsCurvePolygon *newPoly = static_cast< QgsCurvePolygon * >( d->geometry->clone() );
742  newPoly->removeInteriorRings( minimumRingArea );
743  return QgsGeometry( newPoly );
744  }
745 }
746 
747 int QgsGeometry::addPart( GEOSGeometry *newPart )
748 {
749  if ( !d->geometry || !newPart )
750  {
751  return 1;
752  }
753 
754  detach( true );
755 
756  QgsAbstractGeometry *geom = QgsGeos::fromGeos( newPart );
757  return QgsGeometryEditUtils::addPart( d->geometry, geom );
758 }
759 
760 int QgsGeometry::translate( double dx, double dy )
761 {
762  if ( !d->geometry )
763  {
764  return 1;
765  }
766 
767  detach( true );
768 
769  d->geometry->transform( QTransform::fromTranslate( dx, dy ) );
770  return 0;
771 }
772 
773 int QgsGeometry::rotate( double rotation, const QgsPointXY &center )
774 {
775  if ( !d->geometry )
776  {
777  return 1;
778  }
779 
780  detach( true );
781 
782  QTransform t = QTransform::fromTranslate( center.x(), center.y() );
783  t.rotate( -rotation );
784  t.translate( -center.x(), -center.y() );
785  d->geometry->transform( t );
786  return 0;
787 }
788 
789 int QgsGeometry::splitGeometry( const QList<QgsPointXY> &splitLine, QList<QgsGeometry> &newGeometries, bool topological, QList<QgsPointXY> &topologyTestPoints )
790 {
791  if ( !d->geometry )
792  {
793  return 0;
794  }
795 
796  QList<QgsAbstractGeometry *> newGeoms;
797  QgsLineString splitLineString( splitLine );
798  QgsPointSequence tp;
799 
800  QgsGeos geos( d->geometry );
801  int result = geos.splitGeometry( splitLineString, newGeoms, topological, tp );
802 
803  if ( result == 0 )
804  {
805  detach( false );
806  d->geometry = newGeoms.at( 0 );
807 
808  newGeometries.clear();
809  for ( int i = 1; i < newGeoms.size(); ++i )
810  {
811  newGeometries.push_back( QgsGeometry( newGeoms.at( i ) ) );
812  }
813  }
814 
815  convertPointList( tp, topologyTestPoints );
816  return result;
817 }
818 
819 int QgsGeometry::reshapeGeometry( const QgsLineString &reshapeLineString )
820 {
821  if ( !d->geometry )
822  {
823  return 0;
824  }
825 
826  QgsGeos geos( d->geometry );
827  int errorCode = 0;
828  QgsAbstractGeometry *geom = geos.reshapeGeometry( reshapeLineString, &errorCode );
829  if ( errorCode == 0 && geom )
830  {
831  detach( false );
832  delete d->geometry;
833  d->geometry = geom;
834  return 0;
835  }
836  return errorCode;
837 }
838 
840 {
841  if ( !d->geometry || !other.d->geometry )
842  {
843  return 0;
844  }
845 
846  QgsGeos geos( d->geometry );
847 
848  QgsAbstractGeometry *diffGeom = geos.intersection( *other.geometry() );
849  if ( !diffGeom )
850  {
851  return 1;
852  }
853 
854  detach( false );
855 
856  delete d->geometry;
857  d->geometry = diffGeom;
858  return 0;
859 }
860 
862 {
863  if ( !d->geometry || other.isNull() )
864  {
865  return QgsGeometry();
866  }
867 
868  QgsGeos geos( d->geometry );
869 
870  QgsAbstractGeometry *diffGeom = geos.intersection( *other.geometry() );
871  if ( !diffGeom )
872  {
873  return QgsGeometry();
874  }
875 
876  return QgsGeometry( diffGeom );
877 }
878 
880 {
881  if ( d->geometry )
882  {
883  return d->geometry->boundingBox();
884  }
885  return QgsRectangle();
886 }
887 
888 QgsGeometry QgsGeometry::orientedMinimumBoundingBox( double &area, double &angle, double &width, double &height ) const
889 {
890  QgsRectangle minRect;
891  area = DBL_MAX;
892  angle = 0;
893  width = DBL_MAX;
894  height = DBL_MAX;
895 
896  if ( !d->geometry || d->geometry->nCoordinates() < 2 )
897  return QgsGeometry();
898 
899  QgsGeometry hull = convexHull();
900  if ( hull.isNull() )
901  return QgsGeometry();
902 
903  QgsVertexId vertexId;
904  QgsPoint pt0;
905  QgsPoint pt1;
906  QgsPoint pt2;
907  // get first point
908  hull.geometry()->nextVertex( vertexId, pt0 );
909  pt1 = pt0;
910  double prevAngle = 0.0;
911  while ( hull.geometry()->nextVertex( vertexId, pt2 ) )
912  {
913  double currentAngle = QgsGeometryUtils::lineAngle( pt1.x(), pt1.y(), pt2.x(), pt2.y() );
914  double rotateAngle = 180.0 / M_PI * ( currentAngle - prevAngle );
915  prevAngle = currentAngle;
916 
917  QTransform t = QTransform::fromTranslate( pt0.x(), pt0.y() );
918  t.rotate( rotateAngle );
919  t.translate( -pt0.x(), -pt0.y() );
920 
921  hull.geometry()->transform( t );
922 
923  QgsRectangle bounds = hull.geometry()->boundingBox();
924  double currentArea = bounds.width() * bounds.height();
925  if ( currentArea < area )
926  {
927  minRect = bounds;
928  area = currentArea;
929  angle = 180.0 / M_PI * currentAngle;
930  width = bounds.width();
931  height = bounds.height();
932  }
933 
934  pt2 = pt1;
935  }
936 
937  QgsGeometry minBounds = QgsGeometry::fromRect( minRect );
938  minBounds.rotate( angle, QgsPointXY( pt0.x(), pt0.y() ) );
939 
940  // constrain angle to 0 - 180
941  if ( angle > 180.0 )
942  angle = fmod( angle, 180.0 );
943 
944  return minBounds;
945 }
946 
947 QgsGeometry QgsGeometry::orthogonalize( double tolerance, int maxIterations, double angleThreshold ) const
948 {
949  QgsInternalGeometryEngine engine( *this );
950 
951  return engine.orthogonalize( tolerance, maxIterations, angleThreshold );
952 }
953 
954 bool QgsGeometry::intersects( const QgsRectangle &r ) const
955 {
956  QgsGeometry g = fromRect( r );
957  return intersects( g );
958 }
959 
961 {
962  if ( !d->geometry || geometry.isNull() )
963  {
964  return false;
965  }
966 
967  QgsGeos geos( d->geometry );
968  return geos.intersects( *geometry.d->geometry );
969 }
970 
971 bool QgsGeometry::contains( const QgsPointXY *p ) const
972 {
973  if ( !d->geometry || !p )
974  {
975  return false;
976  }
977 
978  QgsPoint pt( p->x(), p->y() );
979  QgsGeos geos( d->geometry );
980  return geos.contains( pt );
981 }
982 
984 {
985  if ( !d->geometry || geometry.isNull() )
986  {
987  return false;
988  }
989 
990  QgsGeos geos( d->geometry );
991  return geos.contains( *( geometry.d->geometry ) );
992 }
993 
995 {
996  if ( !d->geometry || geometry.isNull() )
997  {
998  return false;
999  }
1000 
1001  QgsGeos geos( d->geometry );
1002  return geos.disjoint( *( geometry.d->geometry ) );
1003 }
1004 
1006 {
1007  if ( !d->geometry || geometry.isNull() )
1008  {
1009  return false;
1010  }
1011 
1012  QgsGeos geos( d->geometry );
1013  return geos.isEqual( *( geometry.d->geometry ) );
1014 }
1015 
1017 {
1018  if ( !d->geometry || geometry.isNull() )
1019  {
1020  return false;
1021  }
1022 
1023  QgsGeos geos( d->geometry );
1024  return geos.touches( *( geometry.d->geometry ) );
1025 }
1026 
1028 {
1029  if ( !d->geometry || geometry.isNull() )
1030  {
1031  return false;
1032  }
1033 
1034  QgsGeos geos( d->geometry );
1035  return geos.overlaps( *( geometry.d->geometry ) );
1036 }
1037 
1039 {
1040  if ( !d->geometry || geometry.isNull() )
1041  {
1042  return false;
1043  }
1044 
1045  QgsGeos geos( d->geometry );
1046  return geos.within( *( geometry.d->geometry ) );
1047 }
1048 
1050 {
1051  if ( !d->geometry || geometry.isNull() )
1052  {
1053  return false;
1054  }
1055 
1056  QgsGeos geos( d->geometry );
1057  return geos.crosses( *( geometry.d->geometry ) );
1058 }
1059 
1060 QString QgsGeometry::exportToWkt( int precision ) const
1061 {
1062  if ( !d->geometry )
1063  {
1064  return QString();
1065  }
1066  return d->geometry->asWkt( precision );
1067 }
1068 
1069 QString QgsGeometry::exportToGeoJSON( int precision ) const
1070 {
1071  if ( !d->geometry )
1072  {
1073  return QStringLiteral( "null" );
1074  }
1075  return d->geometry->asJSON( precision );
1076 }
1077 
1079 {
1080  switch ( destType )
1081  {
1083  return convertToPoint( destMultipart );
1084 
1086  return convertToLine( destMultipart );
1087 
1089  return convertToPolygon( destMultipart );
1090 
1091  default:
1092  return QgsGeometry();
1093  }
1094 }
1095 
1097 {
1098  if ( !d->geometry )
1099  {
1100  return false;
1101  }
1102 
1103  if ( isMultipart() ) //already multitype, no need to convert
1104  {
1105  return true;
1106  }
1107 
1108  QgsGeometryCollection *multiGeom = dynamic_cast<QgsGeometryCollection *>
1110  if ( !multiGeom )
1111  {
1112  return false;
1113  }
1114 
1115  detach( true );
1116  multiGeom->addGeometry( d->geometry );
1117  d->geometry = multiGeom;
1118  return true;
1119 }
1120 
1122 {
1123  if ( !d->geometry )
1124  {
1125  return false;
1126  }
1127 
1128  if ( !isMultipart() ) //already single part, no need to convert
1129  {
1130  return true;
1131  }
1132 
1133  QgsGeometryCollection *multiGeom = dynamic_cast<QgsGeometryCollection *>( d->geometry );
1134  if ( !multiGeom || multiGeom->partCount() < 1 )
1135  return false;
1136 
1137  QgsAbstractGeometry *firstPart = multiGeom->geometryN( 0 )->clone();
1138  detach( false );
1139 
1140  d->geometry = firstPart;
1141  return true;
1142 }
1143 
1145 {
1147  {
1148  return QgsPointXY();
1149  }
1150  QgsPoint *pt = dynamic_cast<QgsPoint *>( d->geometry );
1151  if ( !pt )
1152  {
1153  return QgsPointXY();
1154  }
1155 
1156  return QgsPointXY( pt->x(), pt->y() );
1157 }
1158 
1160 {
1161  QgsPolyline polyLine;
1162  if ( !d->geometry )
1163  {
1164  return polyLine;
1165  }
1166 
1167  bool doSegmentation = ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::CompoundCurve
1169  QgsLineString *line = nullptr;
1170  if ( doSegmentation )
1171  {
1172  QgsCurve *curve = dynamic_cast<QgsCurve *>( d->geometry );
1173  if ( !curve )
1174  {
1175  return polyLine;
1176  }
1177  line = curve->curveToLine();
1178  }
1179  else
1180  {
1181  line = dynamic_cast<QgsLineString *>( d->geometry );
1182  if ( !line )
1183  {
1184  return polyLine;
1185  }
1186  }
1187 
1188  int nVertices = line->numPoints();
1189  polyLine.resize( nVertices );
1190  for ( int i = 0; i < nVertices; ++i )
1191  {
1192  polyLine[i].setX( line->xAt( i ) );
1193  polyLine[i].setY( line->yAt( i ) );
1194  }
1195 
1196  if ( doSegmentation )
1197  {
1198  delete line;
1199  }
1200 
1201  return polyLine;
1202 }
1203 
1205 {
1206  if ( !d->geometry )
1207  return QgsPolygon();
1208 
1209  bool doSegmentation = ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::CurvePolygon );
1210 
1211  QgsPolygonV2 *p = nullptr;
1212  if ( doSegmentation )
1213  {
1214  QgsCurvePolygon *curvePoly = dynamic_cast<QgsCurvePolygon *>( d->geometry );
1215  if ( !curvePoly )
1216  {
1217  return QgsPolygon();
1218  }
1219  p = curvePoly->toPolygon();
1220  }
1221  else
1222  {
1223  p = dynamic_cast<QgsPolygonV2 *>( d->geometry );
1224  }
1225 
1226  if ( !p )
1227  {
1228  return QgsPolygon();
1229  }
1230 
1231  QgsPolygon polygon;
1232  convertPolygon( *p, polygon );
1233 
1234  if ( doSegmentation )
1235  {
1236  delete p;
1237  }
1238  return polygon;
1239 }
1240 
1242 {
1244  {
1245  return QgsMultiPoint();
1246  }
1247 
1248  const QgsMultiPointV2 *mp = dynamic_cast<QgsMultiPointV2 *>( d->geometry );
1249  if ( !mp )
1250  {
1251  return QgsMultiPoint();
1252  }
1253 
1254  int nPoints = mp->numGeometries();
1255  QgsMultiPoint multiPoint( nPoints );
1256  for ( int i = 0; i < nPoints; ++i )
1257  {
1258  const QgsPoint *pt = static_cast<const QgsPoint *>( mp->geometryN( i ) );
1259  multiPoint[i].setX( pt->x() );
1260  multiPoint[i].setY( pt->y() );
1261  }
1262  return multiPoint;
1263 }
1264 
1266 {
1267  if ( !d->geometry )
1268  {
1269  return QgsMultiPolyline();
1270  }
1271 
1272  QgsGeometryCollection *geomCollection = dynamic_cast<QgsGeometryCollection *>( d->geometry );
1273  if ( !geomCollection )
1274  {
1275  return QgsMultiPolyline();
1276  }
1277 
1278  int nLines = geomCollection->numGeometries();
1279  if ( nLines < 1 )
1280  {
1281  return QgsMultiPolyline();
1282  }
1283 
1284  QgsMultiPolyline mpl;
1285  for ( int i = 0; i < nLines; ++i )
1286  {
1287  bool deleteLine = false;
1288  const QgsLineString *line = dynamic_cast<const QgsLineString *>( geomCollection->geometryN( i ) );
1289  if ( !line )
1290  {
1291  const QgsCurve *curve = dynamic_cast<const QgsCurve *>( geomCollection->geometryN( i ) );
1292  if ( !curve )
1293  {
1294  continue;
1295  }
1296  deleteLine = true;
1297  line = curve->curveToLine();
1298  }
1299 
1300  QgsPointSequence lineCoords;
1301  line->points( lineCoords );
1302  QgsPolyline polyLine;
1303  convertToPolyline( lineCoords, polyLine );
1304  mpl.append( polyLine );
1305 
1306  if ( deleteLine )
1307  {
1308  delete line;
1309  }
1310  }
1311  return mpl;
1312 }
1313 
1315 {
1316  if ( !d->geometry )
1317  {
1318  return QgsMultiPolygon();
1319  }
1320 
1321  QgsGeometryCollection *geomCollection = dynamic_cast<QgsGeometryCollection *>( d->geometry );
1322  if ( !geomCollection )
1323  {
1324  return QgsMultiPolygon();
1325  }
1326 
1327  int nPolygons = geomCollection->numGeometries();
1328  if ( nPolygons < 1 )
1329  {
1330  return QgsMultiPolygon();
1331  }
1332 
1333  QgsMultiPolygon mp;
1334  for ( int i = 0; i < nPolygons; ++i )
1335  {
1336  const QgsPolygonV2 *polygon = dynamic_cast<const QgsPolygonV2 *>( geomCollection->geometryN( i ) );
1337  if ( !polygon )
1338  {
1339  const QgsCurvePolygon *cPolygon = dynamic_cast<const QgsCurvePolygon *>( geomCollection->geometryN( i ) );
1340  if ( cPolygon )
1341  {
1342  polygon = cPolygon->toPolygon();
1343  }
1344  else
1345  {
1346  continue;
1347  }
1348  }
1349 
1350  QgsPolygon poly;
1351  convertPolygon( *polygon, poly );
1352  mp.append( poly );
1353  }
1354  return mp;
1355 }
1356 
1357 double QgsGeometry::area() const
1358 {
1359  if ( !d->geometry )
1360  {
1361  return -1.0;
1362  }
1363  QgsGeos g( d->geometry );
1364 
1365 #if 0
1366  //debug: compare geos area with calculation in QGIS
1367  double geosArea = g.area();
1368  double qgisArea = 0;
1369  QgsSurface *surface = dynamic_cast<QgsSurface *>( d->geometry );
1370  if ( surface )
1371  {
1372  qgisArea = surface->area();
1373  }
1374 #endif
1375 
1376  return g.area();
1377 }
1378 
1379 double QgsGeometry::length() const
1380 {
1381  if ( !d->geometry )
1382  {
1383  return -1.0;
1384  }
1385  QgsGeos g( d->geometry );
1386  return g.length();
1387 }
1388 
1389 double QgsGeometry::distance( const QgsGeometry &geom ) const
1390 {
1391  if ( !d->geometry || !geom.d->geometry )
1392  {
1393  return -1.0;
1394  }
1395 
1396  QgsGeos g( d->geometry );
1397  return g.distance( *( geom.d->geometry ) );
1398 }
1399 
1400 QgsGeometry QgsGeometry::buffer( double distance, int segments ) const
1401 {
1402  if ( !d->geometry )
1403  {
1404  return QgsGeometry();
1405  }
1406 
1407  QgsGeos g( d->geometry );
1408  QgsAbstractGeometry *geom = g.buffer( distance, segments );
1409  if ( !geom )
1410  {
1411  return QgsGeometry();
1412  }
1413  return QgsGeometry( geom );
1414 }
1415 
1416 QgsGeometry QgsGeometry::buffer( double distance, int segments, EndCapStyle endCapStyle, JoinStyle joinStyle, double mitreLimit ) const
1417 {
1418  if ( !d->geometry )
1419  {
1420  return QgsGeometry();
1421  }
1422 
1423  QgsGeos g( d->geometry );
1424  QgsAbstractGeometry *geom = g.buffer( distance, segments, endCapStyle, joinStyle, mitreLimit );
1425  if ( !geom )
1426  {
1427  return QgsGeometry();
1428  }
1429  return QgsGeometry( geom );
1430 }
1431 
1432 QgsGeometry QgsGeometry::offsetCurve( double distance, int segments, JoinStyle joinStyle, double mitreLimit ) const
1433 {
1434  if ( !d->geometry || type() != QgsWkbTypes::LineGeometry )
1435  {
1436  return QgsGeometry();
1437  }
1438 
1439  if ( QgsWkbTypes::isMultiType( d->geometry->wkbType() ) )
1440  {
1441  QList<QgsGeometry> parts = asGeometryCollection();
1442  QList<QgsGeometry> results;
1443  Q_FOREACH ( const QgsGeometry &part, parts )
1444  {
1445  QgsGeometry result = part.offsetCurve( distance, segments, joinStyle, mitreLimit );
1446  if ( result )
1447  results << result;
1448  }
1449  if ( results.isEmpty() )
1450  return QgsGeometry();
1451 
1452  QgsGeometry first = results.takeAt( 0 );
1453  Q_FOREACH ( const QgsGeometry &result, results )
1454  {
1455  first.addPart( result );
1456  }
1457  return first;
1458  }
1459  else
1460  {
1461  QgsGeos geos( d->geometry );
1462  QgsAbstractGeometry *offsetGeom = geos.offsetCurve( distance, segments, joinStyle, mitreLimit );
1463  if ( !offsetGeom )
1464  {
1465  return QgsGeometry();
1466  }
1467  return QgsGeometry( offsetGeom );
1468  }
1469 }
1470 
1471 QgsGeometry QgsGeometry::singleSidedBuffer( double distance, int segments, BufferSide side, JoinStyle joinStyle, double mitreLimit ) const
1472 {
1473  if ( !d->geometry || type() != QgsWkbTypes::LineGeometry )
1474  {
1475  return QgsGeometry();
1476  }
1477 
1478  if ( QgsWkbTypes::isMultiType( d->geometry->wkbType() ) )
1479  {
1480  QList<QgsGeometry> parts = asGeometryCollection();
1481  QList<QgsGeometry> results;
1482  Q_FOREACH ( const QgsGeometry &part, parts )
1483  {
1484  QgsGeometry result = part.singleSidedBuffer( distance, segments, side, joinStyle, mitreLimit );
1485  if ( result )
1486  results << result;
1487  }
1488  if ( results.isEmpty() )
1489  return QgsGeometry();
1490 
1491  QgsGeometry first = results.takeAt( 0 );
1492  Q_FOREACH ( const QgsGeometry &result, results )
1493  {
1494  first.addPart( result );
1495  }
1496  return first;
1497  }
1498  else
1499  {
1500  QgsGeos geos( d->geometry );
1501  QgsAbstractGeometry *bufferGeom = geos.singleSidedBuffer( distance, segments, side,
1502  joinStyle, mitreLimit );
1503  if ( !bufferGeom )
1504  {
1505  return QgsGeometry();
1506  }
1507  return QgsGeometry( bufferGeom );
1508  }
1509 }
1510 
1511 QgsGeometry QgsGeometry::extendLine( double startDistance, double endDistance ) const
1512 {
1513  if ( !d->geometry || type() != QgsWkbTypes::LineGeometry )
1514  {
1515  return QgsGeometry();
1516  }
1517 
1518  if ( QgsWkbTypes::isMultiType( d->geometry->wkbType() ) )
1519  {
1520  QList<QgsGeometry> parts = asGeometryCollection();
1521  QList<QgsGeometry> results;
1522  Q_FOREACH ( const QgsGeometry &part, parts )
1523  {
1524  QgsGeometry result = part.extendLine( startDistance, endDistance );
1525  if ( result )
1526  results << result;
1527  }
1528  if ( results.isEmpty() )
1529  return QgsGeometry();
1530 
1531  QgsGeometry first = results.takeAt( 0 );
1532  Q_FOREACH ( const QgsGeometry &result, results )
1533  {
1534  first.addPart( result );
1535  }
1536  return first;
1537  }
1538  else
1539  {
1540  QgsLineString *line = dynamic_cast< QgsLineString * >( d->geometry );
1541  if ( !line )
1542  return QgsGeometry();
1543 
1544  QgsLineString *newLine = line->clone();
1545  newLine->extend( startDistance, endDistance );
1546  return QgsGeometry( newLine );
1547  }
1548 }
1549 
1550 QgsGeometry QgsGeometry::simplify( double tolerance ) const
1551 {
1552  if ( !d->geometry )
1553  {
1554  return QgsGeometry();
1555  }
1556 
1557  QgsGeos geos( d->geometry );
1558  QgsAbstractGeometry *simplifiedGeom = geos.simplify( tolerance );
1559  if ( !simplifiedGeom )
1560  {
1561  return QgsGeometry();
1562  }
1563  return QgsGeometry( simplifiedGeom );
1564 }
1565 
1566 QgsGeometry QgsGeometry::densifyByCount( int extraNodesPerSegment ) const
1567 {
1568  QgsInternalGeometryEngine engine( *this );
1569 
1570  return engine.densifyByCount( extraNodesPerSegment );
1571 }
1572 
1574 {
1575  QgsInternalGeometryEngine engine( *this );
1576 
1577  return engine.densifyByDistance( distance );
1578 }
1579 
1581 {
1582  if ( !d->geometry )
1583  {
1584  return QgsGeometry();
1585  }
1586 
1587  QgsGeos geos( d->geometry );
1589  bool ok = geos.centroid( centroid );
1590  if ( !ok )
1591  {
1592  return QgsGeometry();
1593  }
1594  return QgsGeometry( centroid.clone() );
1595 }
1596 
1598 {
1599  if ( !d->geometry )
1600  {
1601  return QgsGeometry();
1602  }
1603 
1604  QgsGeos geos( d->geometry );
1605  QgsPoint pt;
1606  bool ok = geos.pointOnSurface( pt );
1607  if ( !ok )
1608  {
1609  return QgsGeometry();
1610  }
1611  return QgsGeometry( pt.clone() );
1612 }
1613 
1614 QgsGeometry QgsGeometry::poleOfInaccessibility( double precision, double *distanceToBoundary ) const
1615 {
1616  QgsInternalGeometryEngine engine( *this );
1617 
1618  return engine.poleOfInaccessibility( precision, distanceToBoundary );
1619 }
1620 
1622 {
1623  if ( !d->geometry )
1624  {
1625  return QgsGeometry();
1626  }
1627  QgsGeos geos( d->geometry );
1628  QgsAbstractGeometry *cHull = geos.convexHull();
1629  if ( !cHull )
1630  {
1631  return QgsGeometry();
1632  }
1633  return QgsGeometry( cHull );
1634 }
1635 
1636 QgsGeometry QgsGeometry::voronoiDiagram( const QgsGeometry &extent, double tolerance, bool edgesOnly ) const
1637 {
1638  if ( !d->geometry )
1639  {
1640  return QgsGeometry();
1641  }
1642 
1643  QgsGeos geos( d->geometry );
1644  return geos.voronoiDiagram( extent.geometry(), tolerance, edgesOnly );
1645 }
1646 
1647 QgsGeometry QgsGeometry::delaunayTriangulation( double tolerance, bool edgesOnly ) const
1648 {
1649  if ( !d->geometry )
1650  {
1651  return QgsGeometry();
1652  }
1653 
1654  QgsGeos geos( d->geometry );
1655  return geos.delaunayTriangulation( tolerance, edgesOnly );
1656 }
1657 
1659 {
1660  if ( !d->geometry )
1661  {
1662  return QgsGeometry();
1663  }
1664 
1665  const QgsAbstractGeometry *geom = d->geometry;
1666  std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
1668  {
1669  segmentizedCopy.reset( d->geometry->segmentize() );
1670  geom = segmentizedCopy.get();
1671  }
1672 
1673  QgsGeos geos( geom );
1674  QgsAbstractGeometry *result = geos.subdivide( maxNodes );
1675  if ( !result )
1676  {
1677  return QgsGeometry();
1678  }
1679  return QgsGeometry( result );
1680 }
1681 
1683 {
1684  if ( !d->geometry )
1685  {
1686  return QgsGeometry();
1687  }
1688 
1689  QgsGeometry line = *this;
1691  line = QgsGeometry( d->geometry->boundary() );
1692 
1693  QgsGeos geos( line.geometry() );
1694  QgsAbstractGeometry *result = geos.interpolate( distance );
1695  if ( !result )
1696  {
1697  return QgsGeometry();
1698  }
1699  return QgsGeometry( result );
1700 }
1701 
1702 double QgsGeometry::lineLocatePoint( const QgsGeometry &point ) const
1703 {
1704  if ( type() != QgsWkbTypes::LineGeometry )
1705  return -1;
1706 
1707  if ( QgsWkbTypes::flatType( point.wkbType() ) != QgsWkbTypes::Point )
1708  return -1;
1709 
1710  QgsGeometry segmentized = *this;
1712  {
1713  segmentized = QgsGeometry( static_cast< QgsCurve * >( d->geometry )->segmentize() );
1714  }
1715 
1716  QgsGeos geos( d->geometry );
1717  return geos.lineLocatePoint( *( static_cast< QgsPoint * >( point.d->geometry ) ) );
1718 }
1719 
1721 {
1722  if ( !d->geometry )
1723  return 0.0;
1724 
1725  // always operate on segmentized geometries
1726  QgsGeometry segmentized = *this;
1728  {
1729  segmentized = QgsGeometry( static_cast< QgsCurve * >( d->geometry )->segmentize() );
1730  }
1731 
1732  QgsVertexId previous;
1733  QgsVertexId next;
1734  if ( !QgsGeometryUtils::verticesAtDistance( *segmentized.geometry(), distance, previous, next ) )
1735  return 0.0;
1736 
1737  if ( previous == next )
1738  {
1739  // distance coincided exactly with a vertex
1740  QgsVertexId v2 = previous;
1741  QgsVertexId v1;
1742  QgsVertexId v3;
1743  QgsGeometryUtils::adjacentVertices( *segmentized.geometry(), v2, v1, v3 );
1744  if ( v1.isValid() && v3.isValid() )
1745  {
1746  QgsPoint p1 = segmentized.geometry()->vertexAt( v1 );
1747  QgsPoint p2 = segmentized.geometry()->vertexAt( v2 );
1748  QgsPoint p3 = segmentized.geometry()->vertexAt( v3 );
1749  double angle1 = QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1750  double angle2 = QgsGeometryUtils::lineAngle( p2.x(), p2.y(), p3.x(), p3.y() );
1751  return QgsGeometryUtils::averageAngle( angle1, angle2 );
1752  }
1753  else if ( v3.isValid() )
1754  {
1755  QgsPoint p1 = segmentized.geometry()->vertexAt( v2 );
1756  QgsPoint p2 = segmentized.geometry()->vertexAt( v3 );
1757  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1758  }
1759  else
1760  {
1761  QgsPoint p1 = segmentized.geometry()->vertexAt( v1 );
1762  QgsPoint p2 = segmentized.geometry()->vertexAt( v2 );
1763  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1764  }
1765  }
1766  else
1767  {
1768  QgsPoint p1 = segmentized.geometry()->vertexAt( previous );
1769  QgsPoint p2 = segmentized.geometry()->vertexAt( next );
1770  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1771  }
1772 }
1773 
1775 {
1776  if ( !d->geometry || geometry.isNull() )
1777  {
1778  return QgsGeometry();
1779  }
1780 
1781  QgsGeos geos( d->geometry );
1782 
1783  QgsAbstractGeometry *resultGeom = geos.intersection( *( geometry.d->geometry ) );
1784  return QgsGeometry( resultGeom );
1785 }
1786 
1788 {
1789  if ( !d->geometry || geometry.isNull() )
1790  {
1791  return QgsGeometry();
1792  }
1793 
1794  QgsGeos geos( d->geometry );
1795 
1796  QgsAbstractGeometry *resultGeom = geos.combine( *( geometry.d->geometry ) );
1797  if ( !resultGeom )
1798  {
1799  return QgsGeometry();
1800  }
1801  return QgsGeometry( resultGeom );
1802 }
1803 
1805 {
1806  if ( !d->geometry )
1807  {
1808  return QgsGeometry();
1809  }
1810 
1812  {
1813  // special case - a single linestring was passed
1814  return QgsGeometry( *this );
1815  }
1816 
1817  QgsGeos geos( d->geometry );
1818  return geos.mergeLines();
1819 }
1820 
1822 {
1823  if ( !d->geometry || geometry.isNull() )
1824  {
1825  return QgsGeometry();
1826  }
1827 
1828  QgsGeos geos( d->geometry );
1829 
1830  QgsAbstractGeometry *resultGeom = geos.difference( *( geometry.d->geometry ) );
1831  if ( !resultGeom )
1832  {
1833  return QgsGeometry();
1834  }
1835  return QgsGeometry( resultGeom );
1836 }
1837 
1839 {
1840  if ( !d->geometry || geometry.isNull() )
1841  {
1842  return QgsGeometry();
1843  }
1844 
1845  QgsGeos geos( d->geometry );
1846 
1847  QgsAbstractGeometry *resultGeom = geos.symDifference( *( geometry.d->geometry ) );
1848  if ( !resultGeom )
1849  {
1850  return QgsGeometry();
1851  }
1852  return QgsGeometry( resultGeom );
1853 }
1854 
1855 QgsGeometry QgsGeometry::extrude( double x, double y )
1856 {
1857  QgsInternalGeometryEngine engine( *this );
1858 
1859  return engine.extrude( x, y );
1860 }
1861 
1862 QByteArray QgsGeometry::exportToWkb() const
1863 {
1864  return d->geometry ? d->geometry->asWkb() : QByteArray();
1865 }
1866 
1867 QList<QgsGeometry> QgsGeometry::asGeometryCollection() const
1868 {
1869  QList<QgsGeometry> geometryList;
1870  if ( !d->geometry )
1871  {
1872  return geometryList;
1873  }
1874 
1875  QgsGeometryCollection *gc = dynamic_cast<QgsGeometryCollection *>( d->geometry );
1876  if ( gc )
1877  {
1878  int numGeom = gc->numGeometries();
1879  geometryList.reserve( numGeom );
1880  for ( int i = 0; i < numGeom; ++i )
1881  {
1882  geometryList.append( QgsGeometry( gc->geometryN( i )->clone() ) );
1883  }
1884  }
1885  else //a singlepart geometry
1886  {
1887  geometryList.append( QgsGeometry( d->geometry->clone() ) );
1888  }
1889 
1890  return geometryList;
1891 }
1892 
1893 QPointF QgsGeometry::asQPointF() const
1894 {
1895  QgsPointXY point = asPoint();
1896  return point.toQPointF();
1897 }
1898 
1899 QPolygonF QgsGeometry::asQPolygonF() const
1900 {
1901  QPolygonF result;
1902  QgsPolyline polyline;
1904  if ( type == QgsWkbTypes::LineString || type == QgsWkbTypes::LineString25D )
1905  {
1906  polyline = asPolyline();
1907  }
1908  else if ( type == QgsWkbTypes::Polygon || type == QgsWkbTypes::Polygon25D )
1909  {
1910  QgsPolygon polygon = asPolygon();
1911  if ( polygon.size() < 1 )
1912  return result;
1913  polyline = polygon.at( 0 );
1914  }
1915  else
1916  {
1917  return result;
1918  }
1919 
1920  QgsPolyline::const_iterator lineIt = polyline.constBegin();
1921  for ( ; lineIt != polyline.constEnd(); ++lineIt )
1922  {
1923  result << lineIt->toQPointF();
1924  }
1925  return result;
1926 }
1927 
1928 bool QgsGeometry::deleteRing( int ringNum, int partNum )
1929 {
1930  if ( !d->geometry )
1931  {
1932  return false;
1933  }
1934 
1935  detach( true );
1936  bool ok = QgsGeometryEditUtils::deleteRing( d->geometry, ringNum, partNum );
1937  return ok;
1938 }
1939 
1940 bool QgsGeometry::deletePart( int partNum )
1941 {
1942  if ( !d->geometry )
1943  {
1944  return false;
1945  }
1946 
1947  if ( !isMultipart() && partNum < 1 )
1948  {
1949  setGeometry( nullptr );
1950  return true;
1951  }
1952 
1953  detach( true );
1954  bool ok = QgsGeometryEditUtils::deletePart( d->geometry, partNum );
1955  return ok;
1956 }
1957 
1958 int QgsGeometry::avoidIntersections( const QList<QgsVectorLayer *> &avoidIntersectionsLayers, const QHash<QgsVectorLayer *, QSet<QgsFeatureId> > &ignoreFeatures )
1959 {
1960  if ( !d->geometry )
1961  {
1962  return 1;
1963  }
1964 
1965  QgsAbstractGeometry *diffGeom = QgsGeometryEditUtils::avoidIntersections( *( d->geometry ), avoidIntersectionsLayers, ignoreFeatures );
1966  if ( diffGeom )
1967  {
1968  detach( false );
1969  d->geometry = diffGeom;
1970  }
1971  return 0;
1972 }
1973 
1974 
1976 {
1977  if ( !d->geometry )
1978  return QgsGeometry();
1979 
1980  QString errorMsg;
1982  if ( !g )
1983  return QgsGeometry();
1984 
1985  return QgsGeometry( g );
1986 }
1987 
1988 
1989 void QgsGeometry::validateGeometry( QList<QgsGeometry::Error> &errors, ValidationMethod method )
1990 {
1991  QgsGeometryValidator::validateGeometry( *this, errors, method );
1992 }
1993 
1995 {
1996  if ( !d->geometry )
1997  {
1998  return false;
1999  }
2000 
2001  QgsGeos geos( d->geometry );
2002  return geos.isValid();
2003 }
2004 
2006 {
2007  if ( !d->geometry )
2008  return false;
2009 
2010  QgsGeos geos( d->geometry );
2011  return geos.isSimple();
2012 }
2013 
2015 {
2016  if ( !d->geometry || !g.d->geometry )
2017  {
2018  return false;
2019  }
2020 
2021  QgsGeos geos( d->geometry );
2022  return geos.isEqual( *( g.d->geometry ) );
2023 }
2024 
2025 QgsGeometry QgsGeometry::unaryUnion( const QList<QgsGeometry> &geometries )
2026 {
2027  QgsGeos geos( nullptr );
2028 
2029  QList<QgsAbstractGeometry *> geomV2List;
2030  QList<QgsGeometry>::const_iterator it = geometries.constBegin();
2031  for ( ; it != geometries.constEnd(); ++it )
2032  {
2033  if ( !( ( *it ).isNull() ) )
2034  {
2035  geomV2List.append( ( *it ).geometry() );
2036  }
2037  }
2038 
2039  QgsAbstractGeometry *geom = geos.combine( geomV2List );
2040  return QgsGeometry( geom );
2041 }
2042 
2043 QgsGeometry QgsGeometry::polygonize( const QList<QgsGeometry> &geometryList )
2044 {
2045  QgsGeos geos( nullptr );
2046 
2047  QList<QgsAbstractGeometry *> geomV2List;
2048  QList<QgsGeometry>::const_iterator it = geometryList.constBegin();
2049  for ( ; it != geometryList.constEnd(); ++it )
2050  {
2051  if ( !( ( *it ).isNull() ) )
2052  {
2053  geomV2List.append( ( *it ).geometry() );
2054  }
2055  }
2056 
2057  return geos.polygonize( geomV2List );
2058 }
2059 
2061 {
2063  {
2064  return;
2065  }
2066 
2067  QgsAbstractGeometry *straightGeom = d->geometry->segmentize();
2068  detach( false );
2069 
2070  d->geometry = straightGeom;
2071 }
2072 
2074 {
2075  if ( !d->geometry )
2076  {
2077  return false;
2078  }
2079 
2080  return d->geometry->hasCurvedSegments();
2081 }
2082 
2084 {
2085  if ( !d->geometry )
2086  {
2087  return 1;
2088  }
2089 
2090  detach();
2091  d->geometry->transform( ct );
2092  return 0;
2093 }
2094 
2095 int QgsGeometry::transform( const QTransform &ct )
2096 {
2097  if ( !d->geometry )
2098  {
2099  return 1;
2100  }
2101 
2102  detach();
2103  d->geometry->transform( ct );
2104  return 0;
2105 }
2106 
2108 {
2109  if ( d->geometry )
2110  {
2111  detach();
2112  d->geometry->transform( mtp.transform() );
2113  }
2114 }
2115 
2117 {
2118  if ( !d->geometry || rectangle.isNull() || rectangle.isEmpty() )
2119  {
2120  return QgsGeometry();
2121  }
2122 
2123  QgsGeos geos( d->geometry );
2124  QgsAbstractGeometry *resultGeom = geos.clip( rectangle );
2125  return QgsGeometry( resultGeom );
2126 }
2127 
2128 void QgsGeometry::draw( QPainter &p ) const
2129 {
2130  if ( d->geometry )
2131  {
2132  d->geometry->draw( p );
2133  }
2134 }
2135 
2136 static bool vertexIndexInfo( const QgsAbstractGeometry *g, int vertexIndex, int &partIndex, int &ringIndex, int &vertex )
2137 {
2138  if ( vertexIndex < 0 )
2139  return false; // clearly something wrong
2140 
2141  if ( const QgsGeometryCollection *geomCollection = dynamic_cast<const QgsGeometryCollection *>( g ) )
2142  {
2143  partIndex = 0;
2144  int offset = 0;
2145  for ( int i = 0; i < geomCollection->numGeometries(); ++i )
2146  {
2147  const QgsAbstractGeometry *part = geomCollection->geometryN( i );
2148 
2149  // count total number of vertices in the part
2150  int numPoints = 0;
2151  for ( int k = 0; k < part->ringCount(); ++k )
2152  numPoints += part->vertexCount( 0, k );
2153 
2154  if ( vertexIndex < numPoints )
2155  {
2156  int nothing;
2157  return vertexIndexInfo( part, vertexIndex, nothing, ringIndex, vertex ); // set ring_index + index
2158  }
2159  vertexIndex -= numPoints;
2160  offset += numPoints;
2161  partIndex++;
2162  }
2163  }
2164  else if ( const QgsCurvePolygon *curvePolygon = dynamic_cast<const QgsCurvePolygon *>( g ) )
2165  {
2166  const QgsCurve *ring = curvePolygon->exteriorRing();
2167  if ( vertexIndex < ring->numPoints() )
2168  {
2169  partIndex = 0;
2170  ringIndex = 0;
2171  vertex = vertexIndex;
2172  return true;
2173  }
2174  vertexIndex -= ring->numPoints();
2175  ringIndex = 1;
2176  for ( int i = 0; i < curvePolygon->numInteriorRings(); ++i )
2177  {
2178  const QgsCurve *ring = curvePolygon->interiorRing( i );
2179  if ( vertexIndex < ring->numPoints() )
2180  {
2181  partIndex = 0;
2182  vertex = vertexIndex;
2183  return true;
2184  }
2185  vertexIndex -= ring->numPoints();
2186  ringIndex += 1;
2187  }
2188  }
2189  else if ( const QgsCurve *curve = dynamic_cast<const QgsCurve *>( g ) )
2190  {
2191  if ( vertexIndex < curve->numPoints() )
2192  {
2193  partIndex = 0;
2194  ringIndex = 0;
2195  vertex = vertexIndex;
2196  return true;
2197  }
2198  }
2199  else if ( dynamic_cast<const QgsPoint *>( g ) )
2200  {
2201  if ( vertexIndex == 0 )
2202  {
2203  partIndex = 0;
2204  ringIndex = 0;
2205  vertex = 0;
2206  return true;
2207  }
2208  }
2209 
2210  return false;
2211 }
2212 
2214 {
2215  if ( !d->geometry )
2216  {
2217  return false;
2218  }
2219 
2220  id.type = QgsVertexId::SegmentVertex;
2221 
2222  bool res = vertexIndexInfo( d->geometry, nr, id.part, id.ring, id.vertex );
2223  if ( !res )
2224  return false;
2225 
2226  // now let's find out if it is a straight or circular segment
2227  const QgsAbstractGeometry *g = d->geometry;
2228  if ( const QgsGeometryCollection *geomCollection = dynamic_cast<const QgsGeometryCollection *>( g ) )
2229  {
2230  g = geomCollection->geometryN( id.part );
2231  }
2232 
2233  if ( const QgsCurvePolygon *curvePolygon = dynamic_cast<const QgsCurvePolygon *>( g ) )
2234  {
2235  g = id.ring == 0 ? curvePolygon->exteriorRing() : curvePolygon->interiorRing( id.ring - 1 );
2236  }
2237 
2238  if ( const QgsCurve *curve = dynamic_cast<const QgsCurve *>( g ) )
2239  {
2240  QgsPoint p;
2241  res = curve->pointAt( id.vertex, p, id.type );
2242  if ( !res )
2243  return false;
2244  }
2245 
2246  return true;
2247 }
2248 
2250 {
2251  if ( !d->geometry )
2252  {
2253  return -1;
2254  }
2255 
2257 
2258  int vertexCount = 0;
2259  for ( int part = 0; part < coords.size(); ++part )
2260  {
2261  const QgsRingSequence &featureCoords = coords.at( part );
2262  for ( int ring = 0; ring < featureCoords.size(); ++ring )
2263  {
2264  const QgsPointSequence &ringCoords = featureCoords.at( ring );
2265  for ( int vertex = 0; vertex < ringCoords.size(); ++vertex )
2266  {
2267  if ( vertex == id.vertex && ring == id.ring && part == id.part )
2268  {
2269  return vertexCount;
2270  }
2271  ++vertexCount;
2272  }
2273  }
2274  }
2275  return -1;
2276 }
2277 
2278 void QgsGeometry::convertPointList( const QList<QgsPointXY> &input, QgsPointSequence &output )
2279 {
2280  output.clear();
2281  QList<QgsPointXY>::const_iterator it = input.constBegin();
2282  for ( ; it != input.constEnd(); ++it )
2283  {
2284  output.append( QgsPoint( it->x(), it->y() ) );
2285  }
2286 }
2287 
2288 void QgsGeometry::convertPointList( const QgsPointSequence &input, QList<QgsPointXY> &output )
2289 {
2290  output.clear();
2291  QgsPointSequence::const_iterator it = input.constBegin();
2292  for ( ; it != input.constEnd(); ++it )
2293  {
2294  output.append( QgsPointXY( it->x(), it->y() ) );
2295  }
2296 }
2297 
2298 QgsGeometry::operator bool() const
2299 {
2300  return d->geometry;
2301 }
2302 
2303 void QgsGeometry::convertToPolyline( const QgsPointSequence &input, QgsPolyline &output )
2304 {
2305  output.clear();
2306  output.resize( input.size() );
2307 
2308  for ( int i = 0; i < input.size(); ++i )
2309  {
2310  const QgsPoint &pt = input.at( i );
2311  output[i].setX( pt.x() );
2312  output[i].setY( pt.y() );
2313  }
2314 }
2315 
2316 void QgsGeometry::convertPolygon( const QgsPolygonV2 &input, QgsPolygon &output )
2317 {
2318  output.clear();
2319  QgsCoordinateSequence coords = input.coordinateSequence();
2320  if ( coords.size() < 1 )
2321  {
2322  return;
2323  }
2324  const QgsRingSequence &rings = coords[0];
2325  output.resize( rings.size() );
2326  for ( int i = 0; i < rings.size(); ++i )
2327  {
2328  convertToPolyline( rings[i], output[i] );
2329  }
2330 }
2331 
2332 GEOSContextHandle_t QgsGeometry::getGEOSHandler()
2333 {
2334  return QgsGeos::getGEOSHandler();
2335 }
2336 
2338 {
2339  return QgsGeometry( new QgsPoint( point.x(), point.y() ) );
2340 }
2341 
2342 QgsGeometry QgsGeometry::fromQPolygonF( const QPolygonF &polygon )
2343 {
2344  if ( polygon.isClosed() )
2345  {
2347  }
2348  else
2349  {
2351  }
2352 }
2353 
2355 {
2356  QgsPolygon result;
2357  result << createPolylineFromQPolygonF( polygon );
2358  return result;
2359 }
2360 
2362 {
2363  QgsPolyline result;
2364  QPolygonF::const_iterator it = polygon.constBegin();
2365  for ( ; it != polygon.constEnd(); ++it )
2366  {
2367  result.append( QgsPointXY( *it ) );
2368  }
2369  return result;
2370 }
2371 
2372 bool QgsGeometry::compare( const QgsPolyline &p1, const QgsPolyline &p2, double epsilon )
2373 {
2374  if ( p1.count() != p2.count() )
2375  return false;
2376 
2377  for ( int i = 0; i < p1.count(); ++i )
2378  {
2379  if ( !p1.at( i ).compare( p2.at( i ), epsilon ) )
2380  return false;
2381  }
2382  return true;
2383 }
2384 
2385 bool QgsGeometry::compare( const QgsPolygon &p1, const QgsPolygon &p2, double epsilon )
2386 {
2387  if ( p1.count() != p2.count() )
2388  return false;
2389 
2390  for ( int i = 0; i < p1.count(); ++i )
2391  {
2392  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
2393  return false;
2394  }
2395  return true;
2396 }
2397 
2398 
2399 bool QgsGeometry::compare( const QgsMultiPolygon &p1, const QgsMultiPolygon &p2, double epsilon )
2400 {
2401  if ( p1.count() != p2.count() )
2402  return false;
2403 
2404  for ( int i = 0; i < p1.count(); ++i )
2405  {
2406  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
2407  return false;
2408  }
2409  return true;
2410 }
2411 
2412 QgsGeometry QgsGeometry::smooth( const unsigned int iterations, const double offset, double minimumDistance, double maxAngle ) const
2413 {
2414  if ( d->geometry->isEmpty() )
2415  return QgsGeometry();
2416 
2417  QgsGeometry geom = *this;
2419  geom = QgsGeometry( d->geometry->segmentize() );
2420 
2421  switch ( QgsWkbTypes::flatType( geom.wkbType() ) )
2422  {
2423  case QgsWkbTypes::Point:
2425  //can't smooth a point based geometry
2426  return geom;
2427 
2429  {
2430  QgsLineString *lineString = static_cast< QgsLineString * >( d->geometry );
2431  return QgsGeometry( smoothLine( *lineString, iterations, offset, minimumDistance, maxAngle ) );
2432  }
2433 
2435  {
2436  QgsMultiLineString *multiLine = static_cast< QgsMultiLineString * >( d->geometry );
2437 
2438  QgsMultiLineString *resultMultiline = new QgsMultiLineString();
2439  for ( int i = 0; i < multiLine->numGeometries(); ++i )
2440  {
2441  resultMultiline->addGeometry( smoothLine( *( static_cast< QgsLineString * >( multiLine->geometryN( i ) ) ), iterations, offset, minimumDistance, maxAngle ) );
2442  }
2443  return QgsGeometry( resultMultiline );
2444  }
2445 
2446  case QgsWkbTypes::Polygon:
2447  {
2448  QgsPolygonV2 *poly = static_cast< QgsPolygonV2 * >( d->geometry );
2449  return QgsGeometry( smoothPolygon( *poly, iterations, offset, minimumDistance, maxAngle ) );
2450  }
2451 
2453  {
2454  QgsMultiPolygonV2 *multiPoly = static_cast< QgsMultiPolygonV2 * >( d->geometry );
2455 
2456  QgsMultiPolygonV2 *resultMultiPoly = new QgsMultiPolygonV2();
2457  for ( int i = 0; i < multiPoly->numGeometries(); ++i )
2458  {
2459  resultMultiPoly->addGeometry( smoothPolygon( *( static_cast< QgsPolygonV2 * >( multiPoly->geometryN( i ) ) ), iterations, offset, minimumDistance, maxAngle ) );
2460  }
2461  return QgsGeometry( resultMultiPoly );
2462  }
2463 
2464  case QgsWkbTypes::Unknown:
2465  default:
2466  return QgsGeometry( *this );
2467  }
2468 }
2469 
2470 inline QgsPoint interpolatePointOnLine( const QgsPoint &p1, const QgsPoint &p2, const double offset )
2471 {
2472  double deltaX = p2.x() - p1.x();
2473  double deltaY = p2.y() - p1.y();
2474  return QgsPoint( p1.x() + deltaX * offset, p1.y() + deltaY * offset );
2475 }
2476 
2477 QgsLineString *smoothCurve( const QgsLineString &line, const unsigned int iterations,
2478  const double offset, double squareDistThreshold, double maxAngleRads,
2479  bool isRing )
2480 {
2481  std::unique_ptr< QgsLineString > result( new QgsLineString( line ) );
2482  for ( unsigned int iteration = 0; iteration < iterations; ++iteration )
2483  {
2484  QgsPointSequence outputLine;
2485  outputLine.reserve( 2 * ( result->numPoints() - 1 ) );
2486  bool skipFirst = false;
2487  bool skipLast = false;
2488  if ( isRing )
2489  {
2490  QgsPoint p1 = result->pointN( result->numPoints() - 2 );
2491  QgsPoint p2 = result->pointN( 0 );
2492  QgsPoint p3 = result->pointN( 1 );
2493  double angle = QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(),
2494  p3.x(), p3.y() );
2495  angle = qAbs( M_PI - angle );
2496  skipFirst = angle > maxAngleRads;
2497  }
2498  for ( int i = 0; i < result->numPoints() - 1; i++ )
2499  {
2500  QgsPoint p1 = result->pointN( i );
2501  QgsPoint p2 = result->pointN( i + 1 );
2502 
2503  double angle = M_PI;
2504  if ( i == 0 && isRing )
2505  {
2506  QgsPoint p3 = result->pointN( result->numPoints() - 2 );
2507  angle = QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(),
2508  p3.x(), p3.y() );
2509  }
2510  else if ( i < result->numPoints() - 2 )
2511  {
2512  QgsPoint p3 = result->pointN( i + 2 );
2513  angle = QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(),
2514  p3.x(), p3.y() );
2515  }
2516  else if ( i == result->numPoints() - 2 && isRing )
2517  {
2518  QgsPoint p3 = result->pointN( 1 );
2519  angle = QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(),
2520  p3.x(), p3.y() );
2521  }
2522 
2523  skipLast = angle < M_PI - maxAngleRads || angle > M_PI + maxAngleRads;
2524 
2525  // don't apply distance threshold to first or last segment
2526  if ( i == 0 || i >= result->numPoints() - 2
2527  || QgsGeometryUtils::sqrDistance2D( p1, p2 ) > squareDistThreshold )
2528  {
2529  if ( !isRing )
2530  {
2531  if ( !skipFirst )
2532  outputLine << ( i == 0 ? result->pointN( i ) : interpolatePointOnLine( p1, p2, offset ) );
2533  if ( !skipLast )
2534  outputLine << ( i == result->numPoints() - 2 ? result->pointN( i + 1 ) : interpolatePointOnLine( p1, p2, 1.0 - offset ) );
2535  else
2536  outputLine << p2;
2537  }
2538  else
2539  {
2540  // ring
2541  if ( !skipFirst )
2542  outputLine << interpolatePointOnLine( p1, p2, offset );
2543  else if ( i == 0 )
2544  outputLine << p1;
2545  if ( !skipLast )
2546  outputLine << interpolatePointOnLine( p1, p2, 1.0 - offset );
2547  else
2548  outputLine << p2;
2549  }
2550  }
2551  skipFirst = skipLast;
2552  }
2553 
2554  if ( isRing && outputLine.at( 0 ) != outputLine.at( outputLine.count() - 1 ) )
2555  outputLine << outputLine.at( 0 );
2556 
2557  result->setPoints( outputLine );
2558  }
2559  return result.release();
2560 }
2561 
2562 QgsLineString *QgsGeometry::smoothLine( const QgsLineString &line, const unsigned int iterations, const double offset, double minimumDistance, double maxAngle ) const
2563 {
2564  double maxAngleRads = maxAngle * M_PI / 180.0;
2565  double squareDistThreshold = minimumDistance > 0 ? minimumDistance * minimumDistance : -1;
2566  return smoothCurve( line, iterations, offset, squareDistThreshold, maxAngleRads, false );
2567 }
2568 
2569 QgsPolygonV2 *QgsGeometry::smoothPolygon( const QgsPolygonV2 &polygon, const unsigned int iterations, const double offset, double minimumDistance, double maxAngle ) const
2570 {
2571  double maxAngleRads = maxAngle * M_PI / 180.0;
2572  double squareDistThreshold = minimumDistance > 0 ? minimumDistance * minimumDistance : -1;
2573  std::unique_ptr< QgsPolygonV2 > resultPoly( new QgsPolygonV2 );
2574 
2575  resultPoly->setExteriorRing( smoothCurve( *( static_cast< const QgsLineString *>( polygon.exteriorRing() ) ), iterations, offset,
2576  squareDistThreshold, maxAngleRads, true ) );
2577 
2578  for ( int i = 0; i < polygon.numInteriorRings(); ++i )
2579  {
2580  resultPoly->addInteriorRing( smoothCurve( *( static_cast< const QgsLineString *>( polygon.interiorRing( i ) ) ), iterations, offset,
2581  squareDistThreshold, maxAngleRads, true ) );
2582  }
2583  return resultPoly.release();
2584 }
2585 
2586 QgsGeometry QgsGeometry::convertToPoint( bool destMultipart ) const
2587 {
2588  switch ( type() )
2589  {
2591  {
2592  bool srcIsMultipart = isMultipart();
2593 
2594  if ( ( destMultipart && srcIsMultipart ) ||
2595  ( !destMultipart && !srcIsMultipart ) )
2596  {
2597  // return a copy of the same geom
2598  return QgsGeometry( *this );
2599  }
2600  if ( destMultipart )
2601  {
2602  // layer is multipart => make a multipoint with a single point
2603  return fromMultiPoint( QgsMultiPoint() << asPoint() );
2604  }
2605  else
2606  {
2607  // destination is singlepart => make a single part if possible
2608  QgsMultiPoint multiPoint = asMultiPoint();
2609  if ( multiPoint.count() == 1 )
2610  {
2611  return fromPoint( multiPoint[0] );
2612  }
2613  }
2614  return QgsGeometry();
2615  }
2616 
2618  {
2619  // only possible if destination is multipart
2620  if ( !destMultipart )
2621  return QgsGeometry();
2622 
2623  // input geometry is multipart
2624  if ( isMultipart() )
2625  {
2626  QgsMultiPolyline multiLine = asMultiPolyline();
2627  QgsMultiPoint multiPoint;
2628  for ( QgsMultiPolyline::const_iterator multiLineIt = multiLine.constBegin(); multiLineIt != multiLine.constEnd(); ++multiLineIt )
2629  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2630  multiPoint << *lineIt;
2631  return fromMultiPoint( multiPoint );
2632  }
2633  // input geometry is not multipart: copy directly the line into a multipoint
2634  else
2635  {
2636  QgsPolyline line = asPolyline();
2637  if ( !line.isEmpty() )
2638  return fromMultiPoint( line );
2639  }
2640  return QgsGeometry();
2641  }
2642 
2644  {
2645  // can only transform if destination is multipoint
2646  if ( !destMultipart )
2647  return QgsGeometry();
2648 
2649  // input geometry is multipart: make a multipoint from multipolygon
2650  if ( isMultipart() )
2651  {
2652  QgsMultiPolygon multiPolygon = asMultiPolygon();
2653  QgsMultiPoint multiPoint;
2654  for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
2655  for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
2656  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2657  multiPoint << *lineIt;
2658  return fromMultiPoint( multiPoint );
2659  }
2660  // input geometry is not multipart: make a multipoint from polygon
2661  else
2662  {
2663  QgsPolygon polygon = asPolygon();
2664  QgsMultiPoint multiPoint;
2665  for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
2666  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2667  multiPoint << *lineIt;
2668  return fromMultiPoint( multiPoint );
2669  }
2670  }
2671 
2672  default:
2673  return QgsGeometry();
2674  }
2675 }
2676 
2677 QgsGeometry QgsGeometry::convertToLine( bool destMultipart ) const
2678 {
2679  switch ( type() )
2680  {
2682  {
2683  if ( !isMultipart() )
2684  return QgsGeometry();
2685 
2686  QgsMultiPoint multiPoint = asMultiPoint();
2687  if ( multiPoint.count() < 2 )
2688  return QgsGeometry();
2689 
2690  if ( destMultipart )
2691  return fromMultiPolyline( QgsMultiPolyline() << multiPoint );
2692  else
2693  return fromPolyline( multiPoint );
2694  }
2695 
2697  {
2698  bool srcIsMultipart = isMultipart();
2699 
2700  if ( ( destMultipart && srcIsMultipart ) ||
2701  ( !destMultipart && ! srcIsMultipart ) )
2702  {
2703  // return a copy of the same geom
2704  return QgsGeometry( *this );
2705  }
2706  if ( destMultipart )
2707  {
2708  // destination is multipart => makes a multipoint with a single line
2709  QgsPolyline line = asPolyline();
2710  if ( !line.isEmpty() )
2711  return fromMultiPolyline( QgsMultiPolyline() << line );
2712  }
2713  else
2714  {
2715  // destination is singlepart => make a single part if possible
2716  QgsMultiPolyline multiLine = asMultiPolyline();
2717  if ( multiLine.count() == 1 )
2718  return fromPolyline( multiLine[0] );
2719  }
2720  return QgsGeometry();
2721  }
2722 
2724  {
2725  // input geometry is multipolygon
2726  if ( isMultipart() )
2727  {
2728  QgsMultiPolygon multiPolygon = asMultiPolygon();
2729  QgsMultiPolyline multiLine;
2730  for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
2731  for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
2732  multiLine << *multiLineIt;
2733 
2734  if ( destMultipart )
2735  {
2736  // destination is multipart
2737  return fromMultiPolyline( multiLine );
2738  }
2739  else if ( multiLine.count() == 1 )
2740  {
2741  // destination is singlepart => make a single part if possible
2742  return fromPolyline( multiLine[0] );
2743  }
2744  }
2745  // input geometry is single polygon
2746  else
2747  {
2748  QgsPolygon polygon = asPolygon();
2749  // if polygon has rings
2750  if ( polygon.count() > 1 )
2751  {
2752  // cannot fit a polygon with rings in a single line layer
2753  // TODO: would it be better to remove rings?
2754  if ( destMultipart )
2755  {
2756  QgsPolygon polygon = asPolygon();
2757  QgsMultiPolyline multiLine;
2758  for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
2759  multiLine << *multiLineIt;
2760  return fromMultiPolyline( multiLine );
2761  }
2762  }
2763  // no rings
2764  else if ( polygon.count() == 1 )
2765  {
2766  if ( destMultipart )
2767  {
2768  return fromMultiPolyline( polygon );
2769  }
2770  else
2771  {
2772  return fromPolyline( polygon[0] );
2773  }
2774  }
2775  }
2776  return QgsGeometry();
2777  }
2778 
2779  default:
2780  return QgsGeometry();
2781  }
2782 }
2783 
2784 QgsGeometry QgsGeometry::convertToPolygon( bool destMultipart ) const
2785 {
2786  switch ( type() )
2787  {
2789  {
2790  if ( !isMultipart() )
2791  return QgsGeometry();
2792 
2793  QgsMultiPoint multiPoint = asMultiPoint();
2794  if ( multiPoint.count() < 3 )
2795  return QgsGeometry();
2796 
2797  if ( multiPoint.last() != multiPoint.first() )
2798  multiPoint << multiPoint.first();
2799 
2800  QgsPolygon polygon = QgsPolygon() << multiPoint;
2801  if ( destMultipart )
2802  return fromMultiPolygon( QgsMultiPolygon() << polygon );
2803  else
2804  return fromPolygon( polygon );
2805  }
2806 
2808  {
2809  // input geometry is multiline
2810  if ( isMultipart() )
2811  {
2812  QgsMultiPolyline multiLine = asMultiPolyline();
2813  QgsMultiPolygon multiPolygon;
2814  for ( QgsMultiPolyline::iterator multiLineIt = multiLine.begin(); multiLineIt != multiLine.end(); ++multiLineIt )
2815  {
2816  // do not create polygon for a 1 segment line
2817  if ( ( *multiLineIt ).count() < 3 )
2818  return QgsGeometry();
2819  if ( ( *multiLineIt ).count() == 3 && ( *multiLineIt ).first() == ( *multiLineIt ).last() )
2820  return QgsGeometry();
2821 
2822  // add closing node
2823  if ( ( *multiLineIt ).first() != ( *multiLineIt ).last() )
2824  *multiLineIt << ( *multiLineIt ).first();
2825  multiPolygon << ( QgsPolygon() << *multiLineIt );
2826  }
2827  // check that polygons were inserted
2828  if ( !multiPolygon.isEmpty() )
2829  {
2830  if ( destMultipart )
2831  {
2832  return fromMultiPolygon( multiPolygon );
2833  }
2834  else if ( multiPolygon.count() == 1 )
2835  {
2836  // destination is singlepart => make a single part if possible
2837  return fromPolygon( multiPolygon[0] );
2838  }
2839  }
2840  }
2841  // input geometry is single line
2842  else
2843  {
2844  QgsPolyline line = asPolyline();
2845 
2846  // do not create polygon for a 1 segment line
2847  if ( line.count() < 3 )
2848  return QgsGeometry();
2849  if ( line.count() == 3 && line.first() == line.last() )
2850  return QgsGeometry();
2851 
2852  // add closing node
2853  if ( line.first() != line.last() )
2854  line << line.first();
2855 
2856  // destination is multipart
2857  if ( destMultipart )
2858  {
2859  return fromMultiPolygon( QgsMultiPolygon() << ( QgsPolygon() << line ) );
2860  }
2861  else
2862  {
2863  return fromPolygon( QgsPolygon() << line );
2864  }
2865  }
2866  return QgsGeometry();
2867  }
2868 
2870  {
2871  bool srcIsMultipart = isMultipart();
2872 
2873  if ( ( destMultipart && srcIsMultipart ) ||
2874  ( !destMultipart && ! srcIsMultipart ) )
2875  {
2876  // return a copy of the same geom
2877  return QgsGeometry( *this );
2878  }
2879  if ( destMultipart )
2880  {
2881  // destination is multipart => makes a multipoint with a single polygon
2882  QgsPolygon polygon = asPolygon();
2883  if ( !polygon.isEmpty() )
2884  return fromMultiPolygon( QgsMultiPolygon() << polygon );
2885  }
2886  else
2887  {
2888  QgsMultiPolygon multiPolygon = asMultiPolygon();
2889  if ( multiPolygon.count() == 1 )
2890  {
2891  // destination is singlepart => make a single part if possible
2892  return fromPolygon( multiPolygon[0] );
2893  }
2894  }
2895  return QgsGeometry();
2896  }
2897 
2898  default:
2899  return QgsGeometry();
2900  }
2901 }
2902 
2904 {
2905  return new QgsGeos( geometry );
2906 }
2907 
2908 QDataStream &operator<<( QDataStream &out, const QgsGeometry &geometry )
2909 {
2910  out << geometry.exportToWkb();
2911  return out;
2912 }
2913 
2914 QDataStream &operator>>( QDataStream &in, QgsGeometry &geometry )
2915 {
2916  QByteArray byteArray;
2917  in >> byteArray;
2918  if ( byteArray.isEmpty() )
2919  {
2920  geometry.setGeometry( nullptr );
2921  return in;
2922  }
2923 
2924  geometry.fromWkb( byteArray );
2925  return in;
2926 }
QgsPolygon asPolygon() const
Return contents of the geometry as a polygon if wkbType is WKBPolygon, otherwise an empty list...
bool crosses(const QgsAbstractGeometry &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:401
const QgsCurve * interiorRing(int i) const
virtual QString asWkt(int precision=17) const =0
Returns a WKT representation of the geometry.
QgsMultiPolyline asMultiPolyline() const
Return contents of the geometry as a multi linestring if wkbType is WKBMultiLineString, otherwise an empty list.
A rectangle specified with double values.
Definition: qgsrectangle.h:38
bool intersects(const QgsAbstractGeometry &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:391
double y
Definition: qgspoint.h:41
QgsAbstractGeometry * offsetCurve(double distance, int segments, int joinStyle, double mitreLimit, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1854
virtual bool isEmpty() const
Returns true if the geometry is empty.
QgsGeometry combine(const QgsGeometry &geometry) const
Returns a geometry representing all the points in this geometry and other (a union geometry operation...
static int addPart(QgsAbstractGeometry *geom, QgsAbstractGeometry *part)
Adds part to multi type geometry (taking ownership)
void setPoints(const QgsPointSequence &points)
Resets the line string to match the specified list of points.
QgsGeometry mergeLines(QString *errorMsg=nullptr) const
Merges any connected lines in a LineString/MultiLineString geometry and converts them to single line ...
Definition: qgsgeos.cpp:2005
void points(QgsPointSequence &pt) const override
Returns a list of points within the curve.
static Type multiType(Type type)
Returns the multi type for a WKB type.
Definition: qgswkbtypes.h:293
virtual bool deleteVertex(QgsVertexId position)=0
Deletes a vertex within the geometry.
QgsAbstractGeometry * symDifference(const QgsAbstractGeometry &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:361
int makeDifferenceInPlace(const QgsGeometry &other)
Changes this geometry such that it does not intersect the other geometry.
static QgsGeometry fromPolyline(const QgsPolyline &polyline)
Creates a new geometry from a QgsPolyline object.
bool intersects(const QgsRectangle &r) const
Test for intersection with a rectangle (uses GEOS)
QDataStream & operator<<(QDataStream &out, const QgsGeometry &geometry)
Writes the geometry to stream out. QGIS version compatibility is not guaranteed.
int addPart(const QList< QgsPointXY > &points, QgsWkbTypes::GeometryType geomType=QgsWkbTypes::UnknownGeometry)
Adds a new part to a the geometry.
QgsGeometry removeInteriorRings(double minimumAllowedArea=-1) const
Removes the interior rings from a (multi)polygon geometry.
bool isMultipart() const
Returns true if WKB of the geometry is of WKBMulti* type.
virtual QByteArray asWkb() const =0
Returns a WKB representation of the geometry.
QgsAbstractGeometry * intersection(const QgsAbstractGeometry &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:182
static bool verticesAtDistance(const QgsAbstractGeometry &geometry, double distance, QgsVertexId &previousVertex, QgsVertexId &nextVertex)
Retrieves the vertices which are before and after the interpolated point at a specified distance alon...
bool isNull() const
Returns true if the geometry is null (ie, contains no underlying geometry accessible via geometry() )...
double distance(const QgsGeometry &geom) const
Returns the minimum distance between this geometry and another geometry, using GEOS.
static double lineAngle(double x1, double y1, double x2, double y2)
Calculates the direction of line joining two points in radians, clockwise from the north direction...
bool isValid() const
Returns true if the vertex id is valid.
bool within(const QgsGeometry &geometry) const
Test for if geometry is within another (uses GEOS)
static bool isMultiType(Type type)
Returns true if the WKB type is a multi type.
Definition: qgswkbtypes.h:550
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer&#39;s length...
virtual bool insertVertex(QgsVertexId position, const QgsPoint &vertex)=0
Inserts a vertex into the geometry.
double angleAtVertex(int vertex) const
Returns the bisector angle for this geometry at the specified vertex.
static double averageAngle(double x1, double y1, double x2, double y2, double x3, double y3)
Angle between two linear segments.
QgsGeometry poleOfInaccessibility(double precision, double *distanceFromBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...
static bool compare(const QgsPolyline &p1, const QgsPolyline &p2, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compares two polylines for equality within a specified tolerance.
double ANALYSIS_EXPORT leftOf(QgsPoint *thepoint, QgsPoint *p1, QgsPoint *p2)
Returns whether &#39;thepoint&#39; is left or right of the line from &#39;p1&#39; to &#39;p2&#39;. Negativ values mean left a...
Definition: MathUtils.cc:310
static double angleBetweenThreePoints(double x1, double y1, double x2, double y2, double x3, double y3)
Calculates the angle between the lines AB and BC, where AB and BC described by points a...
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QgsGeometry subdivide(int maxNodes=256) const
Subdivides the geometry.
double y
Definition: qgspointxy.h:47
QgsGeometry shortestLine(const QgsGeometry &other, QString *errorMsg=nullptr) const
Returns the shortest line joining this geometry to the other geometry.
Definition: qgsgeos.cpp:2059
double area(QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:489
A class to represent a 2D point.
Definition: qgspointxy.h:42
QgsGeometry orthogonalize(double tolerance=1.0E-8, int maxIterations=1000, double angleThreshold=15.0) const
Attempts to orthogonalize a line or polygon geometry by shifting vertices to make the geometries angl...
virtual double closestSegment(const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, bool *leftOf, double epsilon) const =0
Searches for the closest segment of the geometry to a given point.
void validateGeometry(QList< QgsGeometry::Error > &errors, ValidationMethod method=ValidatorQgisInternal)
Validate geometry and produce a list of geometry errors.
QgsAbstractGeometry * buffer(double distance, int segments, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1439
bool moveVertex(double x, double y, int atVertex)
Moves the vertex at the given position number and item (first number is index 0) to the given coordin...
Multi line string geometry collection.
QgsGeometry interpolate(double distance) const
Return interpolated point on line at distance.
Curve polygon geometry type.
bool overlaps(const QgsGeometry &geometry) const
Test for if geometry overlaps another (uses GEOS)
double length(QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:506
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:96
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
QgsGeometry centroid() const
Returns the center of mass of a geometry.
QgsGeometry()
Constructor.
Definition: qgsgeometry.cpp:56
bool isValid(QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1594
int splitGeometry(const QgsLineString &splitLine, QList< QgsAbstractGeometry *> &newGeometries, bool topological, QgsPointSequence &topologyTestPoints, QString *errorMsg=nullptr) const override
Splits this geometry according to a given line.
Definition: qgsgeos.cpp:522
virtual QgsAbstractGeometry * boundary() const =0
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
QgsGeometry makeValid()
Attempts to make an invalid geometry valid without losing vertices.
Multi point geometry collection.
Definition: qgsmultipoint.h:28
bool within(const QgsAbstractGeometry &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:406
QgsGeometry intersection(const QgsGeometry &geometry) const
Returns a geometry representing the points shared by this geometry and other.
static QgsPoint closestVertex(const QgsAbstractGeometry &geom, const QgsPoint &pt, QgsVertexId &id)
Returns the closest vertex to a geometry for a specified point.
double distanceToVertex(int vertex) const
Returns the distance along this geometry from its first vertex to the specified vertex.
EndCapStyle
End cap styles for buffers.
Definition: qgsgeometry.h:581
virtual bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const =0
Returns next vertex id and coordinates.
QgsGeometry closestPoint(const QgsGeometry &other, QString *errorMsg=nullptr) const
Returns the closest point on the geometry to the other geometry.
Definition: qgsgeos.cpp:2024
static QgsAbstractGeometry * avoidIntersections(const QgsAbstractGeometry &geom, const QList< QgsVectorLayer *> &avoidIntersectionsLayers, QHash< QgsVectorLayer *, QSet< QgsFeatureId > > ignoreFeatures=(QHash< QgsVectorLayer *, QSet< QgsFeatureId > >()))
Alters a geometry so that it avoids intersections with features from all open vector layers...
double closestSegmentWithContext(const QgsPointXY &point, QgsPointXY &minDistPoint, int &afterVertex, double *leftOf=nullptr, double epsilon=DEFAULT_SEGMENT_EPSILON) const
Searches for the closest segment of geometry to the given point.
bool insertVertex(double x, double y, int beforeVertex)
Insert a new vertex before the given vertex index, ring and item (first number is index 0) If the req...
virtual QgsRectangle boundingBox() const =0
Returns the minimal bounding box for the geometry.
static QgsAbstractGeometry * fromMultiPolyline(const QgsMultiPolyline &multiline)
Construct geometry from a multipolyline.
QgsGeometry nearestPoint(const QgsGeometry &other) const
Returns the nearest point on this geometry to another geometry.
virtual void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform, bool transformZ=false)=0
Transforms the geometry using a coordinate transform.
bool isEqual(const QgsAbstractGeometry &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1608
QgsGeometry & operator=(QgsGeometry const &rhs)
Assignments will prompt a deep copy of the object.
Definition: qgsgeometry.cpp:78
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
static QgsPolyline createPolylineFromQPolygonF(const QPolygonF &polygon)
Creates a QgsPolyline from a QPolygonF.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cc:857
bool isGeosEqual(const QgsGeometry &) const
Compares the geometry with another geometry using GEOS.
static QgsAbstractGeometry * fromPolygon(const QgsPolygon &polygon)
Construct geometry from a polygon.
bool deleteRing(int ringNum, int partNum=0)
Delete a ring in polygon or multipolygon.
bool isGeosValid() const
Checks validity of the geometry using GEOS.
QgsGeometry offsetCurve(double distance, int segments, JoinStyle joinStyle, double mitreLimit) const
Returns an offset line at a given distance and side from an input line.
QgsPolyline asPolyline() const
Return contents of the geometry as a polyline if wkbType is WKBLineString, otherwise an empty list...
static QgsAbstractGeometry * fromMultiPolygon(const QgsMultiPolygon &multipoly)
Construct geometry from a multipolygon.
QVector< QgsPointXY > QgsPolyline
Polyline is represented as a vector of points.
Definition: qgsgeometry.h:48
static GEOSContextHandle_t getGEOSHandler()
Definition: qgsgeos.cpp:2714
static GEOSGeometry * asGeos(const QgsAbstractGeometry *geom, double precision=0)
Definition: qgsgeos.cpp:1218
int numPoints() const override
Returns the number of points in the curve.
QgsAbstractGeometry * singleSidedBuffer(double distance, int segments, int side, int joinStyle, double mitreLimit, QString *errorMsg=nullptr) const
Returns a single sided buffer for a geometry.
Definition: qgsgeos.cpp:1870
QgsPointXY closestVertex(const QgsPointXY &point, int &atVertex, int &beforeVertex, int &afterVertex, double &sqrDist) const
Returns the vertex closest to the given point, the corresponding vertex index, squared distance snap ...
QgsGeometry poleOfInaccessibility(double precision, double *distanceToBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...
bool deletePart(int partNum)
Delete part identified by the part number.
bool centroid(QgsPoint &pt, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1501
QgsMultiPoint asMultiPoint() const
Return contents of the geometry as a multi point if wkbType is WKBMultiPoint, otherwise an empty list...
QgsGeometry mergeLines() const
Merges any connected lines in a LineString/MultiLineString geometry and converts them to single line ...
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:35
Polygon geometry type.
Definition: qgspolygon.h:30
QgsPointXY transform(const QgsPointXY &p) const
Transform the point from map (world) coordinates to device coordinates.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
int numInteriorRings() const
static QgsAbstractGeometry * fromMultiPoint(const QgsMultiPoint &multipoint)
Construct geometry from a multipoint.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:66
QPointF toQPointF() const
Converts a point to a QPointF.
Definition: qgspointxy.cpp:40
static void convertPointList(const QList< QgsPointXY > &input, QgsPointSequence &output)
Upgrades a point list from QgsPointXY to QgsPointV2.
static bool deleteRing(QgsAbstractGeometry *geom, int ringNum, int partNum=0)
Deletes a ring from a geometry.
bool convertToSingleType()
Converts multi type geometry into single type geometry e.g.
bool equals(const QgsGeometry &geometry) const
Test for if geometry equals another (uses GEOS)
Utility class for identifying a unique vertex within a geometry.
QgsAbstractGeometry * geometry
Definition: qgsgeometry.cpp:53
QgsAbstractGeometry * subdivide(int maxNodes, QString *errorMsg=nullptr) const
Subdivides the geometry.
Definition: qgsgeos.cpp:312
bool isEmpty() const
Returns true if the rectangle is empty.
QByteArray exportToWkb() const
Export the geometry to WKB.
Geometry collection.
virtual int partCount() const override
Returns count of parts contained in the geometry.
QgsPoint interpolatePointOnLine(const QgsPoint &p1, const QgsPoint &p2, const double offset)
static QgsGeometry fromQPointF(QPointF point)
Construct geometry from a QPointF.
QgsLineString * smoothCurve(const QgsLineString &line, const unsigned int iterations, const double offset, double squareDistThreshold, double maxAngleRads, bool isRing)
QgsGeometry convexHull() const
Returns the smallest convex polygon that contains all the points in the geometry. ...
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:118
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Returns a copy of the geometry which has been densified by adding the specified number of extra nodes...
QList< QgsGeometry > asGeometryCollection() const
Return contents of the geometry as a list of geometries.
bool deleteVertex(int atVertex)
Deletes the vertex at the given position number and item (first number is index 0) Returns false if a...
double yAt(int index) const override
Returns the y-coordinate of the specified node in the line string.
void setY(double y)
Sets the y value of the point.
Definition: qgspointxy.h:108
static int addRing(QgsAbstractGeometry *geom, QgsCurve *ring)
Adds interior ring (taking ownership).
static GeometryType geometryType(Type type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:652
QgsAbstractGeometry * combine(const QgsAbstractGeometry &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:332
#define M_PI
QgsGeometry extendLine(double startDistance, double endDistance) const
Extends a (multi)line geometry by extrapolating out the start or end of the line by a specified dista...
double sqrDistToVertexAt(QgsPointXY &point SIP_IN, int atVertex) const
Returns the squared cartesian distance between the given point to the given vertex index (vertex at t...
QVector< QgsPolygon > QgsMultiPolygon
A collection of QgsPolygons that share a common collection of attributes.
Definition: qgsgeometry.h:76
void fromGeos(GEOSGeometry *geos)
Set the geometry, feeding in a geometry in GEOS format.
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
bool crosses(const QgsGeometry &geometry) const
Test for if geometry crosses another (uses GEOS)
QgsGeometry clipped(const QgsRectangle &rectangle)
Clips the geometry using the specified rectangle.
virtual QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
Definition: qgspoint.cpp:116
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
static QgsAbstractGeometry * geomFromWkt(const QString &text)
Construct geometry from a WKT string.
QgsAbstractGeometry * reshapeGeometry(const QgsLineString &reshapeWithLine, int *errorCode, QString *errorMsg=nullptr) const
Definition: qgsgeos.cpp:1897
QString exportToWkt(int precision=17) const
Exports the geometry to WKT.
QgsGeometry singleSidedBuffer(double distance, int segments, BufferSide side, JoinStyle joinStyle=JoinStyleRound, double mitreLimit=2.0) const
Returns a single sided buffer for a (multi)line geometry.
virtual double area() const
Returns the area of the geometry.
virtual int ringCount(int part=0) const =0
Returns the number of rings of which this geometry is built.
Abstract base class for curved geometry type.
Definition: qgscurve.h:34
QVector< QgsPolyline > QgsPolygon
Polygon: first item of the list is outer ring, inner rings (if any) start from second item...
Definition: qgsgeometry.h:55
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
bool touches(const QgsGeometry &geometry) const
Test for if geometry touch another (uses GEOS)
Abstract base class for all geometries.
virtual QgsCoordinateSequence coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
void convertToStraightSegment()
Converts the geometry to straight line segments, if it is a curved geometry type. ...
const QgsCurve * exteriorRing() const
Does vector analysis using the geos library and handles import, export, exception handling*...
Definition: qgsgeos.h:32
QgsAbstractGeometry * clip(const QgsRectangle &rectangle, QString *errorMsg=nullptr) const
Performs a fast, non-robust intersection between the geometry and a rectangle.
Definition: qgsgeos.cpp:192
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:36
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
QgsWkbTypes::GeometryType type() const
Returns type of the geometry as a QgsWkbTypes::GeometryType.
QgsGeometry delaunayTriangulation(double tolerance=0.0, bool edgesOnly=false, QString *errorMsg=nullptr) const
Returns the Delaunay triangulation for the vertices of the geometry.
Definition: qgsgeos.cpp:2205
QgsAbstractGeometry * difference(const QgsAbstractGeometry &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:187
int translate(double dx, double dy)
Translate this geometry by dx, dy.
double length() const
Returns the length of geometry using GEOS.
This class offers geometry processing methods.
void setX(double x)
Sets the x value of the point.
Definition: qgspointxy.h:100
double x
Definition: qgspointxy.h:46
virtual QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
static QgsGeometry fromPolygon(const QgsPolygon &polygon)
Creates a new geometry from a QgsPolygon.
QgsGeometry extrude(double x, double y)
Returns an extruded version of this geometry.
void draw(QPainter &p) const
Draws the geometry onto a QPainter.
virtual bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
int numGeometries() const
Returns the number of geometries within the collection.
void setX(double x)
Sets the point&#39;s x-coordinate.
Definition: qgspoint.h:180
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:106
QPolygonF asQPolygonF() const
Return contents of the geometry as a QPolygonF.
QVector< QgsPolyline > QgsMultiPolyline
A collection of QgsPolylines that share a common collection of attributes.
Definition: qgsgeometry.h:69
static QgsGeometry fromMultiPolygon(const QgsMultiPolygon &multipoly)
Creates a new geometry from a QgsMultiPolygon.
double interpolateAngle(double distance) const
Returns the angle parallel to the linestring or polygon boundary at the specified distance along the ...
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:91
static QgsAbstractGeometry * fromPolyline(const QgsPolyline &polyline)
Construct geometry from a polyline.
BufferSide
Side of line to buffer.
Definition: qgsgeometry.h:574
static QgsGeometry unaryUnion(const QList< QgsGeometry > &geometries)
Compute the unary union on a list of geometries.
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:136
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
int vertexNrFromVertexId(QgsVertexId i) const
Returns the vertex number corresponding to a vertex idd.
virtual QgsCoordinateSequence coordinateSequence() const =0
Retrieves the sequence of geometries, rings and nodes.
QgsGeometry simplify(double tolerance) const
Returns a simplified version of this geometry using a specified tolerance value.
static QgsPolygon createPolygonFromQPolygonF(const QPolygonF &polygon)
Creates a QgsPolygon from a QPolygonF.
bool touches(const QgsAbstractGeometry &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:396
static QgsAbstractGeometry * fromGeos(const GEOSGeometry *geos)
Create a geometry from a GEOSGeometry.
Definition: qgsgeos.cpp:1005
static double sqrDistance2D(const QgsPoint &pt1, const QgsPoint &pt2)
Returns the squared 2D distance between two points.
virtual void clear()=0
Clears the geometry, ie reset it to a null geometry.
QgsAbstractGeometry * convexHull(QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1577
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
QgsPointXY asPoint() const
Return contents of the geometry as a point if wkbType is WKBPoint, otherwise returns [0...
QgsPointXY vertexAt(int atVertex) const
Returns coordinates of a vertex.
static void validateGeometry(const QgsGeometry &geometry, QList< QgsGeometry::Error > &errors, QgsGeometry::ValidationMethod method=QgsGeometry::ValidatorQgisInternal)
Validate geometry and produce a list of geometry errors.
static GEOSContextHandle_t getGEOSHandler()
Return GEOS context handle.
static QgsGeometry fromMultiPoint(const QgsMultiPoint &multipoint)
Creates a new geometry from a QgsMultiPoint object.
bool requiresConversionToStraightSegments() const
Returns true if the geometry is a curved geometry type which requires conversion to display as straig...
void mapToPixel(const QgsMapToPixel &mtp)
Transforms the geometry from map units to pixels in place.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
static QgsAbstractGeometry * geomFromWkb(QgsConstWkbPtr &wkb)
Construct geometry from a WKB string.
virtual bool moveVertex(QgsVertexId position, const QgsPoint &newPos)=0
Moves a vertex within the geometry.
bool disjoint(const QgsAbstractGeometry &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:421
QString exportToGeoJSON(int precision=17) const
Exports the geometry to GeoJSON.
bool overlaps(const QgsAbstractGeometry &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:411
static bool isCurvedType(Type type)
Returns true if the WKB type is a curved type or can contain curved geometries.
Definition: qgswkbtypes.h:598
GEOSGeometry * exportToGeos(double precision=0) const
Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destr...
virtual void draw(QPainter &p) const =0
Draws the geometry using the specified QPainter.
QgsMultiPolygon asMultiPolygon() const
Return contents of the geometry as a multi polygon if wkbType is WKBMultiPolygon, otherwise an empty ...
double distance(const QgsAbstractGeometry &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:366
static void adjacentVertices(const QgsAbstractGeometry &geom, QgsVertexId atVertex, QgsVertexId &beforeVertex, QgsVertexId &afterVertex)
Returns vertices adjacent to a specified vertex within a geometry.
int splitGeometry(const QList< QgsPointXY > &splitLine, QList< QgsGeometry > &newGeometries, bool topological, QList< QgsPointXY > &topologyTestPoints)
Splits this geometry according to a given line.
bool vertexIdFromVertexNr(int nr, QgsVertexId &id) const
Calculates the vertex ID from a vertex number.
bool isSimple() const
Determines whether the geometry is simple (according to OGC definition), i.e.
void setGeometry(QgsAbstractGeometry *geometry)
Sets the underlying geometry store.
virtual QgsPolygonV2 * toPolygon(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a new polygon geometry corresponding to a segmentized approximation of the curve...
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:40
QPointF asQPointF() const
Return contents of the geometry as a QPointF if wkbType is WKBPoint, otherwise returns a null QPointF...
ValidationMethod
Available methods for validating geometries.
Definition: qgsgeometry.h:979
QVector< QgsPointXY > QgsMultiPoint
A collection of QgsPoints that share a common collection of attributes.
Definition: qgsgeometry.h:62
virtual int vertexCount(int part=0, int ring=0) const =0
Returns the number of vertexes of which this geometry is built.
virtual QgsLineString * curveToLine(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const =0
Returns a new line string geometry corresponding to a segmentized approximation of the curve...
static QgsAbstractGeometry * geomFromWkbType(QgsWkbTypes::Type t)
Return empty geometry from wkb type.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
QgsGeometry shortestLine(const QgsGeometry &other) const
Returns the shortest line joining this geometry to another geometry.
static QgsGeometry polygonize(const QList< QgsAbstractGeometry *> &geometries, QString *errorMsg=nullptr)
Creates a GeometryCollection geometry containing possible polygons formed from the constituent linewo...
Definition: qgsgeos.cpp:2132
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
static QgsGeometry fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
static QgsGeometry collectGeometry(const QList< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
QList< QgsPointSequence > QgsRingSequence
Class for doing transforms between two map coordinate systems.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:96
int transform(const QgsCoordinateTransform &ct)
Transform this geometry as described by CoordinateTransform ct.
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
int rotate(double rotation, const QgsPointXY &center)
Rotate this geometry around the Z axis.
void adjacentVertices(int atVertex, int &beforeVertex, int &afterVertex) const
Returns the indexes of the vertices before and after the given vertex index.
QgsGeometry convertToType(QgsWkbTypes::GeometryType destType, bool destMultipart=false) const
Try to convert the geometry to the requested type.
double closestVertexWithContext(const QgsPointXY &point, int &atVertex) const
Searches for the closest vertex in this geometry to the given point.
Multi polygon geometry collection.
Contains geometry relation and modification algorithms.
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:101
int reshapeGeometry(const QgsLineString &reshapeLineString)
Replaces a part of this geometry with another line.
static QgsGeometry fromPoint(const QgsPointXY &point)
Creates a new geometry from a QgsPointXY object.
QgsGeometry orientedMinimumBoundingBox(double &area, double &angle, double &width, double &height) const
Returns the oriented minimum bounding box for the geometry, which is the smallest (by area) rotated r...
QgsGeometry makeDifference(const QgsGeometry &other) const
Returns the geometry formed by modifying this geometry such that it does not intersect the other geom...
QgsGeometry voronoiDiagram(const QgsGeometry &extent=QgsGeometry(), double tolerance=0.0, bool edgesOnly=false) const
Creates a Voronoi diagram for the nodes contained within the geometry.
static bool deletePart(QgsAbstractGeometry *geom, int partNum)
Deletes a part from a geometry.
QList< QgsRingSequence > QgsCoordinateSequence
QgsGeometry orthogonalize(double tolerance=1.0E-8, int maxIterations=1000, double angleThreshold=15.0) const
Attempts to orthogonalize a line or polygon geometry by shifting vertices to make the geometries angl...
double area() const
Returns the area of the geometry using GEOS.
QgsGeometry voronoiDiagram(const QgsAbstractGeometry *extent=nullptr, double tolerance=0.0, bool edgesOnly=false, QString *errorMsg=nullptr) const
Creates a Voronoi diagram for the nodes contained within the geometry.
Definition: qgsgeos.cpp:2171
bool pointOnSurface(QgsPoint &pt, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1548
JoinStyle
Join styles for buffers.
Definition: qgsgeometry.h:589
QList< QgsPoint > QgsPointSequence
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Densifies the geometry by adding the specified number of extra nodes within each segment of the geome...
static QgsAbstractGeometry * fromPoint(const QgsPointXY &point)
Construct geometry from a point.
bool contains(const QgsPointXY *p) const
Test for containment of a point (uses GEOS)
QgsGeometry symDifference(const QgsGeometry &geometry) const
Returns a geometry representing the points making up this geometry that do not make up other...
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
QgsAbstractGeometry * _qgis_lwgeom_make_valid(const QgsAbstractGeometry &lwgeom_in, QString &errorMessage)
Implementation of QgsGeometry::makeValid(). Not a public API.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
Represents a vector layer which manages a vector based data sets.
bool contains(const QgsAbstractGeometry &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:416
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:423
QgsGeometry delaunayTriangulation(double tolerance=0.0, bool edgesOnly=false) const
Returns the Delaunay triangulation for the vertices of the geometry.
QgsGeometry smooth(const unsigned int iterations=1, const double offset=0.25, double minimumDistance=-1.0, double maxAngle=180.0) const
Smooths a geometry by rounding off corners using the Chaikin algorithm.
virtual bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
static QgsGeometry polygonize(const QList< QgsGeometry > &geometries)
Creates a GeometryCollection geometry containing possible polygons formed from the constituent linewo...
void removeInteriorRings(double minimumAllowedArea=-1)
Removes the interior rings from the polygon.
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
virtual bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
virtual int numPoints() const =0
Returns the number of points in the curve.
static double distanceToVertex(const QgsAbstractGeometry &geom, QgsVertexId id)
Returns the distance along a geometry from its first vertex to the specified vertex.
int addRing(const QList< QgsPointXY > &ring)
Adds a new ring to this geometry.
QgsAbstractGeometry * geometry() const
Returns the underlying geometry store.
double lineLocatePoint(const QgsGeometry &point) const
Returns a distance representing the location along this linestring of the closest point on this lines...
bool disjoint(const QgsGeometry &geometry) const
Test for if geometry is disjoint of another (uses GEOS)
bool isSimple(QString *errorMsg=nullptr) const override
Determines whether the geometry is simple (according to OGC definition).
Definition: qgsgeos.cpp:1642
virtual QString asJSON(int precision=17) const =0
Returns a GeoJSON representation of the geometry.
QgsGeometry extrude(double x, double y) const
Will extrude a line or (segmentized) curve by a given offset and return a polygon representation of i...
QgsAbstractGeometry * simplify(double tolerance, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1471
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:125
static QgsGeometry fromMultiPolyline(const QgsMultiPolyline &multiline)
Creates a new geometry from a QgsMultiPolyline object.
QDataStream & operator>>(QDataStream &in, QgsGeometry &geometry)
Reads a geometry from stream in into geometry. QGIS version compatibility is not guaranteed.
int avoidIntersections(const QList< QgsVectorLayer *> &avoidIntersectionsLayers, const QHash< QgsVectorLayer *, QSet< QgsFeatureId > > &ignoreFeatures=(QHash< QgsVectorLayer *, QSet< QgsFeatureId > >()))
Modifies geometry to avoid intersections with the layers specified in project properties.
void extend(double startDistance, double endDistance)
Extends the line geometry by extrapolating out the start or end of the line by a specified distance...
double x
Definition: qgspoint.h:40
QgsGeometry difference(const QgsGeometry &geometry) const
Returns a geometry representing the points making up this geometry that do not make up other...