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