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