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