QGIS API Documentation  2.99.0-Master (25b0421)
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 #include "qgscircle.h"
48 
50 {
52  QAtomicInt ref;
53  std::unique_ptr< QgsAbstractGeometry > geometry;
54 };
55 
57  : d( new QgsGeometryPrivate() )
58 {
59 }
60 
62 {
63  if ( !d->ref.deref() )
64  delete d;
65 }
66 
68  : d( new QgsGeometryPrivate() )
69 {
70  d->geometry.reset( geom );
71  d->ref = QAtomicInt( 1 );
72 }
73 
74 QgsGeometry::QgsGeometry( std::unique_ptr<QgsAbstractGeometry> geom )
75  : d( new QgsGeometryPrivate() )
76 {
77  d->geometry = std::move( geom );
78  d->ref = QAtomicInt( 1 );
79 }
80 
82 {
83  d = other.d;
84  mLastError = other.mLastError;
85  d->ref.ref();
86 }
87 
89 {
90  if ( !d->ref.deref() )
91  {
92  delete d;
93  }
94 
95  mLastError = other.mLastError;
96  d = other.d;
97  d->ref.ref();
98  return *this;
99 }
100 
101 void QgsGeometry::detach()
102 {
103  if ( d->ref <= 1 )
104  return;
105 
106  std::unique_ptr< QgsAbstractGeometry > cGeom;
107  if ( d->geometry )
108  cGeom.reset( d->geometry->clone() );
109 
110  reset( std::move( cGeom ) );
111 }
112 
113 void QgsGeometry::reset( std::unique_ptr<QgsAbstractGeometry> newGeometry )
114 {
115  if ( d->ref > 1 )
116  {
117  ( void )d->ref.deref();
118  d = new QgsGeometryPrivate();
119  }
120  d->geometry = std::move( newGeometry );
121 }
122 
124 {
125  return d->geometry.get();
126 }
127 
129 {
130  if ( d->geometry.get() == geometry )
131  {
132  return;
133  }
134 
135  reset( std::unique_ptr< QgsAbstractGeometry >( geometry ) );
136 }
137 
139 {
140  return !d->geometry;
141 }
142 
143 QgsGeometry QgsGeometry::fromWkt( const QString &wkt )
144 {
145  std::unique_ptr< QgsAbstractGeometry > geom = QgsGeometryFactory::geomFromWkt( wkt );
146  if ( !geom )
147  {
148  return QgsGeometry();
149  }
150  return QgsGeometry( std::move( geom ) );
151 }
152 
154 {
155  std::unique_ptr< QgsAbstractGeometry > geom( QgsGeometryFactory::fromPoint( point ) );
156  if ( geom )
157  {
158  return QgsGeometry( geom.release() );
159  }
160  return QgsGeometry();
161 }
162 
164 {
165  std::unique_ptr< QgsAbstractGeometry > geom = QgsGeometryFactory::fromPolyline( polyline );
166  if ( geom )
167  {
168  return QgsGeometry( std::move( geom ) );
169  }
170  return QgsGeometry();
171 }
172 
174 {
175  std::unique_ptr< QgsPolygonV2 > geom = QgsGeometryFactory::fromPolygon( polygon );
176  if ( geom )
177  {
178  return QgsGeometry( std::move( geom.release() ) );
179  }
180  return QgsGeometry();
181 }
182 
184 {
185  std::unique_ptr< QgsMultiPointV2 > geom = QgsGeometryFactory::fromMultiPoint( multipoint );
186  if ( geom )
187  {
188  return QgsGeometry( std::move( geom ) );
189  }
190  return QgsGeometry();
191 }
192 
194 {
195  std::unique_ptr< QgsMultiLineString > geom = QgsGeometryFactory::fromMultiPolyline( multiline );
196  if ( geom )
197  {
198  return QgsGeometry( std::move( geom ) );
199  }
200  return QgsGeometry();
201 }
202 
204 {
205  std::unique_ptr< QgsMultiPolygonV2 > geom = QgsGeometryFactory::fromMultiPolygon( multipoly );
206  if ( geom )
207  {
208  return QgsGeometry( std::move( geom ) );
209  }
210  return QgsGeometry();
211 }
212 
214 {
215  QgsPolyline ring;
216  ring.append( QgsPointXY( rect.xMinimum(), rect.yMinimum() ) );
217  ring.append( QgsPointXY( rect.xMaximum(), rect.yMinimum() ) );
218  ring.append( QgsPointXY( rect.xMaximum(), rect.yMaximum() ) );
219  ring.append( QgsPointXY( rect.xMinimum(), rect.yMaximum() ) );
220  ring.append( QgsPointXY( rect.xMinimum(), rect.yMinimum() ) );
221 
222  QgsPolygon polygon;
223  polygon.append( ring );
224 
225  return fromPolygon( polygon );
226 }
227 
228 QgsGeometry QgsGeometry::collectGeometry( const QList< QgsGeometry > &geometries )
229 {
230  QgsGeometry collected;
231 
232  for ( const QgsGeometry &g : geometries )
233  {
234  if ( collected.isNull() )
235  {
236  collected = g;
237  collected.convertToMultiType();
238  }
239  else
240  {
241  collected.addPart( g );
242  }
243  }
244  return collected;
245 }
246 
247 void QgsGeometry::fromWkb( unsigned char *wkb, int length )
248 {
249  QgsConstWkbPtr ptr( wkb, length );
250  reset( QgsGeometryFactory::geomFromWkb( ptr ) );
251  delete [] wkb;
252 }
253 
254 void QgsGeometry::fromWkb( const QByteArray &wkb )
255 {
256  QgsConstWkbPtr ptr( wkb );
257  reset( QgsGeometryFactory::geomFromWkb( ptr ) );
258 }
259 
260 GEOSGeometry *QgsGeometry::exportToGeos( double precision ) const
261 {
262  if ( !d->geometry )
263  {
264  return nullptr;
265  }
266 
267  return QgsGeos::asGeos( d->geometry.get(), precision ).release();
268 }
269 
270 
272 {
273  if ( !d->geometry )
274  {
275  return QgsWkbTypes::Unknown;
276  }
277  else
278  {
279  return d->geometry->wkbType();
280  }
281 }
282 
283 
285 {
286  if ( !d->geometry )
287  {
289  }
290  return static_cast< QgsWkbTypes::GeometryType >( QgsWkbTypes::geometryType( d->geometry->wkbType() ) );
291 }
292 
294 {
295  if ( !d->geometry )
296  {
297  return true;
298  }
299 
300  return d->geometry->isEmpty();
301 }
302 
304 {
305  if ( !d->geometry )
306  {
307  return false;
308  }
309  return QgsWkbTypes::isMultiType( d->geometry->wkbType() );
310 }
311 
312 void QgsGeometry::fromGeos( GEOSGeometry *geos )
313 {
314  reset( QgsGeos::fromGeos( geos ) );
315  GEOSGeom_destroy_r( QgsGeos::getGEOSHandler(), geos );
316 }
317 
318 QgsPointXY QgsGeometry::closestVertex( const QgsPointXY &point, int &atVertex, int &beforeVertex, int &afterVertex, double &sqrDist ) const
319 {
320  if ( !d->geometry )
321  {
322  sqrDist = -1;
323  return QgsPointXY( 0, 0 );
324  }
325 
326  QgsPoint pt( point.x(), point.y() );
327  QgsVertexId id;
328 
329  QgsPoint vp = QgsGeometryUtils::closestVertex( *( d->geometry ), pt, id );
330  if ( !id.isValid() )
331  {
332  sqrDist = -1;
333  return QgsPointXY( 0, 0 );
334  }
335  sqrDist = QgsGeometryUtils::sqrDistance2D( pt, vp );
336 
337  atVertex = vertexNrFromVertexId( id );
338  adjacentVertices( atVertex, beforeVertex, afterVertex );
339  return QgsPointXY( vp.x(), vp.y() );
340 }
341 
342 double QgsGeometry::distanceToVertex( int vertex ) const
343 {
344  if ( !d->geometry )
345  {
346  return -1;
347  }
348 
349  QgsVertexId id;
350  if ( !vertexIdFromVertexNr( vertex, id ) )
351  {
352  return -1;
353  }
354 
355  return QgsGeometryUtils::distanceToVertex( *( d->geometry ), id );
356 }
357 
358 double QgsGeometry::angleAtVertex( int vertex ) const
359 {
360  if ( !d->geometry )
361  {
362  return 0;
363  }
364 
365  QgsVertexId v2;
366  if ( !vertexIdFromVertexNr( vertex, v2 ) )
367  {
368  return 0;
369  }
370 
371  QgsVertexId v1;
372  QgsVertexId v3;
373  QgsGeometryUtils::adjacentVertices( *d->geometry, v2, v1, v3 );
374  if ( v1.isValid() && v3.isValid() )
375  {
376  QgsPoint p1 = d->geometry->vertexAt( v1 );
377  QgsPoint p2 = d->geometry->vertexAt( v2 );
378  QgsPoint p3 = d->geometry->vertexAt( v3 );
379  double angle1 = QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
380  double angle2 = QgsGeometryUtils::lineAngle( p2.x(), p2.y(), p3.x(), p3.y() );
381  return QgsGeometryUtils::averageAngle( angle1, angle2 );
382  }
383  else if ( v3.isValid() )
384  {
385  QgsPoint p1 = d->geometry->vertexAt( v2 );
386  QgsPoint p2 = d->geometry->vertexAt( v3 );
387  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
388  }
389  else if ( v1.isValid() )
390  {
391  QgsPoint p1 = d->geometry->vertexAt( v1 );
392  QgsPoint p2 = d->geometry->vertexAt( v2 );
393  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
394  }
395  return 0.0;
396 }
397 
398 void QgsGeometry::adjacentVertices( int atVertex, int &beforeVertex, int &afterVertex ) const
399 {
400  if ( !d->geometry )
401  {
402  return;
403  }
404 
405  QgsVertexId id;
406  if ( !vertexIdFromVertexNr( atVertex, id ) )
407  {
408  beforeVertex = -1;
409  afterVertex = -1;
410  return;
411  }
412 
413  QgsVertexId beforeVertexId, afterVertexId;
414  QgsGeometryUtils::adjacentVertices( *( d->geometry ), id, beforeVertexId, afterVertexId );
415  beforeVertex = vertexNrFromVertexId( beforeVertexId );
416  afterVertex = vertexNrFromVertexId( afterVertexId );
417 }
418 
419 bool QgsGeometry::moveVertex( double x, double y, int atVertex )
420 {
421  if ( !d->geometry )
422  {
423  return false;
424  }
425 
426  QgsVertexId id;
427  if ( !vertexIdFromVertexNr( atVertex, id ) )
428  {
429  return false;
430  }
431 
432  detach();
433 
434  return d->geometry->moveVertex( id, QgsPoint( x, y ) );
435 }
436 
437 bool QgsGeometry::moveVertex( const QgsPoint &p, int atVertex )
438 {
439  if ( !d->geometry )
440  {
441  return false;
442  }
443 
444  QgsVertexId id;
445  if ( !vertexIdFromVertexNr( atVertex, id ) )
446  {
447  return false;
448  }
449 
450  detach();
451 
452  return d->geometry->moveVertex( id, p );
453 }
454 
455 bool QgsGeometry::deleteVertex( int atVertex )
456 {
457  if ( !d->geometry )
458  {
459  return false;
460  }
461 
462  //maintain compatibility with < 2.10 API
463  if ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::MultiPoint )
464  {
465  detach();
466  //delete geometry instead of point
467  return static_cast< QgsGeometryCollection * >( d->geometry.get() )->removeGeometry( atVertex );
468  }
469 
470  //if it is a point, set the geometry to nullptr
471  if ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::Point )
472  {
473  reset( nullptr );
474  return true;
475  }
476 
477  QgsVertexId id;
478  if ( !vertexIdFromVertexNr( atVertex, id ) )
479  {
480  return false;
481  }
482 
483  detach();
484 
485  return d->geometry->deleteVertex( id );
486 }
487 
488 bool QgsGeometry::insertVertex( double x, double y, int beforeVertex )
489 {
490  if ( !d->geometry )
491  {
492  return false;
493  }
494 
495  //maintain compatibility with < 2.10 API
496  if ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::MultiPoint )
497  {
498  detach();
499  //insert geometry instead of point
500  return static_cast< QgsGeometryCollection * >( d->geometry.get() )->insertGeometry( new QgsPoint( x, y ), beforeVertex );
501  }
502 
503  QgsVertexId id;
504  if ( !vertexIdFromVertexNr( beforeVertex, id ) )
505  {
506  return false;
507  }
508 
509  detach();
510 
511  return d->geometry->insertVertex( id, QgsPoint( x, y ) );
512 }
513 
514 bool QgsGeometry::insertVertex( const QgsPoint &point, int beforeVertex )
515 {
516  if ( !d->geometry )
517  {
518  return false;
519  }
520 
521  //maintain compatibility with < 2.10 API
522  if ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::MultiPoint )
523  {
524  detach();
525  //insert geometry instead of point
526  return static_cast< QgsGeometryCollection * >( d->geometry.get() )->insertGeometry( new QgsPoint( point ), beforeVertex );
527  }
528 
529  QgsVertexId id;
530  if ( !vertexIdFromVertexNr( beforeVertex, id ) )
531  {
532  return false;
533  }
534 
535  detach();
536 
537  return d->geometry->insertVertex( id, point );
538 }
539 
540 QgsPoint QgsGeometry::vertexAt( int atVertex ) const
541 {
542  if ( !d->geometry )
543  {
544  return QgsPoint();
545  }
546 
547  QgsVertexId vId;
548  ( void )vertexIdFromVertexNr( atVertex, vId );
549  if ( vId.vertex < 0 )
550  {
551  return QgsPoint();
552  }
553  return d->geometry->vertexAt( vId );
554 }
555 
556 double QgsGeometry::sqrDistToVertexAt( QgsPointXY &point, int atVertex ) const
557 {
558  QgsPointXY vertexPoint = vertexAt( atVertex );
559  return QgsGeometryUtils::sqrDistance2D( QgsPoint( vertexPoint.x(), vertexPoint.y() ), QgsPoint( point.x(), point.y() ) );
560 }
561 
563 {
564  QgsGeos geos( d->geometry.get() );
565  mLastError.clear();
566  QgsGeometry result = geos.closestPoint( other );
567  result.mLastError = mLastError;
568  return result;
569 }
570 
572 {
573  QgsGeos geos( d->geometry.get() );
574  mLastError.clear();
575  QgsGeometry result = geos.shortestLine( other, &mLastError );
576  result.mLastError = mLastError;
577  return result;
578 }
579 
580 double QgsGeometry::closestVertexWithContext( const QgsPointXY &point, int &atVertex ) const
581 {
582  if ( !d->geometry )
583  {
584  return -1;
585  }
586 
587  QgsVertexId vId;
588  QgsPoint pt( point.x(), point.y() );
589  QgsPoint closestPoint = QgsGeometryUtils::closestVertex( *( d->geometry ), pt, vId );
590  if ( !vId.isValid() )
591  return -1;
592  atVertex = vertexNrFromVertexId( vId );
593  return QgsGeometryUtils::sqrDistance2D( closestPoint, pt );
594 }
595 
597  const QgsPointXY &point,
598  QgsPointXY &minDistPoint,
599  int &afterVertex,
600  double *leftOf,
601  double epsilon ) const
602 {
603  if ( !d->geometry )
604  {
605  return -1;
606  }
607 
608  QgsPoint segmentPt;
609  QgsVertexId vertexAfter;
610  bool leftOfBool;
611 
612  double sqrDist = d->geometry->closestSegment( QgsPoint( point.x(), point.y() ), segmentPt, vertexAfter, &leftOfBool, epsilon );
613  if ( sqrDist < 0 )
614  return -1;
615 
616  minDistPoint.setX( segmentPt.x() );
617  minDistPoint.setY( segmentPt.y() );
618  afterVertex = vertexNrFromVertexId( vertexAfter );
619  if ( leftOf )
620  {
621  *leftOf = leftOfBool ? 1.0 : -1.0;
622  }
623  return sqrDist;
624 }
625 
626 QgsGeometry::OperationResult QgsGeometry::addRing( const QList<QgsPointXY> &ring )
627 {
628  std::unique_ptr< QgsLineString > ringLine = qgis::make_unique< QgsLineString >( ring );
629  return addRing( ringLine.release() );
630 }
631 
633 {
634  std::unique_ptr< QgsCurve > r( ring );
635  if ( !d->geometry )
636  {
637  return InvalidInput;
638  }
639 
640  detach();
641 
642  return QgsGeometryEditUtils::addRing( d->geometry.get(), std::move( r ) );
643 }
644 
646 {
648  convertPointList( points, l );
649  return addPart( l, geomType );
650 }
651 
653 {
654  std::unique_ptr< QgsAbstractGeometry > partGeom;
655  if ( points.size() == 1 )
656  {
657  partGeom = qgis::make_unique< QgsPoint >( points[0] );
658  }
659  else if ( points.size() > 1 )
660  {
661  std::unique_ptr< QgsLineString > ringLine = qgis::make_unique< QgsLineString >();
662  ringLine->setPoints( points );
663  partGeom = std::move( ringLine );
664  }
665  return addPart( partGeom.release(), geomType );
666 }
667 
669 {
670  std::unique_ptr< QgsAbstractGeometry > p( part );
671  if ( !d->geometry )
672  {
673  switch ( geomType )
674  {
676  reset( qgis::make_unique< QgsMultiPointV2 >() );
677  break;
679  reset( qgis::make_unique< QgsMultiLineString >() );
680  break;
682  reset( qgis::make_unique< QgsMultiPolygonV2 >() );
683  break;
684  default:
685  reset( nullptr );
687  }
688  }
689  else
690  {
691  detach();
692  }
693 
695  return QgsGeometryEditUtils::addPart( d->geometry.get(), std::move( p ) );
696 }
697 
699 {
700  if ( !d->geometry )
701  {
703  }
704  if ( !newPart || !newPart.d->geometry )
705  {
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 
719  if ( QgsWkbTypes::isMultiType( d->geometry->wkbType() ) )
720  {
721  const QList<QgsGeometry> parts = asGeometryCollection();
722  QList<QgsGeometry> results;
723  for ( 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  for ( const QgsGeometry &result : qgis::as_const( results ) )
734  {
735  first.addPart( result );
736  }
737  return first;
738  }
739  else
740  {
741  std::unique_ptr< QgsCurvePolygon > newPoly( static_cast< QgsCurvePolygon * >( d->geometry->clone() ) );
742  newPoly->removeInteriorRings( minimumRingArea );
743  return QgsGeometry( std::move( newPoly ) );
744  }
745 }
746 
748 {
749  if ( !d->geometry )
750  {
752  }
753  if ( !newPart )
754  {
756  }
757 
758  detach();
759 
760  std::unique_ptr< QgsAbstractGeometry > geom = QgsGeos::fromGeos( newPart );
761  return QgsGeometryEditUtils::addPart( d->geometry.get(), std::move( geom ) );
762 }
763 
765 {
766  if ( !d->geometry )
767  {
769  }
770 
771  detach();
772 
773  d->geometry->transform( QTransform::fromTranslate( dx, dy ) );
774  return QgsGeometry::Success;
775 }
776 
778 {
779  if ( !d->geometry )
780  {
782  }
783 
784  detach();
785 
786  QTransform t = QTransform::fromTranslate( center.x(), center.y() );
787  t.rotate( -rotation );
788  t.translate( -center.x(), -center.y() );
789  d->geometry->transform( t );
790  return QgsGeometry::Success;
791 }
792 
793 QgsGeometry::OperationResult QgsGeometry::splitGeometry( const QList<QgsPointXY> &splitLine, QList<QgsGeometry> &newGeometries, bool topological, QList<QgsPointXY> &topologyTestPoints )
794 {
795  if ( !d->geometry )
796  {
797  return InvalidBaseGeometry;
798  }
799 
800  QList<QgsGeometry > newGeoms;
801  QgsLineString splitLineString( splitLine );
802  QgsPointSequence tp;
803 
804  QgsGeos geos( d->geometry.get() );
805  mLastError.clear();
806  QgsGeometryEngine::EngineOperationResult result = geos.splitGeometry( splitLineString, newGeoms, topological, tp, &mLastError );
807 
808  if ( result == QgsGeometryEngine::Success )
809  {
810  *this = newGeoms.takeAt( 0 );
811 
812  newGeometries = newGeoms;
813  }
814 
815  convertPointList( tp, topologyTestPoints );
816 
817  switch ( result )
818  {
820  return QgsGeometry::Success;
833  //default: do not implement default to handle properly all cases
834  }
835 
836  // this should never be reached
837  Q_ASSERT( false );
839 }
840 
842 {
843  if ( !d->geometry )
844  {
845  return InvalidBaseGeometry;
846  }
847 
848  QgsGeos geos( d->geometry.get() );
850  mLastError.clear();
851  std::unique_ptr< QgsAbstractGeometry > geom( geos.reshapeGeometry( reshapeLineString, &errorCode, &mLastError ) );
852  if ( errorCode == QgsGeometryEngine::Success && geom )
853  {
854  reset( std::move( geom ) );
855  return Success;
856  }
857 
858  switch ( errorCode )
859  {
861  return Success;
865  return GeometryEngineError;
867  return InvalidBaseGeometry;
869  return InvalidInput;
870  case QgsGeometryEngine::SplitCannotSplitPoint: // should not happen
871  return GeometryEngineError;
873  return NothingHappened;
874  }
875 
876  // should not be reached
877  return GeometryEngineError;
878 }
879 
881 {
882  if ( !d->geometry || !other.d->geometry )
883  {
884  return 0;
885  }
886 
887  QgsGeos geos( d->geometry.get() );
888 
889  mLastError.clear();
890  std::unique_ptr< QgsAbstractGeometry > diffGeom( geos.intersection( other.geometry(), &mLastError ) );
891  if ( !diffGeom )
892  {
893  return 1;
894  }
895 
896  reset( std::move( diffGeom ) );
897  return 0;
898 }
899 
901 {
902  if ( !d->geometry || other.isNull() )
903  {
904  return QgsGeometry();
905  }
906 
907  QgsGeos geos( d->geometry.get() );
908 
909  mLastError.clear();
910  std::unique_ptr< QgsAbstractGeometry > diffGeom( geos.intersection( other.geometry(), &mLastError ) );
911  if ( !diffGeom )
912  {
913  QgsGeometry result;
914  result.mLastError = mLastError;
915  return result;
916  }
917 
918  return QgsGeometry( diffGeom.release() );
919 }
920 
922 {
923  if ( d->geometry )
924  {
925  return d->geometry->boundingBox();
926  }
927  return QgsRectangle();
928 }
929 
930 QgsGeometry QgsGeometry::orientedMinimumBoundingBox( double &area, double &angle, double &width, double &height ) const
931 {
932  QgsRectangle minRect;
933  area = DBL_MAX;
934  angle = 0;
935  width = DBL_MAX;
936  height = DBL_MAX;
937 
938  if ( !d->geometry || d->geometry->nCoordinates() < 2 )
939  return QgsGeometry();
940 
941  QgsGeometry hull = convexHull();
942  if ( hull.isNull() )
943  return QgsGeometry();
944 
945  QgsVertexId vertexId;
946  QgsPoint pt0;
947  QgsPoint pt1;
948  QgsPoint pt2;
949  // get first point
950  hull.geometry()->nextVertex( vertexId, pt0 );
951  pt1 = pt0;
952  double prevAngle = 0.0;
953  while ( hull.geometry()->nextVertex( vertexId, pt2 ) )
954  {
955  double currentAngle = QgsGeometryUtils::lineAngle( pt1.x(), pt1.y(), pt2.x(), pt2.y() );
956  double rotateAngle = 180.0 / M_PI * ( currentAngle - prevAngle );
957  prevAngle = currentAngle;
958 
959  QTransform t = QTransform::fromTranslate( pt0.x(), pt0.y() );
960  t.rotate( rotateAngle );
961  t.translate( -pt0.x(), -pt0.y() );
962 
963  hull.geometry()->transform( t );
964 
965  QgsRectangle bounds = hull.geometry()->boundingBox();
966  double currentArea = bounds.width() * bounds.height();
967  if ( currentArea < area )
968  {
969  minRect = bounds;
970  area = currentArea;
971  angle = 180.0 / M_PI * currentAngle;
972  width = bounds.width();
973  height = bounds.height();
974  }
975 
976  pt2 = pt1;
977  }
978 
979  QgsGeometry minBounds = QgsGeometry::fromRect( minRect );
980  minBounds.rotate( angle, QgsPointXY( pt0.x(), pt0.y() ) );
981 
982  // constrain angle to 0 - 180
983  if ( angle > 180.0 )
984  angle = std::fmod( angle, 180.0 );
985 
986  return minBounds;
987 }
988 
990 {
991  double area, angle, width, height;
992  return orientedMinimumBoundingBox( area, angle, width, height );
993 }
994 
995 static QgsCircle __recMinimalEnclosingCircle( QgsMultiPoint points, QgsMultiPoint boundary )
996 {
997  auto l_boundary = boundary.length();
998  QgsCircle circ_mec;
999  if ( ( points.length() == 0 ) || ( l_boundary == 3 ) )
1000  {
1001  switch ( l_boundary )
1002  {
1003  case 0:
1004  circ_mec = QgsCircle();
1005  break;
1006  case 1:
1007  circ_mec = QgsCircle( QgsPoint( boundary.last() ), 0 );
1008  boundary.pop_back();
1009  break;
1010  case 2:
1011  {
1012  QgsPointXY p1 = boundary.last();
1013  boundary.pop_back();
1014  QgsPointXY p2 = boundary.last();
1015  boundary.pop_back();
1016  circ_mec = QgsCircle().from2Points( QgsPoint( p1 ), QgsPoint( p2 ) );
1017  }
1018  break;
1019  default:
1020  QgsPoint p1( boundary.at( 0 ) );
1021  QgsPoint p2( boundary.at( 1 ) );
1022  QgsPoint p3( boundary.at( 2 ) );
1023  circ_mec = QgsCircle().minimalCircleFrom3Points( p1, p2, p3 );
1024  break;
1025  }
1026  return circ_mec;
1027  }
1028  else
1029  {
1030  QgsPointXY pxy = points.last();
1031  points.pop_back();
1032  circ_mec = __recMinimalEnclosingCircle( points, boundary );
1033  QgsPoint p( pxy );
1034  if ( !circ_mec.contains( p ) )
1035  {
1036  boundary.append( pxy );
1037  circ_mec = __recMinimalEnclosingCircle( points, boundary );
1038  }
1039  }
1040  return circ_mec;
1041 }
1042 
1043 QgsGeometry QgsGeometry::minimalEnclosingCircle( QgsPointXY &center, double &radius, unsigned int segments ) const
1044 {
1045  center = QgsPointXY( );
1046  radius = 0;
1047 
1048  if ( !d->geometry )
1049  {
1050  return QgsGeometry();
1051  }
1052 
1053  /* optimization */
1054  QgsGeometry hull = convexHull();
1055  if ( hull.isNull() )
1056  return QgsGeometry();
1057 
1058  QgsMultiPoint P = hull.convertToPoint( true ).asMultiPoint();
1059  QgsMultiPoint R;
1060 
1061  QgsCircle circ = __recMinimalEnclosingCircle( P, R );
1062  center = QgsPointXY( circ.center() );
1063  radius = circ.radius();
1064  QgsGeometry geom;
1065  geom.setGeometry( circ.toPolygon( segments ) );
1066  return geom;
1067 
1068 }
1069 
1070 QgsGeometry QgsGeometry::minimalEnclosingCircle( unsigned int segments ) const
1071 {
1072  QgsPointXY center;
1073  double radius;
1074  return minimalEnclosingCircle( center, radius, segments );
1075 
1076 }
1077 
1078 QgsGeometry QgsGeometry::orthogonalize( double tolerance, int maxIterations, double angleThreshold ) const
1079 {
1080  QgsInternalGeometryEngine engine( *this );
1081 
1082  return engine.orthogonalize( tolerance, maxIterations, angleThreshold );
1083 }
1084 
1086 {
1087  QgsGeometry g = fromRect( r );
1088  return intersects( g );
1089 }
1090 
1092 {
1093  if ( !d->geometry || geometry.isNull() )
1094  {
1095  return false;
1096  }
1097 
1098  QgsGeos geos( d->geometry.get() );
1099  mLastError.clear();
1100  return geos.intersects( geometry.d->geometry.get(), &mLastError );
1101 }
1102 
1103 bool QgsGeometry::contains( const QgsPointXY *p ) const
1104 {
1105  if ( !d->geometry || !p )
1106  {
1107  return false;
1108  }
1109 
1110  QgsPoint pt( p->x(), p->y() );
1111  QgsGeos geos( d->geometry.get() );
1112  mLastError.clear();
1113  return geos.contains( &pt, &mLastError );
1114 }
1115 
1117 {
1118  if ( !d->geometry || geometry.isNull() )
1119  {
1120  return false;
1121  }
1122 
1123  QgsGeos geos( d->geometry.get() );
1124  mLastError.clear();
1125  return geos.contains( geometry.d->geometry.get(), &mLastError );
1126 }
1127 
1129 {
1130  if ( !d->geometry || geometry.isNull() )
1131  {
1132  return false;
1133  }
1134 
1135  QgsGeos geos( d->geometry.get() );
1136  mLastError.clear();
1137  return geos.disjoint( geometry.d->geometry.get(), &mLastError );
1138 }
1139 
1141 {
1142  if ( !d->geometry || geometry.isNull() )
1143  {
1144  return false;
1145  }
1146 
1147  QgsGeos geos( d->geometry.get() );
1148  mLastError.clear();
1149  return geos.isEqual( geometry.d->geometry.get(), &mLastError );
1150 }
1151 
1153 {
1154  if ( !d->geometry || geometry.isNull() )
1155  {
1156  return false;
1157  }
1158 
1159  QgsGeos geos( d->geometry.get() );
1160  mLastError.clear();
1161  return geos.touches( geometry.d->geometry.get(), &mLastError );
1162 }
1163 
1165 {
1166  if ( !d->geometry || geometry.isNull() )
1167  {
1168  return false;
1169  }
1170 
1171  QgsGeos geos( d->geometry.get() );
1172  mLastError.clear();
1173  return geos.overlaps( geometry.d->geometry.get(), &mLastError );
1174 }
1175 
1177 {
1178  if ( !d->geometry || geometry.isNull() )
1179  {
1180  return false;
1181  }
1182 
1183  QgsGeos geos( d->geometry.get() );
1184  mLastError.clear();
1185  return geos.within( geometry.d->geometry.get(), &mLastError );
1186 }
1187 
1189 {
1190  if ( !d->geometry || geometry.isNull() )
1191  {
1192  return false;
1193  }
1194 
1195  QgsGeos geos( d->geometry.get() );
1196  mLastError.clear();
1197  return geos.crosses( geometry.d->geometry.get(), &mLastError );
1198 }
1199 
1200 QString QgsGeometry::exportToWkt( int precision ) const
1201 {
1202  if ( !d->geometry )
1203  {
1204  return QString();
1205  }
1206  return d->geometry->asWkt( precision );
1207 }
1208 
1209 QString QgsGeometry::exportToGeoJSON( int precision ) const
1210 {
1211  if ( !d->geometry )
1212  {
1213  return QStringLiteral( "null" );
1214  }
1215  return d->geometry->asJSON( precision );
1216 }
1217 
1219 {
1220  switch ( destType )
1221  {
1223  return convertToPoint( destMultipart );
1224 
1226  return convertToLine( destMultipart );
1227 
1229  return convertToPolygon( destMultipart );
1230 
1231  default:
1232  return QgsGeometry();
1233  }
1234 }
1235 
1237 {
1238  if ( !d->geometry )
1239  {
1240  return false;
1241  }
1242 
1243  if ( isMultipart() ) //already multitype, no need to convert
1244  {
1245  return true;
1246  }
1247 
1248  std::unique_ptr< QgsAbstractGeometry >geom = QgsGeometryFactory::geomFromWkbType( QgsWkbTypes::multiType( d->geometry->wkbType() ) );
1249  QgsGeometryCollection *multiGeom = qgsgeometry_cast<QgsGeometryCollection *>( geom.get() );
1250  if ( !multiGeom )
1251  {
1252  return false;
1253  }
1254 
1255  multiGeom->addGeometry( d->geometry->clone() );
1256  reset( std::move( geom ) );
1257  return true;
1258 }
1259 
1261 {
1262  if ( !d->geometry )
1263  {
1264  return false;
1265  }
1266 
1267  if ( !isMultipart() ) //already single part, no need to convert
1268  {
1269  return true;
1270  }
1271 
1273  if ( !multiGeom || multiGeom->partCount() < 1 )
1274  return false;
1275 
1276  std::unique_ptr< QgsAbstractGeometry > firstPart( multiGeom->geometryN( 0 )->clone() );
1277  reset( std::move( firstPart ) );
1278  return true;
1279 }
1280 
1282 {
1283  if ( !d->geometry || QgsWkbTypes::flatType( d->geometry->wkbType() ) != QgsWkbTypes::Point )
1284  {
1285  return QgsPointXY();
1286  }
1287  QgsPoint *pt = qgsgeometry_cast<QgsPoint *>( d->geometry.get() );
1288  if ( !pt )
1289  {
1290  return QgsPointXY();
1291  }
1292 
1293  return QgsPointXY( pt->x(), pt->y() );
1294 }
1295 
1297 {
1298  QgsPolyline polyLine;
1299  if ( !d->geometry )
1300  {
1301  return polyLine;
1302  }
1303 
1304  bool doSegmentation = ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::CompoundCurve
1306  std::unique_ptr< QgsLineString > segmentizedLine;
1307  QgsLineString *line = nullptr;
1308  if ( doSegmentation )
1309  {
1310  QgsCurve *curve = qgsgeometry_cast<QgsCurve *>( d->geometry.get() );
1311  if ( !curve )
1312  {
1313  return polyLine;
1314  }
1315  segmentizedLine.reset( curve->curveToLine() );
1316  line = segmentizedLine.get();
1317  }
1318  else
1319  {
1320  line = qgsgeometry_cast<QgsLineString *>( d->geometry.get() );
1321  if ( !line )
1322  {
1323  return polyLine;
1324  }
1325  }
1326 
1327  int nVertices = line->numPoints();
1328  polyLine.resize( nVertices );
1329  for ( int i = 0; i < nVertices; ++i )
1330  {
1331  polyLine[i].setX( line->xAt( i ) );
1332  polyLine[i].setY( line->yAt( i ) );
1333  }
1334 
1335  return polyLine;
1336 }
1337 
1339 {
1340  if ( !d->geometry )
1341  return QgsPolygon();
1342 
1343  bool doSegmentation = ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::CurvePolygon );
1344 
1345  QgsPolygonV2 *p = nullptr;
1346  std::unique_ptr< QgsPolygonV2 > segmentized;
1347  if ( doSegmentation )
1348  {
1349  QgsCurvePolygon *curvePoly = qgsgeometry_cast<QgsCurvePolygon *>( d->geometry.get() );
1350  if ( !curvePoly )
1351  {
1352  return QgsPolygon();
1353  }
1354  segmentized.reset( curvePoly->toPolygon() );
1355  p = segmentized.get();
1356  }
1357  else
1358  {
1359  p = qgsgeometry_cast<QgsPolygonV2 *>( d->geometry.get() );
1360  }
1361 
1362  if ( !p )
1363  {
1364  return QgsPolygon();
1365  }
1366 
1367  QgsPolygon polygon;
1368  convertPolygon( *p, polygon );
1369 
1370  return polygon;
1371 }
1372 
1374 {
1375  if ( !d->geometry || QgsWkbTypes::flatType( d->geometry->wkbType() ) != QgsWkbTypes::MultiPoint )
1376  {
1377  return QgsMultiPoint();
1378  }
1379 
1380  const QgsMultiPointV2 *mp = qgsgeometry_cast<QgsMultiPointV2 *>( d->geometry.get() );
1381  if ( !mp )
1382  {
1383  return QgsMultiPoint();
1384  }
1385 
1386  int nPoints = mp->numGeometries();
1387  QgsMultiPoint multiPoint( nPoints );
1388  for ( int i = 0; i < nPoints; ++i )
1389  {
1390  const QgsPoint *pt = static_cast<const QgsPoint *>( mp->geometryN( i ) );
1391  multiPoint[i].setX( pt->x() );
1392  multiPoint[i].setY( pt->y() );
1393  }
1394  return multiPoint;
1395 }
1396 
1398 {
1399  if ( !d->geometry )
1400  {
1401  return QgsMultiPolyline();
1402  }
1403 
1404  QgsGeometryCollection *geomCollection = qgsgeometry_cast<QgsGeometryCollection *>( d->geometry.get() );
1405  if ( !geomCollection )
1406  {
1407  return QgsMultiPolyline();
1408  }
1409 
1410  int nLines = geomCollection->numGeometries();
1411  if ( nLines < 1 )
1412  {
1413  return QgsMultiPolyline();
1414  }
1415 
1416  QgsMultiPolyline mpl;
1417  for ( int i = 0; i < nLines; ++i )
1418  {
1419  const QgsLineString *line = qgsgeometry_cast<const QgsLineString *>( geomCollection->geometryN( i ) );
1420  std::unique_ptr< QgsLineString > segmentized;
1421  if ( !line )
1422  {
1423  const QgsCurve *curve = qgsgeometry_cast<const QgsCurve *>( geomCollection->geometryN( i ) );
1424  if ( !curve )
1425  {
1426  continue;
1427  }
1428  segmentized.reset( curve->curveToLine() );
1429  line = segmentized.get();
1430  }
1431 
1432  QgsPointSequence lineCoords;
1433  line->points( lineCoords );
1434  QgsPolyline polyLine;
1435  convertToPolyline( lineCoords, polyLine );
1436  mpl.append( polyLine );
1437  }
1438  return mpl;
1439 }
1440 
1442 {
1443  if ( !d->geometry )
1444  {
1445  return QgsMultiPolygon();
1446  }
1447 
1448  QgsGeometryCollection *geomCollection = qgsgeometry_cast<QgsGeometryCollection *>( d->geometry.get() );
1449  if ( !geomCollection )
1450  {
1451  return QgsMultiPolygon();
1452  }
1453 
1454  int nPolygons = geomCollection->numGeometries();
1455  if ( nPolygons < 1 )
1456  {
1457  return QgsMultiPolygon();
1458  }
1459 
1460  QgsMultiPolygon mp;
1461  for ( int i = 0; i < nPolygons; ++i )
1462  {
1463  const QgsPolygonV2 *polygon = qgsgeometry_cast<const QgsPolygonV2 *>( geomCollection->geometryN( i ) );
1464  if ( !polygon )
1465  {
1466  const QgsCurvePolygon *cPolygon = qgsgeometry_cast<const QgsCurvePolygon *>( geomCollection->geometryN( i ) );
1467  if ( cPolygon )
1468  {
1469  polygon = cPolygon->toPolygon();
1470  }
1471  else
1472  {
1473  continue;
1474  }
1475  }
1476 
1477  QgsPolygon poly;
1478  convertPolygon( *polygon, poly );
1479  mp.append( poly );
1480  }
1481  return mp;
1482 }
1483 
1484 double QgsGeometry::area() const
1485 {
1486  if ( !d->geometry )
1487  {
1488  return -1.0;
1489  }
1490  QgsGeos g( d->geometry.get() );
1491 
1492 #if 0
1493  //debug: compare geos area with calculation in QGIS
1494  double geosArea = g.area();
1495  double qgisArea = 0;
1496  QgsSurface *surface = qgsgeometry_cast<QgsSurface *>( d->geometry );
1497  if ( surface )
1498  {
1499  qgisArea = surface->area();
1500  }
1501 #endif
1502 
1503  mLastError.clear();
1504  return g.area( &mLastError );
1505 }
1506 
1507 double QgsGeometry::length() const
1508 {
1509  if ( !d->geometry )
1510  {
1511  return -1.0;
1512  }
1513  QgsGeos g( d->geometry.get() );
1514  mLastError.clear();
1515  return g.length( &mLastError );
1516 }
1517 
1518 double QgsGeometry::distance( const QgsGeometry &geom ) const
1519 {
1520  if ( !d->geometry || !geom.d->geometry )
1521  {
1522  return -1.0;
1523  }
1524 
1525  QgsGeos g( d->geometry.get() );
1526  mLastError.clear();
1527  return g.distance( geom.d->geometry.get(), &mLastError );
1528 }
1529 
1530 double QgsGeometry::hausdorffDistance( const QgsGeometry &geom ) const
1531 {
1532  if ( !d->geometry || !geom.d->geometry )
1533  {
1534  return -1.0;
1535  }
1536 
1537  QgsGeos g( d->geometry.get() );
1538  mLastError.clear();
1539  return g.hausdorffDistance( geom.d->geometry.get(), &mLastError );
1540 }
1541 
1542 double QgsGeometry::hausdorffDistanceDensify( const QgsGeometry &geom, double densifyFraction ) const
1543 {
1544  if ( !d->geometry || !geom.d->geometry )
1545  {
1546  return -1.0;
1547  }
1548 
1549  QgsGeos g( d->geometry.get() );
1550  mLastError.clear();
1551  return g.hausdorffDistanceDensify( geom.d->geometry.get(), densifyFraction, &mLastError );
1552 }
1553 
1555 {
1556  if ( !d->geometry )
1558  return d->geometry->vertices_begin();
1559 }
1560 
1562 {
1563  if ( !d->geometry )
1565  return d->geometry->vertices_end();
1566 }
1567 
1569 {
1570  if ( !d->geometry )
1571  return QgsVertexIterator();
1572  return QgsVertexIterator( d->geometry.get() );
1573 }
1574 
1575 QgsGeometry QgsGeometry::buffer( double distance, int segments ) const
1576 {
1577  if ( !d->geometry )
1578  {
1579  return QgsGeometry();
1580  }
1581 
1582  QgsGeos g( d->geometry.get() );
1583  mLastError.clear();
1584  std::unique_ptr<QgsAbstractGeometry> geom( g.buffer( distance, segments, &mLastError ) );
1585  if ( !geom )
1586  {
1587  QgsGeometry result;
1588  result.mLastError = mLastError;
1589  return result;
1590  }
1591  return QgsGeometry( std::move( geom ) );
1592 }
1593 
1594 QgsGeometry QgsGeometry::buffer( double distance, int segments, EndCapStyle endCapStyle, JoinStyle joinStyle, double miterLimit ) const
1595 {
1596  if ( !d->geometry )
1597  {
1598  return QgsGeometry();
1599  }
1600 
1601  QgsGeos g( d->geometry.get() );
1602  mLastError.clear();
1603  QgsAbstractGeometry *geom = g.buffer( distance, segments, endCapStyle, joinStyle, miterLimit, &mLastError );
1604  if ( !geom )
1605  {
1606  QgsGeometry result;
1607  result.mLastError = mLastError;
1608  return result;
1609  }
1610  return QgsGeometry( geom );
1611 }
1612 
1613 QgsGeometry QgsGeometry::offsetCurve( double distance, int segments, JoinStyle joinStyle, double miterLimit ) const
1614 {
1615  if ( !d->geometry || type() != QgsWkbTypes::LineGeometry )
1616  {
1617  return QgsGeometry();
1618  }
1619 
1620  if ( QgsWkbTypes::isMultiType( d->geometry->wkbType() ) )
1621  {
1622  const QList<QgsGeometry> parts = asGeometryCollection();
1623  QList<QgsGeometry> results;
1624  for ( const QgsGeometry &part : parts )
1625  {
1626  QgsGeometry result = part.offsetCurve( distance, segments, joinStyle, miterLimit );
1627  if ( result )
1628  results << result;
1629  }
1630  if ( results.isEmpty() )
1631  return QgsGeometry();
1632 
1633  QgsGeometry first = results.takeAt( 0 );
1634  for ( const QgsGeometry &result : qgis::as_const( results ) )
1635  {
1636  first.addPart( result );
1637  }
1638  return first;
1639  }
1640  else
1641  {
1642  QgsGeos geos( d->geometry.get() );
1643  mLastError.clear();
1644  QgsAbstractGeometry *offsetGeom = geos.offsetCurve( distance, segments, joinStyle, miterLimit, &mLastError );
1645  if ( !offsetGeom )
1646  {
1647  QgsGeometry result;
1648  result.mLastError = mLastError;
1649  return result;
1650  }
1651  return QgsGeometry( offsetGeom );
1652  }
1653 }
1654 
1655 QgsGeometry QgsGeometry::singleSidedBuffer( double distance, int segments, BufferSide side, JoinStyle joinStyle, double miterLimit ) const
1656 {
1657  if ( !d->geometry || type() != QgsWkbTypes::LineGeometry )
1658  {
1659  return QgsGeometry();
1660  }
1661 
1662  if ( QgsWkbTypes::isMultiType( d->geometry->wkbType() ) )
1663  {
1664  const QList<QgsGeometry> parts = asGeometryCollection();
1665  QList<QgsGeometry> results;
1666  for ( const QgsGeometry &part : parts )
1667  {
1668  QgsGeometry result = part.singleSidedBuffer( distance, segments, side, joinStyle, miterLimit );
1669  if ( result )
1670  results << result;
1671  }
1672  if ( results.isEmpty() )
1673  return QgsGeometry();
1674 
1675  QgsGeometry first = results.takeAt( 0 );
1676  for ( const QgsGeometry &result : qgis::as_const( results ) )
1677  {
1678  first.addPart( result );
1679  }
1680  return first;
1681  }
1682  else
1683  {
1684  QgsGeos geos( d->geometry.get() );
1685  mLastError.clear();
1686  std::unique_ptr< QgsAbstractGeometry > bufferGeom = geos.singleSidedBuffer( distance, segments, side,
1687  joinStyle, miterLimit, &mLastError );
1688  if ( !bufferGeom )
1689  {
1690  QgsGeometry result;
1691  result.mLastError = mLastError;
1692  return result;
1693  }
1694  return QgsGeometry( std::move( bufferGeom ) );
1695  }
1696 }
1697 
1698 QgsGeometry QgsGeometry::extendLine( double startDistance, double endDistance ) const
1699 {
1700  if ( !d->geometry || type() != QgsWkbTypes::LineGeometry )
1701  {
1702  return QgsGeometry();
1703  }
1704 
1705  if ( QgsWkbTypes::isMultiType( d->geometry->wkbType() ) )
1706  {
1707  const QList<QgsGeometry> parts = asGeometryCollection();
1708  QList<QgsGeometry> results;
1709  for ( const QgsGeometry &part : parts )
1710  {
1711  QgsGeometry result = part.extendLine( startDistance, endDistance );
1712  if ( result )
1713  results << result;
1714  }
1715  if ( results.isEmpty() )
1716  return QgsGeometry();
1717 
1718  QgsGeometry first = results.takeAt( 0 );
1719  for ( const QgsGeometry &result : qgis::as_const( results ) )
1720  {
1721  first.addPart( result );
1722  }
1723  return first;
1724  }
1725  else
1726  {
1727  QgsLineString *line = qgsgeometry_cast< QgsLineString * >( d->geometry.get() );
1728  if ( !line )
1729  return QgsGeometry();
1730 
1731  std::unique_ptr< QgsLineString > newLine( line->clone() );
1732  newLine->extend( startDistance, endDistance );
1733  return QgsGeometry( std::move( newLine ) );
1734  }
1735 }
1736 
1737 QgsGeometry QgsGeometry::simplify( double tolerance ) const
1738 {
1739  if ( !d->geometry )
1740  {
1741  return QgsGeometry();
1742  }
1743 
1744  QgsGeos geos( d->geometry.get() );
1745  mLastError.clear();
1746  std::unique_ptr< QgsAbstractGeometry > simplifiedGeom( geos.simplify( tolerance, &mLastError ) );
1747  if ( !simplifiedGeom )
1748  {
1749  QgsGeometry result;
1750  result.mLastError = mLastError;
1751  return result;
1752  }
1753  return QgsGeometry( std::move( simplifiedGeom ) );
1754 }
1755 
1756 QgsGeometry QgsGeometry::densifyByCount( int extraNodesPerSegment ) const
1757 {
1758  QgsInternalGeometryEngine engine( *this );
1759 
1760  return engine.densifyByCount( extraNodesPerSegment );
1761 }
1762 
1764 {
1765  QgsInternalGeometryEngine engine( *this );
1766 
1767  return engine.densifyByDistance( distance );
1768 }
1769 
1771 {
1772  if ( !d->geometry )
1773  {
1774  return QgsGeometry();
1775  }
1776 
1777  QgsGeos geos( d->geometry.get() );
1778 
1779  mLastError.clear();
1780  QgsGeometry result( geos.centroid( &mLastError ) );
1781  result.mLastError = mLastError;
1782  return result;
1783 }
1784 
1786 {
1787  if ( !d->geometry )
1788  {
1789  return QgsGeometry();
1790  }
1791 
1792  QgsGeos geos( d->geometry.get() );
1793 
1794  mLastError.clear();
1795  QgsGeometry result( geos.pointOnSurface( &mLastError ) );
1796  result.mLastError = mLastError;
1797  return result;
1798 }
1799 
1800 QgsGeometry QgsGeometry::poleOfInaccessibility( double precision, double *distanceToBoundary ) const
1801 {
1802  QgsInternalGeometryEngine engine( *this );
1803 
1804  return engine.poleOfInaccessibility( precision, distanceToBoundary );
1805 }
1806 
1808 {
1809  if ( !d->geometry )
1810  {
1811  return QgsGeometry();
1812  }
1813  QgsGeos geos( d->geometry.get() );
1814  mLastError.clear();
1815  std::unique_ptr< QgsAbstractGeometry > cHull( geos.convexHull( &mLastError ) );
1816  if ( !cHull )
1817  {
1818  QgsGeometry geom;
1819  geom.mLastError = mLastError;
1820  return geom;
1821  }
1822  return QgsGeometry( std::move( cHull ) );
1823 }
1824 
1825 QgsGeometry QgsGeometry::voronoiDiagram( const QgsGeometry &extent, double tolerance, bool edgesOnly ) const
1826 {
1827  if ( !d->geometry )
1828  {
1829  return QgsGeometry();
1830  }
1831 
1832  QgsGeos geos( d->geometry.get() );
1833  mLastError.clear();
1834  QgsGeometry result = geos.voronoiDiagram( extent.geometry(), tolerance, edgesOnly, &mLastError );
1835  result.mLastError = mLastError;
1836  return result;
1837 }
1838 
1839 QgsGeometry QgsGeometry::delaunayTriangulation( double tolerance, bool edgesOnly ) const
1840 {
1841  if ( !d->geometry )
1842  {
1843  return QgsGeometry();
1844  }
1845 
1846  QgsGeos geos( d->geometry.get() );
1847  mLastError.clear();
1848  QgsGeometry result = geos.delaunayTriangulation( tolerance, edgesOnly );
1849  result.mLastError = mLastError;
1850  return result;
1851 }
1852 
1854 {
1855  if ( !d->geometry )
1856  {
1857  return QgsGeometry();
1858  }
1859 
1860  const QgsAbstractGeometry *geom = d->geometry.get();
1861  std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
1862  if ( QgsWkbTypes::isCurvedType( d->geometry->wkbType() ) )
1863  {
1864  segmentizedCopy.reset( d->geometry->segmentize() );
1865  geom = segmentizedCopy.get();
1866  }
1867 
1868  QgsGeos geos( geom );
1869  mLastError.clear();
1870  std::unique_ptr< QgsAbstractGeometry > result( geos.subdivide( maxNodes, &mLastError ) );
1871  if ( !result )
1872  {
1873  QgsGeometry geom;
1874  geom.mLastError = mLastError;
1875  return geom;
1876  }
1877  return QgsGeometry( std::move( result ) );
1878 }
1879 
1881 {
1882  if ( !d->geometry )
1883  {
1884  return QgsGeometry();
1885  }
1886 
1887  QgsGeometry line = *this;
1889  line = QgsGeometry( d->geometry->boundary() );
1890 
1891  QgsGeos geos( line.geometry() );
1892  mLastError.clear();
1893  std::unique_ptr< QgsAbstractGeometry > result( geos.interpolate( distance, &mLastError ) );
1894  if ( !result )
1895  {
1896  QgsGeometry geom;
1897  geom.mLastError = mLastError;
1898  return geom;
1899  }
1900  return QgsGeometry( std::move( result ) );
1901 }
1902 
1903 double QgsGeometry::lineLocatePoint( const QgsGeometry &point ) const
1904 {
1905  if ( type() != QgsWkbTypes::LineGeometry )
1906  return -1;
1907 
1908  if ( QgsWkbTypes::flatType( point.wkbType() ) != QgsWkbTypes::Point )
1909  return -1;
1910 
1911  QgsGeometry segmentized = *this;
1913  {
1914  segmentized = QgsGeometry( static_cast< QgsCurve * >( d->geometry.get() )->segmentize() );
1915  }
1916 
1917  QgsGeos geos( d->geometry.get() );
1918  mLastError.clear();
1919  return geos.lineLocatePoint( *( static_cast< QgsPoint * >( point.d->geometry.get() ) ), &mLastError );
1920 }
1921 
1923 {
1924  if ( !d->geometry )
1925  return 0.0;
1926 
1927  // always operate on segmentized geometries
1928  QgsGeometry segmentized = *this;
1930  {
1931  segmentized = QgsGeometry( static_cast< QgsCurve * >( d->geometry.get() )->segmentize() );
1932  }
1933 
1934  QgsVertexId previous;
1935  QgsVertexId next;
1936  if ( !QgsGeometryUtils::verticesAtDistance( *segmentized.geometry(), distance, previous, next ) )
1937  return 0.0;
1938 
1939  if ( previous == next )
1940  {
1941  // distance coincided exactly with a vertex
1942  QgsVertexId v2 = previous;
1943  QgsVertexId v1;
1944  QgsVertexId v3;
1945  QgsGeometryUtils::adjacentVertices( *segmentized.geometry(), v2, v1, v3 );
1946  if ( v1.isValid() && v3.isValid() )
1947  {
1948  QgsPoint p1 = segmentized.geometry()->vertexAt( v1 );
1949  QgsPoint p2 = segmentized.geometry()->vertexAt( v2 );
1950  QgsPoint p3 = segmentized.geometry()->vertexAt( v3 );
1951  double angle1 = QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1952  double angle2 = QgsGeometryUtils::lineAngle( p2.x(), p2.y(), p3.x(), p3.y() );
1953  return QgsGeometryUtils::averageAngle( angle1, angle2 );
1954  }
1955  else if ( v3.isValid() )
1956  {
1957  QgsPoint p1 = segmentized.geometry()->vertexAt( v2 );
1958  QgsPoint p2 = segmentized.geometry()->vertexAt( v3 );
1959  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1960  }
1961  else
1962  {
1963  QgsPoint p1 = segmentized.geometry()->vertexAt( v1 );
1964  QgsPoint p2 = segmentized.geometry()->vertexAt( v2 );
1965  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1966  }
1967  }
1968  else
1969  {
1970  QgsPoint p1 = segmentized.geometry()->vertexAt( previous );
1971  QgsPoint p2 = segmentized.geometry()->vertexAt( next );
1972  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1973  }
1974 }
1975 
1977 {
1978  if ( !d->geometry || geometry.isNull() )
1979  {
1980  return QgsGeometry();
1981  }
1982 
1983  QgsGeos geos( d->geometry.get() );
1984 
1985  mLastError.clear();
1986  std::unique_ptr< QgsAbstractGeometry > resultGeom( geos.intersection( geometry.d->geometry.get(), &mLastError ) );
1987 
1988  if ( !resultGeom )
1989  {
1990  QgsGeometry geom;
1991  geom.mLastError = mLastError;
1992  return geom;
1993  }
1994 
1995  return QgsGeometry( std::move( resultGeom ) );
1996 }
1997 
1999 {
2000  if ( !d->geometry || geometry.isNull() )
2001  {
2002  return QgsGeometry();
2003  }
2004 
2005  QgsGeos geos( d->geometry.get() );
2006  mLastError.clear();
2007  std::unique_ptr< QgsAbstractGeometry > resultGeom( geos.combine( geometry.d->geometry.get(), &mLastError ) );
2008  if ( !resultGeom )
2009  {
2010  QgsGeometry geom;
2011  geom.mLastError = mLastError;
2012  return geom;
2013  }
2014  return QgsGeometry( std::move( resultGeom ) );
2015 }
2016 
2018 {
2019  if ( !d->geometry )
2020  {
2021  return QgsGeometry();
2022  }
2023 
2024  if ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::LineString )
2025  {
2026  // special case - a single linestring was passed
2027  return QgsGeometry( *this );
2028  }
2029 
2030  QgsGeos geos( d->geometry.get() );
2031  mLastError.clear();
2032  QgsGeometry result = geos.mergeLines( &mLastError );
2033  result.mLastError = mLastError;
2034  return result;
2035 }
2036 
2038 {
2039  if ( !d->geometry || geometry.isNull() )
2040  {
2041  return QgsGeometry();
2042  }
2043 
2044  QgsGeos geos( d->geometry.get() );
2045 
2046  mLastError.clear();
2047  std::unique_ptr< QgsAbstractGeometry > resultGeom( geos.difference( geometry.d->geometry.get(), &mLastError ) );
2048  if ( !resultGeom )
2049  {
2050  QgsGeometry geom;
2051  geom.mLastError = mLastError;
2052  return geom;
2053  }
2054  return QgsGeometry( std::move( resultGeom ) );
2055 }
2056 
2058 {
2059  if ( !d->geometry || geometry.isNull() )
2060  {
2061  return QgsGeometry();
2062  }
2063 
2064  QgsGeos geos( d->geometry.get() );
2065 
2066  mLastError.clear();
2067  std::unique_ptr< QgsAbstractGeometry > resultGeom( geos.symDifference( geometry.d->geometry.get(), &mLastError ) );
2068  if ( !resultGeom )
2069  {
2070  QgsGeometry geom;
2071  geom.mLastError = mLastError;
2072  return geom;
2073  }
2074  return QgsGeometry( std::move( resultGeom ) );
2075 }
2076 
2077 QgsGeometry QgsGeometry::extrude( double x, double y )
2078 {
2079  QgsInternalGeometryEngine engine( *this );
2080 
2081  return engine.extrude( x, y );
2082 }
2083 
2084 QByteArray QgsGeometry::exportToWkb() const
2085 {
2086  return d->geometry ? d->geometry->asWkb() : QByteArray();
2087 }
2088 
2089 QList<QgsGeometry> QgsGeometry::asGeometryCollection() const
2090 {
2091  QList<QgsGeometry> geometryList;
2092  if ( !d->geometry )
2093  {
2094  return geometryList;
2095  }
2096 
2098  if ( gc )
2099  {
2100  int numGeom = gc->numGeometries();
2101  geometryList.reserve( numGeom );
2102  for ( int i = 0; i < numGeom; ++i )
2103  {
2104  geometryList.append( QgsGeometry( gc->geometryN( i )->clone() ) );
2105  }
2106  }
2107  else //a singlepart geometry
2108  {
2109  geometryList.append( QgsGeometry( d->geometry->clone() ) );
2110  }
2111 
2112  return geometryList;
2113 }
2114 
2115 QPointF QgsGeometry::asQPointF() const
2116 {
2117  QgsPointXY point = asPoint();
2118  return point.toQPointF();
2119 }
2120 
2121 QPolygonF QgsGeometry::asQPolygonF() const
2122 {
2123  QPolygonF result;
2124  QgsPolyline polyline;
2126  if ( type == QgsWkbTypes::LineString || type == QgsWkbTypes::LineString25D )
2127  {
2128  polyline = asPolyline();
2129  }
2130  else if ( type == QgsWkbTypes::Polygon || type == QgsWkbTypes::Polygon25D )
2131  {
2132  QgsPolygon polygon = asPolygon();
2133  if ( polygon.empty() )
2134  return result;
2135  polyline = polygon.at( 0 );
2136  }
2137  else
2138  {
2139  return result;
2140  }
2141 
2142  for ( const QgsPointXY &p : qgis::as_const( polyline ) )
2143  {
2144  result << p.toQPointF();
2145  }
2146  return result;
2147 }
2148 
2149 bool QgsGeometry::deleteRing( int ringNum, int partNum )
2150 {
2151  if ( !d->geometry )
2152  {
2153  return false;
2154  }
2155 
2156  detach();
2157  bool ok = QgsGeometryEditUtils::deleteRing( d->geometry.get(), ringNum, partNum );
2158  return ok;
2159 }
2160 
2161 bool QgsGeometry::deletePart( int partNum )
2162 {
2163  if ( !d->geometry )
2164  {
2165  return false;
2166  }
2167 
2168  if ( !isMultipart() && partNum < 1 )
2169  {
2170  setGeometry( nullptr );
2171  return true;
2172  }
2173 
2174  detach();
2175  bool ok = QgsGeometryEditUtils::deletePart( d->geometry.get(), partNum );
2176  return ok;
2177 }
2178 
2179 int QgsGeometry::avoidIntersections( const QList<QgsVectorLayer *> &avoidIntersectionsLayers, const QHash<QgsVectorLayer *, QSet<QgsFeatureId> > &ignoreFeatures )
2180 {
2181  if ( !d->geometry )
2182  {
2183  return 1;
2184  }
2185 
2186  std::unique_ptr< QgsAbstractGeometry > diffGeom = QgsGeometryEditUtils::avoidIntersections( *( d->geometry ), avoidIntersectionsLayers, ignoreFeatures );
2187  if ( diffGeom )
2188  {
2189  reset( std::move( diffGeom ) );
2190  }
2191  return 0;
2192 }
2193 
2194 
2196 {
2197  if ( !d->geometry )
2198  return QgsGeometry();
2199 
2200  mLastError.clear();
2201  std::unique_ptr< QgsAbstractGeometry > g( _qgis_lwgeom_make_valid( d->geometry.get(), mLastError ) );
2202 
2203  QgsGeometry result = QgsGeometry( std::move( g ) );
2204  result.mLastError = mLastError;
2205  return result;
2206 }
2207 
2208 
2209 void QgsGeometry::validateGeometry( QList<QgsGeometry::Error> &errors, ValidationMethod method ) const
2210 {
2211  QgsGeometryValidator::validateGeometry( *this, errors, method );
2212 }
2213 
2215 {
2216  if ( !d->geometry )
2217  {
2218  return false;
2219  }
2220 
2221  QgsGeos geos( d->geometry.get() );
2222  mLastError.clear();
2223  return geos.isValid( &mLastError );
2224 }
2225 
2227 {
2228  if ( !d->geometry )
2229  return false;
2230 
2231  QgsGeos geos( d->geometry.get() );
2232  mLastError.clear();
2233  return geos.isSimple( &mLastError );
2234 }
2235 
2237 {
2238  if ( !d->geometry || !g.d->geometry )
2239  {
2240  return false;
2241  }
2242 
2243  QgsGeos geos( d->geometry.get() );
2244  mLastError.clear();
2245  return geos.isEqual( g.d->geometry.get(), &mLastError );
2246 }
2247 
2248 QgsGeometry QgsGeometry::unaryUnion( const QList<QgsGeometry> &geometries )
2249 {
2250  QgsGeos geos( nullptr );
2251 
2252  QString error;
2253  std::unique_ptr< QgsAbstractGeometry > geom( geos.combine( geometries, &error ) );
2254  QgsGeometry result( std::move( geom ) );
2255  result.mLastError = error;
2256  return result;
2257 }
2258 
2259 QgsGeometry QgsGeometry::polygonize( const QList<QgsGeometry> &geometryList )
2260 {
2261  QgsGeos geos( nullptr );
2262 
2263  QList<const QgsAbstractGeometry *> geomV2List;
2264  for ( const QgsGeometry &g : geometryList )
2265  {
2266  if ( !( g.isNull() ) )
2267  {
2268  geomV2List.append( g.geometry() );
2269  }
2270  }
2271 
2272  QString error;
2273  QgsGeometry result = geos.polygonize( geomV2List, &error );
2274  result.mLastError = error;
2275  return result;
2276 }
2277 
2279 {
2281  {
2282  return;
2283  }
2284 
2285  std::unique_ptr< QgsAbstractGeometry > straightGeom( d->geometry->segmentize() );
2286  reset( std::move( straightGeom ) );
2287 }
2288 
2290 {
2291  if ( !d->geometry )
2292  {
2293  return false;
2294  }
2295 
2296  return d->geometry->hasCurvedSegments();
2297 }
2298 
2300 {
2301  if ( !d->geometry )
2302  {
2304  }
2305 
2306  detach();
2307  d->geometry->transform( ct );
2308  return QgsGeometry::Success;
2309 }
2310 
2312 {
2313  if ( !d->geometry )
2314  {
2316  }
2317 
2318  detach();
2319  d->geometry->transform( ct );
2320  return QgsGeometry::Success;
2321 }
2322 
2324 {
2325  if ( d->geometry )
2326  {
2327  detach();
2328  d->geometry->transform( mtp.transform() );
2329  }
2330 }
2331 
2333 {
2334  if ( !d->geometry || rectangle.isNull() || rectangle.isEmpty() )
2335  {
2336  return QgsGeometry();
2337  }
2338 
2339  QgsGeos geos( d->geometry.get() );
2340  mLastError.clear();
2341  std::unique_ptr< QgsAbstractGeometry > resultGeom = geos.clip( rectangle, &mLastError );
2342  if ( !resultGeom )
2343  {
2344  QgsGeometry result;
2345  result.mLastError = mLastError;
2346  return result;
2347  }
2348  return QgsGeometry( std::move( resultGeom ) );
2349 }
2350 
2351 void QgsGeometry::draw( QPainter &p ) const
2352 {
2353  if ( d->geometry )
2354  {
2355  d->geometry->draw( p );
2356  }
2357 }
2358 
2359 static bool vertexIndexInfo( const QgsAbstractGeometry *g, int vertexIndex, int &partIndex, int &ringIndex, int &vertex )
2360 {
2361  if ( vertexIndex < 0 )
2362  return false; // clearly something wrong
2363 
2364  if ( const QgsGeometryCollection *geomCollection = qgsgeometry_cast<const QgsGeometryCollection *>( g ) )
2365  {
2366  partIndex = 0;
2367  int offset = 0;
2368  for ( int i = 0; i < geomCollection->numGeometries(); ++i )
2369  {
2370  const QgsAbstractGeometry *part = geomCollection->geometryN( i );
2371 
2372  // count total number of vertices in the part
2373  int numPoints = 0;
2374  for ( int k = 0; k < part->ringCount(); ++k )
2375  numPoints += part->vertexCount( 0, k );
2376 
2377  if ( vertexIndex < numPoints )
2378  {
2379  int nothing;
2380  return vertexIndexInfo( part, vertexIndex, nothing, ringIndex, vertex ); // set ring_index + index
2381  }
2382  vertexIndex -= numPoints;
2383  offset += numPoints;
2384  partIndex++;
2385  }
2386  }
2387  else if ( const QgsCurvePolygon *curvePolygon = qgsgeometry_cast<const QgsCurvePolygon *>( g ) )
2388  {
2389  const QgsCurve *ring = curvePolygon->exteriorRing();
2390  if ( vertexIndex < ring->numPoints() )
2391  {
2392  partIndex = 0;
2393  ringIndex = 0;
2394  vertex = vertexIndex;
2395  return true;
2396  }
2397  vertexIndex -= ring->numPoints();
2398  ringIndex = 1;
2399  for ( int i = 0; i < curvePolygon->numInteriorRings(); ++i )
2400  {
2401  const QgsCurve *ring = curvePolygon->interiorRing( i );
2402  if ( vertexIndex < ring->numPoints() )
2403  {
2404  partIndex = 0;
2405  vertex = vertexIndex;
2406  return true;
2407  }
2408  vertexIndex -= ring->numPoints();
2409  ringIndex += 1;
2410  }
2411  }
2412  else if ( const QgsCurve *curve = qgsgeometry_cast<const QgsCurve *>( g ) )
2413  {
2414  if ( vertexIndex < curve->numPoints() )
2415  {
2416  partIndex = 0;
2417  ringIndex = 0;
2418  vertex = vertexIndex;
2419  return true;
2420  }
2421  }
2422  else if ( qgsgeometry_cast<const QgsPoint *>( g ) )
2423  {
2424  if ( vertexIndex == 0 )
2425  {
2426  partIndex = 0;
2427  ringIndex = 0;
2428  vertex = 0;
2429  return true;
2430  }
2431  }
2432 
2433  return false;
2434 }
2435 
2437 {
2438  if ( !d->geometry )
2439  {
2440  return false;
2441  }
2442 
2443  id.type = QgsVertexId::SegmentVertex;
2444 
2445  bool res = vertexIndexInfo( d->geometry.get(), nr, id.part, id.ring, id.vertex );
2446  if ( !res )
2447  return false;
2448 
2449  // now let's find out if it is a straight or circular segment
2450  const QgsAbstractGeometry *g = d->geometry.get();
2451  if ( const QgsGeometryCollection *geomCollection = qgsgeometry_cast<const QgsGeometryCollection *>( g ) )
2452  {
2453  g = geomCollection->geometryN( id.part );
2454  }
2455 
2456  if ( const QgsCurvePolygon *curvePolygon = qgsgeometry_cast<const QgsCurvePolygon *>( g ) )
2457  {
2458  g = id.ring == 0 ? curvePolygon->exteriorRing() : curvePolygon->interiorRing( id.ring - 1 );
2459  }
2460 
2461  if ( const QgsCurve *curve = qgsgeometry_cast<const QgsCurve *>( g ) )
2462  {
2463  QgsPoint p;
2464  res = curve->pointAt( id.vertex, p, id.type );
2465  if ( !res )
2466  return false;
2467  }
2468 
2469  return true;
2470 }
2471 
2473 {
2474  if ( !d->geometry )
2475  {
2476  return -1;
2477  }
2478 
2479  QgsCoordinateSequence coords = d->geometry->coordinateSequence();
2480 
2481  int vertexCount = 0;
2482  for ( int part = 0; part < coords.size(); ++part )
2483  {
2484  const QgsRingSequence &featureCoords = coords.at( part );
2485  for ( int ring = 0; ring < featureCoords.size(); ++ring )
2486  {
2487  const QgsPointSequence &ringCoords = featureCoords.at( ring );
2488  for ( int vertex = 0; vertex < ringCoords.size(); ++vertex )
2489  {
2490  if ( vertex == id.vertex && ring == id.ring && part == id.part )
2491  {
2492  return vertexCount;
2493  }
2494  ++vertexCount;
2495  }
2496  }
2497  }
2498  return -1;
2499 }
2500 
2501 QString QgsGeometry::lastError() const
2502 {
2503  return mLastError;
2504 }
2505 
2506 void QgsGeometry::convertPointList( const QList<QgsPointXY> &input, QgsPointSequence &output )
2507 {
2508  output.clear();
2509  for ( const QgsPointXY &p : input )
2510  {
2511  output.append( QgsPoint( p ) );
2512  }
2513 }
2514 
2515 void QgsGeometry::convertPointList( const QgsPointSequence &input, QList<QgsPointXY> &output )
2516 {
2517  output.clear();
2518  for ( const QgsPoint &p : input )
2519  {
2520  output.append( QgsPointXY( p.x(), p.y() ) );
2521  }
2522 }
2523 
2524 QgsGeometry::operator bool() const
2525 {
2526  return d->geometry.get();
2527 }
2528 
2529 void QgsGeometry::convertToPolyline( const QgsPointSequence &input, QgsPolyline &output )
2530 {
2531  output.clear();
2532  output.resize( input.size() );
2533 
2534  for ( int i = 0; i < input.size(); ++i )
2535  {
2536  const QgsPoint &pt = input.at( i );
2537  output[i].setX( pt.x() );
2538  output[i].setY( pt.y() );
2539  }
2540 }
2541 
2542 void QgsGeometry::convertPolygon( const QgsPolygonV2 &input, QgsPolygon &output )
2543 {
2544  output.clear();
2545  QgsCoordinateSequence coords = input.coordinateSequence();
2546  if ( coords.empty() )
2547  {
2548  return;
2549  }
2550  const QgsRingSequence &rings = coords[0];
2551  output.resize( rings.size() );
2552  for ( int i = 0; i < rings.size(); ++i )
2553  {
2554  convertToPolyline( rings[i], output[i] );
2555  }
2556 }
2557 
2558 GEOSContextHandle_t QgsGeometry::getGEOSHandler()
2559 {
2560  return QgsGeos::getGEOSHandler();
2561 }
2562 
2564 {
2565  return QgsGeometry( qgis::make_unique< QgsPoint >( point.x(), point.y() ) );
2566 }
2567 
2568 QgsGeometry QgsGeometry::fromQPolygonF( const QPolygonF &polygon )
2569 {
2570  if ( polygon.isClosed() )
2571  {
2573  }
2574  else
2575  {
2577  }
2578 }
2579 
2581 {
2582  QgsPolygon result;
2583  result << createPolylineFromQPolygonF( polygon );
2584  return result;
2585 }
2586 
2588 {
2589  QgsPolyline result;
2590  for ( const QPointF &p : polygon )
2591  {
2592  result.append( QgsPointXY( p ) );
2593  }
2594  return result;
2595 }
2596 
2597 bool QgsGeometry::compare( const QgsPolyline &p1, const QgsPolyline &p2, double epsilon )
2598 {
2599  if ( p1.count() != p2.count() )
2600  return false;
2601 
2602  for ( int i = 0; i < p1.count(); ++i )
2603  {
2604  if ( !p1.at( i ).compare( p2.at( i ), epsilon ) )
2605  return false;
2606  }
2607  return true;
2608 }
2609 
2610 bool QgsGeometry::compare( const QgsPolygon &p1, const QgsPolygon &p2, double epsilon )
2611 {
2612  if ( p1.count() != p2.count() )
2613  return false;
2614 
2615  for ( int i = 0; i < p1.count(); ++i )
2616  {
2617  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
2618  return false;
2619  }
2620  return true;
2621 }
2622 
2623 
2624 bool QgsGeometry::compare( const QgsMultiPolygon &p1, const QgsMultiPolygon &p2, double epsilon )
2625 {
2626  if ( p1.count() != p2.count() )
2627  return false;
2628 
2629  for ( int i = 0; i < p1.count(); ++i )
2630  {
2631  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
2632  return false;
2633  }
2634  return true;
2635 }
2636 
2637 QgsGeometry QgsGeometry::smooth( const unsigned int iterations, const double offset, double minimumDistance, double maxAngle ) const
2638 {
2639  if ( !d->geometry || d->geometry->isEmpty() )
2640  return QgsGeometry();
2641 
2642  QgsGeometry geom = *this;
2644  geom = QgsGeometry( d->geometry->segmentize() );
2645 
2646  switch ( QgsWkbTypes::flatType( geom.wkbType() ) )
2647  {
2648  case QgsWkbTypes::Point:
2650  //can't smooth a point based geometry
2651  return geom;
2652 
2654  {
2655  QgsLineString *lineString = static_cast< QgsLineString * >( d->geometry.get() );
2656  return QgsGeometry( smoothLine( *lineString, iterations, offset, minimumDistance, maxAngle ) );
2657  }
2658 
2660  {
2661  QgsMultiLineString *multiLine = static_cast< QgsMultiLineString * >( d->geometry.get() );
2662 
2663  std::unique_ptr< QgsMultiLineString > resultMultiline = qgis::make_unique< QgsMultiLineString> ();
2664  for ( int i = 0; i < multiLine->numGeometries(); ++i )
2665  {
2666  resultMultiline->addGeometry( smoothLine( *( static_cast< QgsLineString * >( multiLine->geometryN( i ) ) ), iterations, offset, minimumDistance, maxAngle ).release() );
2667  }
2668  return QgsGeometry( std::move( resultMultiline ) );
2669  }
2670 
2671  case QgsWkbTypes::Polygon:
2672  {
2673  QgsPolygonV2 *poly = static_cast< QgsPolygonV2 * >( d->geometry.get() );
2674  return QgsGeometry( smoothPolygon( *poly, iterations, offset, minimumDistance, maxAngle ) );
2675  }
2676 
2678  {
2679  QgsMultiPolygonV2 *multiPoly = static_cast< QgsMultiPolygonV2 * >( d->geometry.get() );
2680 
2681  std::unique_ptr< QgsMultiPolygonV2 > resultMultiPoly = qgis::make_unique< QgsMultiPolygonV2 >();
2682  for ( int i = 0; i < multiPoly->numGeometries(); ++i )
2683  {
2684  resultMultiPoly->addGeometry( smoothPolygon( *( static_cast< QgsPolygonV2 * >( multiPoly->geometryN( i ) ) ), iterations, offset, minimumDistance, maxAngle ).release() );
2685  }
2686  return QgsGeometry( std::move( resultMultiPoly ) );
2687  }
2688 
2689  case QgsWkbTypes::Unknown:
2690  default:
2691  return QgsGeometry( *this );
2692  }
2693 }
2694 
2695 inline QgsPoint interpolatePointOnLine( const QgsPoint &p1, const QgsPoint &p2, const double offset )
2696 {
2697  double deltaX = p2.x() - p1.x();
2698  double deltaY = p2.y() - p1.y();
2699  return QgsPoint( p1.x() + deltaX * offset, p1.y() + deltaY * offset );
2700 }
2701 
2702 std::unique_ptr< QgsLineString > smoothCurve( const QgsLineString &line, const unsigned int iterations,
2703  const double offset, double squareDistThreshold, double maxAngleRads,
2704  bool isRing )
2705 {
2706  std::unique_ptr< QgsLineString > result = qgis::make_unique< QgsLineString >( line );
2707  for ( unsigned int iteration = 0; iteration < iterations; ++iteration )
2708  {
2709  QgsPointSequence outputLine;
2710  outputLine.reserve( 2 * ( result->numPoints() - 1 ) );
2711  bool skipFirst = false;
2712  bool skipLast = false;
2713  if ( isRing )
2714  {
2715  QgsPoint p1 = result->pointN( result->numPoints() - 2 );
2716  QgsPoint p2 = result->pointN( 0 );
2717  QgsPoint p3 = result->pointN( 1 );
2718  double angle = QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(),
2719  p3.x(), p3.y() );
2720  angle = std::fabs( M_PI - angle );
2721  skipFirst = angle > maxAngleRads;
2722  }
2723  for ( int i = 0; i < result->numPoints() - 1; i++ )
2724  {
2725  QgsPoint p1 = result->pointN( i );
2726  QgsPoint p2 = result->pointN( i + 1 );
2727 
2728  double angle = M_PI;
2729  if ( i == 0 && isRing )
2730  {
2731  QgsPoint p3 = result->pointN( result->numPoints() - 2 );
2732  angle = QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(),
2733  p3.x(), p3.y() );
2734  }
2735  else if ( i < result->numPoints() - 2 )
2736  {
2737  QgsPoint p3 = result->pointN( i + 2 );
2738  angle = QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(),
2739  p3.x(), p3.y() );
2740  }
2741  else if ( i == result->numPoints() - 2 && isRing )
2742  {
2743  QgsPoint p3 = result->pointN( 1 );
2744  angle = QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(),
2745  p3.x(), p3.y() );
2746  }
2747 
2748  skipLast = angle < M_PI - maxAngleRads || angle > M_PI + maxAngleRads;
2749 
2750  // don't apply distance threshold to first or last segment
2751  if ( i == 0 || i >= result->numPoints() - 2
2752  || QgsGeometryUtils::sqrDistance2D( p1, p2 ) > squareDistThreshold )
2753  {
2754  if ( !isRing )
2755  {
2756  if ( !skipFirst )
2757  outputLine << ( i == 0 ? result->pointN( i ) : interpolatePointOnLine( p1, p2, offset ) );
2758  if ( !skipLast )
2759  outputLine << ( i == result->numPoints() - 2 ? result->pointN( i + 1 ) : interpolatePointOnLine( p1, p2, 1.0 - offset ) );
2760  else
2761  outputLine << p2;
2762  }
2763  else
2764  {
2765  // ring
2766  if ( !skipFirst )
2767  outputLine << interpolatePointOnLine( p1, p2, offset );
2768  else if ( i == 0 )
2769  outputLine << p1;
2770  if ( !skipLast )
2771  outputLine << interpolatePointOnLine( p1, p2, 1.0 - offset );
2772  else
2773  outputLine << p2;
2774  }
2775  }
2776  skipFirst = skipLast;
2777  }
2778 
2779  if ( isRing && outputLine.at( 0 ) != outputLine.at( outputLine.count() - 1 ) )
2780  outputLine << outputLine.at( 0 );
2781 
2782  result->setPoints( outputLine );
2783  }
2784  return result;
2785 }
2786 
2787 std::unique_ptr<QgsLineString> QgsGeometry::smoothLine( const QgsLineString &line, const unsigned int iterations, const double offset, double minimumDistance, double maxAngle ) const
2788 {
2789  double maxAngleRads = maxAngle * M_PI / 180.0;
2790  double squareDistThreshold = minimumDistance > 0 ? minimumDistance * minimumDistance : -1;
2791  return smoothCurve( line, iterations, offset, squareDistThreshold, maxAngleRads, false );
2792 }
2793 
2794 std::unique_ptr<QgsPolygonV2> QgsGeometry::smoothPolygon( const QgsPolygonV2 &polygon, const unsigned int iterations, const double offset, double minimumDistance, double maxAngle ) const
2795 {
2796  double maxAngleRads = maxAngle * M_PI / 180.0;
2797  double squareDistThreshold = minimumDistance > 0 ? minimumDistance * minimumDistance : -1;
2798  std::unique_ptr< QgsPolygonV2 > resultPoly = qgis::make_unique< QgsPolygonV2 >();
2799 
2800  resultPoly->setExteriorRing( smoothCurve( *( static_cast< const QgsLineString *>( polygon.exteriorRing() ) ), iterations, offset,
2801  squareDistThreshold, maxAngleRads, true ).release() );
2802 
2803  for ( int i = 0; i < polygon.numInteriorRings(); ++i )
2804  {
2805  resultPoly->addInteriorRing( smoothCurve( *( static_cast< const QgsLineString *>( polygon.interiorRing( i ) ) ), iterations, offset,
2806  squareDistThreshold, maxAngleRads, true ).release() );
2807  }
2808  return resultPoly;
2809 }
2810 
2811 QgsGeometry QgsGeometry::convertToPoint( bool destMultipart ) const
2812 {
2813  switch ( type() )
2814  {
2816  {
2817  bool srcIsMultipart = isMultipart();
2818 
2819  if ( ( destMultipart && srcIsMultipart ) ||
2820  ( !destMultipart && !srcIsMultipart ) )
2821  {
2822  // return a copy of the same geom
2823  return QgsGeometry( *this );
2824  }
2825  if ( destMultipart )
2826  {
2827  // layer is multipart => make a multipoint with a single point
2828  return fromMultiPoint( QgsMultiPoint() << asPoint() );
2829  }
2830  else
2831  {
2832  // destination is singlepart => make a single part if possible
2833  QgsMultiPoint multiPoint = asMultiPoint();
2834  if ( multiPoint.count() == 1 )
2835  {
2836  return fromPoint( multiPoint[0] );
2837  }
2838  }
2839  return QgsGeometry();
2840  }
2841 
2843  {
2844  // only possible if destination is multipart
2845  if ( !destMultipart )
2846  return QgsGeometry();
2847 
2848  // input geometry is multipart
2849  if ( isMultipart() )
2850  {
2851  const QgsMultiPolyline multiLine = asMultiPolyline();
2852  QgsMultiPoint multiPoint;
2853  for ( const QgsPolyline &l : multiLine )
2854  for ( const QgsPointXY &p : l )
2855  multiPoint << p;
2856  return fromMultiPoint( multiPoint );
2857  }
2858  // input geometry is not multipart: copy directly the line into a multipoint
2859  else
2860  {
2861  QgsPolyline line = asPolyline();
2862  if ( !line.isEmpty() )
2863  return fromMultiPoint( line );
2864  }
2865  return QgsGeometry();
2866  }
2867 
2869  {
2870  // can only transform if destination is multipoint
2871  if ( !destMultipart )
2872  return QgsGeometry();
2873 
2874  // input geometry is multipart: make a multipoint from multipolygon
2875  if ( isMultipart() )
2876  {
2877  const QgsMultiPolygon multiPolygon = asMultiPolygon();
2878  QgsMultiPoint multiPoint;
2879  for ( const QgsPolygon &poly : multiPolygon )
2880  for ( const QgsPolyline &line : poly )
2881  for ( const QgsPointXY &pt : line )
2882  multiPoint << pt;
2883  return fromMultiPoint( multiPoint );
2884  }
2885  // input geometry is not multipart: make a multipoint from polygon
2886  else
2887  {
2888  const QgsPolygon polygon = asPolygon();
2889  QgsMultiPoint multiPoint;
2890  for ( const QgsPolyline &line : polygon )
2891  for ( const QgsPointXY &pt : line )
2892  multiPoint << pt;
2893  return fromMultiPoint( multiPoint );
2894  }
2895  }
2896 
2897  default:
2898  return QgsGeometry();
2899  }
2900 }
2901 
2902 QgsGeometry QgsGeometry::convertToLine( bool destMultipart ) const
2903 {
2904  switch ( type() )
2905  {
2907  {
2908  if ( !isMultipart() )
2909  return QgsGeometry();
2910 
2911  QgsMultiPoint multiPoint = asMultiPoint();
2912  if ( multiPoint.count() < 2 )
2913  return QgsGeometry();
2914 
2915  if ( destMultipart )
2916  return fromMultiPolyline( QgsMultiPolyline() << multiPoint );
2917  else
2918  return fromPolyline( multiPoint );
2919  }
2920 
2922  {
2923  bool srcIsMultipart = isMultipart();
2924 
2925  if ( ( destMultipart && srcIsMultipart ) ||
2926  ( !destMultipart && ! srcIsMultipart ) )
2927  {
2928  // return a copy of the same geom
2929  return QgsGeometry( *this );
2930  }
2931  if ( destMultipart )
2932  {
2933  // destination is multipart => makes a multipoint with a single line
2934  QgsPolyline line = asPolyline();
2935  if ( !line.isEmpty() )
2936  return fromMultiPolyline( QgsMultiPolyline() << line );
2937  }
2938  else
2939  {
2940  // destination is singlepart => make a single part if possible
2941  QgsMultiPolyline multiLine = asMultiPolyline();
2942  if ( multiLine.count() == 1 )
2943  return fromPolyline( multiLine[0] );
2944  }
2945  return QgsGeometry();
2946  }
2947 
2949  {
2950  // input geometry is multipolygon
2951  if ( isMultipart() )
2952  {
2953  const QgsMultiPolygon multiPolygon = asMultiPolygon();
2954  QgsMultiPolyline multiLine;
2955  for ( const QgsPolygon &poly : multiPolygon )
2956  for ( const QgsPolyline &line : poly )
2957  multiLine << line;
2958 
2959  if ( destMultipart )
2960  {
2961  // destination is multipart
2962  return fromMultiPolyline( multiLine );
2963  }
2964  else if ( multiLine.count() == 1 )
2965  {
2966  // destination is singlepart => make a single part if possible
2967  return fromPolyline( multiLine[0] );
2968  }
2969  }
2970  // input geometry is single polygon
2971  else
2972  {
2973  QgsPolygon polygon = asPolygon();
2974  // if polygon has rings
2975  if ( polygon.count() > 1 )
2976  {
2977  // cannot fit a polygon with rings in a single line layer
2978  // TODO: would it be better to remove rings?
2979  if ( destMultipart )
2980  {
2981  const QgsPolygon polygon = asPolygon();
2982  QgsMultiPolyline multiLine;
2983  for ( const QgsPolyline &line : polygon )
2984  multiLine << line;
2985  return fromMultiPolyline( multiLine );
2986  }
2987  }
2988  // no rings
2989  else if ( polygon.count() == 1 )
2990  {
2991  if ( destMultipart )
2992  {
2993  return fromMultiPolyline( polygon );
2994  }
2995  else
2996  {
2997  return fromPolyline( polygon[0] );
2998  }
2999  }
3000  }
3001  return QgsGeometry();
3002  }
3003 
3004  default:
3005  return QgsGeometry();
3006  }
3007 }
3008 
3009 QgsGeometry QgsGeometry::convertToPolygon( bool destMultipart ) const
3010 {
3011  switch ( type() )
3012  {
3014  {
3015  if ( !isMultipart() )
3016  return QgsGeometry();
3017 
3018  QgsMultiPoint multiPoint = asMultiPoint();
3019  if ( multiPoint.count() < 3 )
3020  return QgsGeometry();
3021 
3022  if ( multiPoint.last() != multiPoint.first() )
3023  multiPoint << multiPoint.first();
3024 
3025  QgsPolygon polygon = QgsPolygon() << multiPoint;
3026  if ( destMultipart )
3027  return fromMultiPolygon( QgsMultiPolygon() << polygon );
3028  else
3029  return fromPolygon( polygon );
3030  }
3031 
3033  {
3034  // input geometry is multiline
3035  if ( isMultipart() )
3036  {
3037  QgsMultiPolyline multiLine = asMultiPolyline();
3038  QgsMultiPolygon multiPolygon;
3039  for ( QgsMultiPolyline::iterator multiLineIt = multiLine.begin(); multiLineIt != multiLine.end(); ++multiLineIt )
3040  {
3041  // do not create polygon for a 1 segment line
3042  if ( ( *multiLineIt ).count() < 3 )
3043  return QgsGeometry();
3044  if ( ( *multiLineIt ).count() == 3 && ( *multiLineIt ).first() == ( *multiLineIt ).last() )
3045  return QgsGeometry();
3046 
3047  // add closing node
3048  if ( ( *multiLineIt ).first() != ( *multiLineIt ).last() )
3049  *multiLineIt << ( *multiLineIt ).first();
3050  multiPolygon << ( QgsPolygon() << *multiLineIt );
3051  }
3052  // check that polygons were inserted
3053  if ( !multiPolygon.isEmpty() )
3054  {
3055  if ( destMultipart )
3056  {
3057  return fromMultiPolygon( multiPolygon );
3058  }
3059  else if ( multiPolygon.count() == 1 )
3060  {
3061  // destination is singlepart => make a single part if possible
3062  return fromPolygon( multiPolygon[0] );
3063  }
3064  }
3065  }
3066  // input geometry is single line
3067  else
3068  {
3069  QgsPolyline line = asPolyline();
3070 
3071  // do not create polygon for a 1 segment line
3072  if ( line.count() < 3 )
3073  return QgsGeometry();
3074  if ( line.count() == 3 && line.first() == line.last() )
3075  return QgsGeometry();
3076 
3077  // add closing node
3078  if ( line.first() != line.last() )
3079  line << line.first();
3080 
3081  // destination is multipart
3082  if ( destMultipart )
3083  {
3084  return fromMultiPolygon( QgsMultiPolygon() << ( QgsPolygon() << line ) );
3085  }
3086  else
3087  {
3088  return fromPolygon( QgsPolygon() << line );
3089  }
3090  }
3091  return QgsGeometry();
3092  }
3093 
3095  {
3096  bool srcIsMultipart = isMultipart();
3097 
3098  if ( ( destMultipart && srcIsMultipart ) ||
3099  ( !destMultipart && ! srcIsMultipart ) )
3100  {
3101  // return a copy of the same geom
3102  return QgsGeometry( *this );
3103  }
3104  if ( destMultipart )
3105  {
3106  // destination is multipart => makes a multipoint with a single polygon
3107  QgsPolygon polygon = asPolygon();
3108  if ( !polygon.isEmpty() )
3109  return fromMultiPolygon( QgsMultiPolygon() << polygon );
3110  }
3111  else
3112  {
3113  QgsMultiPolygon multiPolygon = asMultiPolygon();
3114  if ( multiPolygon.count() == 1 )
3115  {
3116  // destination is singlepart => make a single part if possible
3117  return fromPolygon( multiPolygon[0] );
3118  }
3119  }
3120  return QgsGeometry();
3121  }
3122 
3123  default:
3124  return QgsGeometry();
3125  }
3126 }
3127 
3129 {
3130  return new QgsGeos( geometry );
3131 }
3132 
3133 QDataStream &operator<<( QDataStream &out, const QgsGeometry &geometry )
3134 {
3135  out << geometry.exportToWkb();
3136  return out;
3137 }
3138 
3139 QDataStream &operator>>( QDataStream &in, QgsGeometry &geometry )
3140 {
3141  QByteArray byteArray;
3142  in >> byteArray;
3143  if ( byteArray.isEmpty() )
3144  {
3145  geometry.setGeometry( nullptr );
3146  return in;
3147  }
3148 
3149  geometry.fromWkb( byteArray );
3150  return in;
3151 }
Geometry engine misses a method implemented or an error occurred in the geometry engine.
Definition: qgsgeometry.h:108
QgsPolygon asPolygon() const
Returns contents of the geometry as a polygon if wkbType is WKBPolygon, otherwise an empty list...
static std::unique_ptr< QgsAbstractGeometry > geomFromWkb(QgsConstWkbPtr &wkb)
Construct geometry from a WKB string.
const QgsCurve * interiorRing(int i) const
Circle geometry type.
Definition: qgscircle.h:42
QgsGeometry orientedMinimumBoundingBox() const
Returns the oriented minimum bounding box for the geometry, which is the smallest (by area) rotated r...
QgsMultiPolyline asMultiPolyline() const
Returns 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:39
double y
Definition: qgspoint.h:42
OperationResult splitGeometry(const QList< QgsPointXY > &splitLine, QList< QgsGeometry > &newGeometries, bool topological, QList< QgsPointXY > &topologyTestPoints)
Splits this geometry according to a given line.
QgsGeometry combine(const QgsGeometry &geometry) const
Returns a geometry representing all the points in this geometry and other (a union geometry operation...
static std::unique_ptr< QgsAbstractGeometry > geomFromWkbType(QgsWkbTypes::Type t)
Return empty geometry from wkb type.
void points(QgsPointSequence &pt) const override
Returns a list of points within the curve.
double hausdorffDistanceDensify(const QgsGeometry &geom, double densifyFraction) const
Returns the Hausdorff distance between this geometry and geom.
static Type multiType(Type type)
Returns the multi type for a WKB type.
Definition: qgswkbtypes.h:296
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
Tests 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.
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.
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...
Java-style iterator for traversal of vertices of a geometry.
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:557
The source geometry is not multi.
Definition: qgsgeometry.h:111
Nothing happened, without any error.
Definition: qgsgeometry.h:105
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...
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.
OperationResult addPart(const QList< QgsPointXY > &points, QgsWkbTypes::GeometryType geomType=QgsWkbTypes::UnknownGeometry)
Adds a new part to a the geometry.
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.cpp:292
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:48
double area(QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:507
A class to represent a 2D point.
Definition: qgspointxy.h:43
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...
OperationResult rotate(double rotation, const QgsPointXY &center)
Rotate this geometry around the Z axis.
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
Returns interpolated point on line at distance.
Curve polygon geometry type.
bool overlaps(const QgsGeometry &geometry) const
Test for if geometry overlaps another (uses GEOS)
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:94
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...
void validateGeometry(QList< QgsGeometry::Error > &errors, ValidationMethod method=ValidatorQgisInternal) const
Validates geometry and produces a list of geometry errors.
QgsGeometry centroid() const
Returns the center of mass of a geometry.
QgsGeometry()
Constructor.
Definition: qgsgeometry.cpp:56
static std::unique_ptr< QgsMultiLineString > fromMultiPolyline(const QgsMultiPolyline &multiline)
Construct geometry from a multipolyline.
OperationResult reshapeGeometry(const QgsLineString &reshapeLineString)
Replaces a part of this geometry with another line.
Multi point geometry collection.
Definition: qgsmultipoint.h:29
double radius() const
Returns the radius of the circle.
Definition: qgscircle.h:159
static std::unique_ptr< QgsAbstractGeometry > fromPoint(const QgsPointXY &point)
Construct geometry from a point.
QgsGeometry intersection(const QgsGeometry &geometry) const
Returns a geometry representing the points shared by this geometry and other.
QgsPoint center() const
Returns the center point.
Definition: qgsellipse.h:113
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:727
virtual bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const =0
Returns next vertex id and coordinates.
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.
QgsGeometry minimalEnclosingCircle(QgsPointXY &center, double &radius, unsigned int segments=36) const
Returns the minimal enclosing circle for the geometry.
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.
QgsGeometry & operator=(QgsGeometry const &rhs)
Creates a deep copy of the object.
Definition: qgsgeometry.cpp:88
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.
OperationResult
Success or failure of a geometry operation.
Definition: qgsgeometry.h:102
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.cpp:786
bool isGeosEqual(const QgsGeometry &) const
Compares the geometry with another geometry using GEOS.
bool deleteRing(int ringNum, int partNum=0)
Deletes a ring in polygon or multipolygon.
bool isGeosValid() const
Checks validity of the geometry using GEOS.
QgsPolyline asPolyline() const
Returns contents of the geometry as a polyline if wkbType is WKBLineString, otherwise an empty list...
QVector< QgsPointXY > QgsPolyline
Polyline is represented as a vector of points.
Definition: qgsgeometry.h:49
static GEOSContextHandle_t getGEOSHandler()
Definition: qgsgeos.cpp:2680
The input geometry (ring, part, split line, etc.) has not the correct geometry type.
Definition: qgsgeometry.h:107
int numPoints() const override
Returns the number of points in the curve.
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)
Deletes part identified by the part number.
QgsMultiPoint asMultiPoint() const
Returns contents of the geometry as a multi point if wkbType is WKBMultiPoint, otherwise an empty lis...
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:36
Polygon geometry type.
Definition: qgspolygon.h:31
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
Operation succeeded.
Nothing happened, without any error.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:67
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.
static std::unique_ptr< QgsAbstractGeometry > fromGeos(const GEOSGeometry *geos)
Create a geometry from a GEOSGeometry.
Definition: qgsgeos.cpp:1000
bool convertToSingleType()
Converts multi type geometry into single type geometry e.g.
OperationResult addRing(const QList< QgsPointXY > &ring)
Adds a new ring to this geometry.
bool equals(const QgsGeometry &geometry) const
Test for if geometry equals another (uses GEOS)
Utility class for identifying a unique vertex within a geometry.
bool isEmpty() const
Returns true if the rectangle is empty.
QByteArray exportToWkb() const
Export the geometry to WKB.
Geometry collection.
static std::unique_ptr< QgsMultiPointV2 > fromMultiPoint(const QgsMultiPoint &multipoint)
Construct geometry from a multipoint.
QgsPoint interpolatePointOnLine(const QgsPoint &p1, const QgsPoint &p2, const double offset)
static QgsGeometry fromQPointF(QPointF point)
Construct geometry from a QPointF.
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:131
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) ...
OperationResult translate(double dx, double dy)
Translates this geometry by dx, dy.
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:114
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:663
static std::unique_ptr< QgsAbstractGeometry > avoidIntersections(const QgsAbstractGeometry &geom, const QList< QgsVectorLayer *> &avoidIntersectionsLayers, const QHash< QgsVectorLayer *, QSet< QgsFeatureId > > &ignoreFeatures=(QHash< QgsVectorLayer *, QSet< QgsFeatureId > >()))
Alters a geometry so that it avoids intersections with features from all open vector layers...
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:73
T qgsgeometry_cast(const QgsAbstractGeometry *geom)
QgsGeometry offsetCurve(double distance, int segments, JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
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...
static geos::unique_ptr asGeos(const QgsAbstractGeometry *geom, double precision=0)
Definition: qgsgeos.cpp:1213
bool contains(const QgsPoint &point, double epsilon=1E-8) const
Returns true if the circle contains the point.
Definition: qgscircle.cpp:276
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.
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
QString exportToWkt(int precision=17) const
Exports the geometry to WKT.
Method not implemented in geometry engine.
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:35
virtual QgsPolygonV2 * toPolygon(unsigned int segments=36) const
Returns a segmented polygon.
Definition: qgsellipse.cpp:213
QVector< QgsPolyline > QgsPolygon
Polygon: first item of the list is outer ring, inner rings (if any) start from second item...
Definition: qgsgeometry.h:56
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.
QgsCoordinateSequence coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
The vertex_iterator class provides STL-style iterator for vertices.
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:98
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
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.
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:105
Error occurred while creating a noded geometry.
double x
Definition: qgspointxy.h:47
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.
static QgsGeometry polygonize(const QList< const QgsAbstractGeometry *> &geometries, QString *errorMsg=nullptr)
Creates a GeometryCollection geometry containing possible polygons formed from the constituent linewo...
Definition: qgsgeos.cpp:2120
Error occurred in the geometry engine.
void draw(QPainter &p) const
Draws the geometry onto a QPainter.
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.
Contains geos related utilities and functions.
Definition: qgsgeos.h:36
void setX(double x)
Sets the point&#39;s x-coordinate.
Definition: qgspoint.h:192
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:119
QgsAbstractGeometry * combine(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Calculate the combination of this and geom.
Definition: qgsgeos.cpp:306
QPolygonF asQPolygonF() const
Returns contents of the geometry as a QPolygonF.
QVector< QgsPolyline > QgsMultiPolyline
A collection of QgsPolylines that share a common collection of attributes.
Definition: qgsgeometry.h:66
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:104
BufferSide
Side of line to buffer.
Definition: qgsgeometry.h:720
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:137
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.
static QgsGeometry::OperationResult addPart(QgsAbstractGeometry *geometry, std::unique_ptr< QgsAbstractGeometry > part)
Add a part to multi type geometry.
int partCount() const override
Returns count of parts contained in the geometry.
static std::unique_ptr< QgsPolygonV2 > fromPolygon(const QgsPolygon &polygon)
Construct geometry from a polygon.
QString lastError() const
Returns an error string referring to the last error encountered either when this geometry was created...
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.
static double sqrDistance2D(const QgsPoint &pt1, const QgsPoint &pt2)
Returns the squared 2D distance between two points.
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
static std::unique_ptr< QgsAbstractGeometry > geomFromWkt(const QString &text)
Construct geometry from a WKT string.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
double hausdorffDistance(const QgsGeometry &geom) const
Returns the Hausdorff distance between this geometry and geom.
OperationResult transform(const QgsCoordinateTransform &ct)
Transforms this geometry as described by CoordinateTransform ct.
QgsPointXY asPoint() const
Returns contents of the geometry as a point if wkbType is WKBPoint, otherwise returns [0...
The base geometry on which the operation is done is invalid or empty.
Definition: qgsgeometry.h:106
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.
QString exportToGeoJSON(int precision=17) const
Exports the geometry to GeoJSON.
static bool isCurvedType(Type type)
Returns true if the WKB type is a curved type or can contain curved geometries.
Definition: qgswkbtypes.h:606
GEOSGeometry * exportToGeos(double precision=0) const
Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destr...
QgsMultiPolygon asMultiPolygon() const
Returns contents of the geometry as a multi polygon if wkbType is WKBMultiPolygon, otherwise an empty list.
static void adjacentVertices(const QgsAbstractGeometry &geom, QgsVertexId atVertex, QgsVertexId &beforeVertex, QgsVertexId &afterVertex)
Returns vertices adjacent to a specified vertex within a geometry.
QgsGeometry makeValid() const
Attempts to make an invalid geometry valid without losing vertices.
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.
std::unique_ptr< QgsAbstractGeometry > subdivide(int maxNodes, QString *errorMsg=nullptr) const
Subdivides the geometry.
Definition: qgsgeos.cpp:286
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:41
QPointF asQPointF() const
Returns contents of the geometry as a QPointF if wkbType is WKBPoint, otherwise returns a null QPoint...
ValidationMethod
Available methods for validating geometries.
Definition: qgsgeometry.h:1219
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 vertices 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...
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.
std::unique_ptr< QgsAbstractGeometry > _qgis_lwgeom_make_valid(const QgsAbstractGeometry *lwgeom_in, QString &errorMessage)
Implementation of QgsGeometry::makeValid(). Not a public API.
static QgsCircle minimalCircleFrom3Points(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon=1E-8)
Constructs the smallest circle from 3 points.
Definition: qgscircle.cpp:192
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.
QgsGeometry singleSidedBuffer(double distance, int segments, BufferSide side, JoinStyle joinStyle=JoinStyleRound, double miterLimit=2.0) const
Returns a single sided buffer for a (multi)line geometry.
The input is not valid.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:109
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
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:114
static QgsGeometry fromPoint(const QgsPointXY &point)
Creates a new geometry from a QgsPointXY object.
QgsGeometry makeDifference(const QgsGeometry &other) const
Returns the geometry formed by modifying this geometry such that it does not intersect the other geom...
static std::unique_ptr< QgsAbstractGeometry > fromPolyline(const QgsPolyline &polyline)
Construct geometry from a polyline.
QgsVertexIterator vertices() const
Returns Java-style iterator for traversal of vertices of the geometry.
static QgsCircle from2Points(const QgsPoint &pt1, const QgsPoint &pt2)
Constructs a circle by 2 points on the circle.
Definition: qgscircle.cpp:37
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.
EngineOperationResult
Success or failure of a geometry operation.
Operation succeeded.
Definition: qgsgeometry.h:104
JoinStyle
Join styles for buffers.
Definition: qgsgeometry.h:735
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...
bool contains(const QgsPointXY *p) const
Tests 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.
Represents a vector layer which manages a vector based data sets.
QgsAbstractGeometry::vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry...
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:427
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.
static QgsGeometry polygonize(const QList< QgsGeometry > &geometries)
Creates a GeometryCollection geometry containing possible polygons formed from the constituent linewo...
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
The geometry on which the operation occurs is not valid.
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.
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the 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
Tests for if geometry is disjoint of another (uses GEOS)
static std::unique_ptr< QgsMultiPolygonV2 > fromMultiPolygon(const QgsMultiPolygon &multipoly)
Construct geometry from a multipolygon.
static QgsGeometry::OperationResult addRing(QgsAbstractGeometry *geometry, std::unique_ptr< QgsCurve > ring)
Add an interior ring to a 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...
std::unique_ptr< QgsAbstractGeometry > geometry
Definition: qgsgeometry.cpp:53
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:138
static QgsGeometry fromMultiPolyline(const QgsMultiPolyline &multiline)
Creates a new geometry from a QgsMultiPolyline object.
std::unique_ptr< QgsLineString > smoothCurve(const QgsLineString &line, const unsigned int iterations, const double offset, double squareDistThreshold, double maxAngleRads, bool isRing)
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.
double x
Definition: qgspoint.h:41
QgsGeometry difference(const QgsGeometry &geometry) const
Returns a geometry representing the points making up this geometry that do not make up other...