QGIS API Documentation  2.99.0-Master (d55fa22)
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 
819 int QgsGeometry::reshapeGeometry( const QList<QgsPoint> &reshapeWithLine )
820 {
821  if ( !d->geometry )
822  {
823  return 0;
824  }
825 
826  QgsLineString reshapeLineString( reshapeWithLine );
827 
828  QgsGeos geos( d->geometry );
829  int errorCode = 0;
830  QgsAbstractGeometry *geom = geos.reshapeGeometry( reshapeLineString, &errorCode );
831  if ( errorCode == 0 && geom )
832  {
833  detach( false );
834  delete d->geometry;
835  d->geometry = geom;
836  return 0;
837  }
838  return errorCode;
839 }
840 
842 {
843  if ( !d->geometry || !other->d->geometry )
844  {
845  return 0;
846  }
847 
848  QgsGeos geos( d->geometry );
849 
850  QgsAbstractGeometry *diffGeom = geos.intersection( *( other->geometry() ) );
851  if ( !diffGeom )
852  {
853  return 1;
854  }
855 
856  detach( false );
857 
858  delete d->geometry;
859  d->geometry = diffGeom;
860  return 0;
861 }
862 
864 {
865  if ( !d->geometry || other.isNull() )
866  {
867  return QgsGeometry();
868  }
869 
870  QgsGeos geos( d->geometry );
871 
872  QgsAbstractGeometry *diffGeom = geos.intersection( *other.geometry() );
873  if ( !diffGeom )
874  {
875  return QgsGeometry();
876  }
877 
878  return QgsGeometry( diffGeom );
879 }
880 
882 {
883  if ( d->geometry )
884  {
885  return d->geometry->boundingBox();
886  }
887  return QgsRectangle();
888 }
889 
890 QgsGeometry QgsGeometry::orientedMinimumBoundingBox( double &area, double &angle, double &width, double &height ) const
891 {
892  QgsRectangle minRect;
893  area = DBL_MAX;
894  angle = 0;
895  width = DBL_MAX;
896  height = DBL_MAX;
897 
898  if ( !d->geometry || d->geometry->nCoordinates() < 2 )
899  return QgsGeometry();
900 
901  QgsGeometry hull = convexHull();
902  if ( hull.isNull() )
903  return QgsGeometry();
904 
905  QgsVertexId vertexId;
906  QgsPointV2 pt0;
907  QgsPointV2 pt1;
908  QgsPointV2 pt2;
909  // get first point
910  hull.geometry()->nextVertex( vertexId, pt0 );
911  pt1 = pt0;
912  double prevAngle = 0.0;
913  while ( hull.geometry()->nextVertex( vertexId, pt2 ) )
914  {
915  double currentAngle = QgsGeometryUtils::lineAngle( pt1.x(), pt1.y(), pt2.x(), pt2.y() );
916  double rotateAngle = 180.0 / M_PI * ( currentAngle - prevAngle );
917  prevAngle = currentAngle;
918 
919  QTransform t = QTransform::fromTranslate( pt0.x(), pt0.y() );
920  t.rotate( rotateAngle );
921  t.translate( -pt0.x(), -pt0.y() );
922 
923  hull.geometry()->transform( t );
924 
925  QgsRectangle bounds = hull.geometry()->boundingBox();
926  double currentArea = bounds.width() * bounds.height();
927  if ( currentArea < area )
928  {
929  minRect = bounds;
930  area = currentArea;
931  angle = 180.0 / M_PI * currentAngle;
932  width = bounds.width();
933  height = bounds.height();
934  }
935 
936  pt2 = pt1;
937  }
938 
939  QgsGeometry minBounds = QgsGeometry::fromRect( minRect );
940  minBounds.rotate( angle, QgsPoint( pt0.x(), pt0.y() ) );
941 
942  // constrain angle to 0 - 180
943  if ( angle > 180.0 )
944  angle = fmod( angle, 180.0 );
945 
946  return minBounds;
947 }
948 
949 QgsGeometry QgsGeometry::orthogonalize( double tolerance, int maxIterations, double angleThreshold ) const
950 {
951  QgsInternalGeometryEngine engine( *this );
952 
953  return engine.orthogonalize( tolerance, maxIterations, angleThreshold );
954 }
955 
956 bool QgsGeometry::intersects( const QgsRectangle &r ) const
957 {
958  QgsGeometry g = fromRect( r );
959  return intersects( g );
960 }
961 
963 {
964  if ( !d->geometry || geometry.isNull() )
965  {
966  return false;
967  }
968 
969  QgsGeos geos( d->geometry );
970  return geos.intersects( *geometry.d->geometry );
971 }
972 
973 bool QgsGeometry::contains( const QgsPoint *p ) const
974 {
975  if ( !d->geometry || !p )
976  {
977  return false;
978  }
979 
980  QgsPointV2 pt( p->x(), p->y() );
981  QgsGeos geos( d->geometry );
982  return geos.contains( pt );
983 }
984 
986 {
987  if ( !d->geometry || geometry.isNull() )
988  {
989  return false;
990  }
991 
992  QgsGeos geos( d->geometry );
993  return geos.contains( *( geometry.d->geometry ) );
994 }
995 
997 {
998  if ( !d->geometry || geometry.isNull() )
999  {
1000  return false;
1001  }
1002 
1003  QgsGeos geos( d->geometry );
1004  return geos.disjoint( *( geometry.d->geometry ) );
1005 }
1006 
1008 {
1009  if ( !d->geometry || geometry.isNull() )
1010  {
1011  return false;
1012  }
1013 
1014  QgsGeos geos( d->geometry );
1015  return geos.isEqual( *( geometry.d->geometry ) );
1016 }
1017 
1019 {
1020  if ( !d->geometry || geometry.isNull() )
1021  {
1022  return false;
1023  }
1024 
1025  QgsGeos geos( d->geometry );
1026  return geos.touches( *( geometry.d->geometry ) );
1027 }
1028 
1030 {
1031  if ( !d->geometry || geometry.isNull() )
1032  {
1033  return false;
1034  }
1035 
1036  QgsGeos geos( d->geometry );
1037  return geos.overlaps( *( geometry.d->geometry ) );
1038 }
1039 
1041 {
1042  if ( !d->geometry || geometry.isNull() )
1043  {
1044  return false;
1045  }
1046 
1047  QgsGeos geos( d->geometry );
1048  return geos.within( *( geometry.d->geometry ) );
1049 }
1050 
1052 {
1053  if ( !d->geometry || geometry.isNull() )
1054  {
1055  return false;
1056  }
1057 
1058  QgsGeos geos( d->geometry );
1059  return geos.crosses( *( geometry.d->geometry ) );
1060 }
1061 
1062 QString QgsGeometry::exportToWkt( int precision ) const
1063 {
1064  if ( !d->geometry )
1065  {
1066  return QString();
1067  }
1068  return d->geometry->asWkt( precision );
1069 }
1070 
1071 QString QgsGeometry::exportToGeoJSON( int precision ) const
1072 {
1073  if ( !d->geometry )
1074  {
1075  return QStringLiteral( "null" );
1076  }
1077  return d->geometry->asJSON( precision );
1078 }
1079 
1081 {
1082  switch ( destType )
1083  {
1085  return convertToPoint( destMultipart );
1086 
1088  return convertToLine( destMultipart );
1089 
1091  return convertToPolygon( destMultipart );
1092 
1093  default:
1094  return QgsGeometry();
1095  }
1096 }
1097 
1099 {
1100  if ( !d->geometry )
1101  {
1102  return false;
1103  }
1104 
1105  if ( isMultipart() ) //already multitype, no need to convert
1106  {
1107  return true;
1108  }
1109 
1110  QgsGeometryCollection *multiGeom = dynamic_cast<QgsGeometryCollection *>
1112  if ( !multiGeom )
1113  {
1114  return false;
1115  }
1116 
1117  detach( true );
1118  multiGeom->addGeometry( d->geometry );
1119  d->geometry = multiGeom;
1120  return true;
1121 }
1122 
1124 {
1125  if ( !d->geometry )
1126  {
1127  return false;
1128  }
1129 
1130  if ( !isMultipart() ) //already single part, no need to convert
1131  {
1132  return true;
1133  }
1134 
1135  QgsGeometryCollection *multiGeom = dynamic_cast<QgsGeometryCollection *>( d->geometry );
1136  if ( !multiGeom || multiGeom->partCount() < 1 )
1137  return false;
1138 
1139  QgsAbstractGeometry *firstPart = multiGeom->geometryN( 0 )->clone();
1140  detach( false );
1141 
1142  d->geometry = firstPart;
1143  return true;
1144 }
1145 
1147 {
1149  {
1150  return QgsPoint();
1151  }
1152  QgsPointV2 *pt = dynamic_cast<QgsPointV2 *>( d->geometry );
1153  if ( !pt )
1154  {
1155  return QgsPoint();
1156  }
1157 
1158  return QgsPoint( pt->x(), pt->y() );
1159 }
1160 
1162 {
1163  QgsPolyline polyLine;
1164  if ( !d->geometry )
1165  {
1166  return polyLine;
1167  }
1168 
1169  bool doSegmentation = ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::CompoundCurve
1171  QgsLineString *line = nullptr;
1172  if ( doSegmentation )
1173  {
1174  QgsCurve *curve = dynamic_cast<QgsCurve *>( d->geometry );
1175  if ( !curve )
1176  {
1177  return polyLine;
1178  }
1179  line = curve->curveToLine();
1180  }
1181  else
1182  {
1183  line = dynamic_cast<QgsLineString *>( d->geometry );
1184  if ( !line )
1185  {
1186  return polyLine;
1187  }
1188  }
1189 
1190  int nVertices = line->numPoints();
1191  polyLine.resize( nVertices );
1192  for ( int i = 0; i < nVertices; ++i )
1193  {
1194  polyLine[i].setX( line->xAt( i ) );
1195  polyLine[i].setY( line->yAt( i ) );
1196  }
1197 
1198  if ( doSegmentation )
1199  {
1200  delete line;
1201  }
1202 
1203  return polyLine;
1204 }
1205 
1207 {
1208  if ( !d->geometry )
1209  return QgsPolygon();
1210 
1211  bool doSegmentation = ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::CurvePolygon );
1212 
1213  QgsPolygonV2 *p = nullptr;
1214  if ( doSegmentation )
1215  {
1216  QgsCurvePolygon *curvePoly = dynamic_cast<QgsCurvePolygon *>( d->geometry );
1217  if ( !curvePoly )
1218  {
1219  return QgsPolygon();
1220  }
1221  p = curvePoly->toPolygon();
1222  }
1223  else
1224  {
1225  p = dynamic_cast<QgsPolygonV2 *>( d->geometry );
1226  }
1227 
1228  if ( !p )
1229  {
1230  return QgsPolygon();
1231  }
1232 
1233  QgsPolygon polygon;
1234  convertPolygon( *p, polygon );
1235 
1236  if ( doSegmentation )
1237  {
1238  delete p;
1239  }
1240  return polygon;
1241 }
1242 
1244 {
1246  {
1247  return QgsMultiPoint();
1248  }
1249 
1250  const QgsMultiPointV2 *mp = dynamic_cast<QgsMultiPointV2 *>( d->geometry );
1251  if ( !mp )
1252  {
1253  return QgsMultiPoint();
1254  }
1255 
1256  int nPoints = mp->numGeometries();
1257  QgsMultiPoint multiPoint( nPoints );
1258  for ( int i = 0; i < nPoints; ++i )
1259  {
1260  const QgsPointV2 *pt = static_cast<const QgsPointV2 *>( mp->geometryN( i ) );
1261  multiPoint[i].setX( pt->x() );
1262  multiPoint[i].setY( pt->y() );
1263  }
1264  return multiPoint;
1265 }
1266 
1268 {
1269  if ( !d->geometry )
1270  {
1271  return QgsMultiPolyline();
1272  }
1273 
1274  QgsGeometryCollection *geomCollection = dynamic_cast<QgsGeometryCollection *>( d->geometry );
1275  if ( !geomCollection )
1276  {
1277  return QgsMultiPolyline();
1278  }
1279 
1280  int nLines = geomCollection->numGeometries();
1281  if ( nLines < 1 )
1282  {
1283  return QgsMultiPolyline();
1284  }
1285 
1286  QgsMultiPolyline mpl;
1287  for ( int i = 0; i < nLines; ++i )
1288  {
1289  bool deleteLine = false;
1290  const QgsLineString *line = dynamic_cast<const QgsLineString *>( geomCollection->geometryN( i ) );
1291  if ( !line )
1292  {
1293  const QgsCurve *curve = dynamic_cast<const QgsCurve *>( geomCollection->geometryN( i ) );
1294  if ( !curve )
1295  {
1296  continue;
1297  }
1298  deleteLine = true;
1299  line = curve->curveToLine();
1300  }
1301 
1302  QgsPointSequence lineCoords;
1303  line->points( lineCoords );
1304  QgsPolyline polyLine;
1305  convertToPolyline( lineCoords, polyLine );
1306  mpl.append( polyLine );
1307 
1308  if ( deleteLine )
1309  {
1310  delete line;
1311  }
1312  }
1313  return mpl;
1314 }
1315 
1317 {
1318  if ( !d->geometry )
1319  {
1320  return QgsMultiPolygon();
1321  }
1322 
1323  QgsGeometryCollection *geomCollection = dynamic_cast<QgsGeometryCollection *>( d->geometry );
1324  if ( !geomCollection )
1325  {
1326  return QgsMultiPolygon();
1327  }
1328 
1329  int nPolygons = geomCollection->numGeometries();
1330  if ( nPolygons < 1 )
1331  {
1332  return QgsMultiPolygon();
1333  }
1334 
1335  QgsMultiPolygon mp;
1336  for ( int i = 0; i < nPolygons; ++i )
1337  {
1338  const QgsPolygonV2 *polygon = dynamic_cast<const QgsPolygonV2 *>( geomCollection->geometryN( i ) );
1339  if ( !polygon )
1340  {
1341  const QgsCurvePolygon *cPolygon = dynamic_cast<const QgsCurvePolygon *>( geomCollection->geometryN( i ) );
1342  if ( cPolygon )
1343  {
1344  polygon = cPolygon->toPolygon();
1345  }
1346  else
1347  {
1348  continue;
1349  }
1350  }
1351 
1352  QgsPolygon poly;
1353  convertPolygon( *polygon, poly );
1354  mp.append( poly );
1355  }
1356  return mp;
1357 }
1358 
1359 double QgsGeometry::area() const
1360 {
1361  if ( !d->geometry )
1362  {
1363  return -1.0;
1364  }
1365  QgsGeos g( d->geometry );
1366 
1367 #if 0
1368  //debug: compare geos area with calculation in QGIS
1369  double geosArea = g.area();
1370  double qgisArea = 0;
1371  QgsSurface *surface = dynamic_cast<QgsSurface *>( d->geometry );
1372  if ( surface )
1373  {
1374  qgisArea = surface->area();
1375  }
1376 #endif
1377 
1378  return g.area();
1379 }
1380 
1381 double QgsGeometry::length() const
1382 {
1383  if ( !d->geometry )
1384  {
1385  return -1.0;
1386  }
1387  QgsGeos g( d->geometry );
1388  return g.length();
1389 }
1390 
1391 double QgsGeometry::distance( const QgsGeometry &geom ) const
1392 {
1393  if ( !d->geometry || !geom.d->geometry )
1394  {
1395  return -1.0;
1396  }
1397 
1398  QgsGeos g( d->geometry );
1399  return g.distance( *( geom.d->geometry ) );
1400 }
1401 
1402 QgsGeometry QgsGeometry::buffer( double distance, int segments ) const
1403 {
1404  if ( !d->geometry )
1405  {
1406  return QgsGeometry();
1407  }
1408 
1409  QgsGeos g( d->geometry );
1410  QgsAbstractGeometry *geom = g.buffer( distance, segments );
1411  if ( !geom )
1412  {
1413  return QgsGeometry();
1414  }
1415  return QgsGeometry( geom );
1416 }
1417 
1418 QgsGeometry QgsGeometry::buffer( double distance, int segments, EndCapStyle endCapStyle, JoinStyle joinStyle, double mitreLimit ) const
1419 {
1420  if ( !d->geometry )
1421  {
1422  return QgsGeometry();
1423  }
1424 
1425  QgsGeos g( d->geometry );
1426  QgsAbstractGeometry *geom = g.buffer( distance, segments, endCapStyle, joinStyle, mitreLimit );
1427  if ( !geom )
1428  {
1429  return QgsGeometry();
1430  }
1431  return QgsGeometry( geom );
1432 }
1433 
1434 QgsGeometry QgsGeometry::offsetCurve( double distance, int segments, JoinStyle joinStyle, double mitreLimit ) const
1435 {
1436  if ( !d->geometry || type() != QgsWkbTypes::LineGeometry )
1437  {
1438  return QgsGeometry();
1439  }
1440 
1441  if ( QgsWkbTypes::isMultiType( d->geometry->wkbType() ) )
1442  {
1443  QList<QgsGeometry> parts = asGeometryCollection();
1444  QList<QgsGeometry> results;
1445  Q_FOREACH ( const QgsGeometry &part, parts )
1446  {
1447  QgsGeometry result = part.offsetCurve( distance, segments, joinStyle, mitreLimit );
1448  if ( result )
1449  results << result;
1450  }
1451  if ( results.isEmpty() )
1452  return QgsGeometry();
1453 
1454  QgsGeometry first = results.takeAt( 0 );
1455  Q_FOREACH ( const QgsGeometry &result, results )
1456  {
1457  first.addPart( result );
1458  }
1459  return first;
1460  }
1461  else
1462  {
1463  QgsGeos geos( d->geometry );
1464  QgsAbstractGeometry *offsetGeom = geos.offsetCurve( distance, segments, joinStyle, mitreLimit );
1465  if ( !offsetGeom )
1466  {
1467  return QgsGeometry();
1468  }
1469  return QgsGeometry( offsetGeom );
1470  }
1471 }
1472 
1473 QgsGeometry QgsGeometry::singleSidedBuffer( double distance, int segments, BufferSide side, JoinStyle joinStyle, double mitreLimit ) const
1474 {
1475  if ( !d->geometry || type() != QgsWkbTypes::LineGeometry )
1476  {
1477  return QgsGeometry();
1478  }
1479 
1480  if ( QgsWkbTypes::isMultiType( d->geometry->wkbType() ) )
1481  {
1482  QList<QgsGeometry> parts = asGeometryCollection();
1483  QList<QgsGeometry> results;
1484  Q_FOREACH ( const QgsGeometry &part, parts )
1485  {
1486  QgsGeometry result = part.singleSidedBuffer( distance, segments, side, joinStyle, mitreLimit );
1487  if ( result )
1488  results << result;
1489  }
1490  if ( results.isEmpty() )
1491  return QgsGeometry();
1492 
1493  QgsGeometry first = results.takeAt( 0 );
1494  Q_FOREACH ( const QgsGeometry &result, results )
1495  {
1496  first.addPart( result );
1497  }
1498  return first;
1499  }
1500  else
1501  {
1502  QgsGeos geos( d->geometry );
1503  QgsAbstractGeometry *bufferGeom = geos.singleSidedBuffer( distance, segments, side,
1504  joinStyle, mitreLimit );
1505  if ( !bufferGeom )
1506  {
1507  return QgsGeometry();
1508  }
1509  return QgsGeometry( bufferGeom );
1510  }
1511 }
1512 
1513 QgsGeometry QgsGeometry::extendLine( double startDistance, double endDistance ) const
1514 {
1515  if ( !d->geometry || type() != QgsWkbTypes::LineGeometry )
1516  {
1517  return QgsGeometry();
1518  }
1519 
1520  if ( QgsWkbTypes::isMultiType( d->geometry->wkbType() ) )
1521  {
1522  QList<QgsGeometry> parts = asGeometryCollection();
1523  QList<QgsGeometry> results;
1524  Q_FOREACH ( const QgsGeometry &part, parts )
1525  {
1526  QgsGeometry result = part.extendLine( startDistance, endDistance );
1527  if ( result )
1528  results << result;
1529  }
1530  if ( results.isEmpty() )
1531  return QgsGeometry();
1532 
1533  QgsGeometry first = results.takeAt( 0 );
1534  Q_FOREACH ( const QgsGeometry &result, results )
1535  {
1536  first.addPart( result );
1537  }
1538  return first;
1539  }
1540  else
1541  {
1542  QgsLineString *line = dynamic_cast< QgsLineString * >( d->geometry );
1543  if ( !line )
1544  return QgsGeometry();
1545 
1546  QgsLineString *newLine = line->clone();
1547  newLine->extend( startDistance, endDistance );
1548  return QgsGeometry( newLine );
1549  }
1550 }
1551 
1552 QgsGeometry QgsGeometry::simplify( double tolerance ) const
1553 {
1554  if ( !d->geometry )
1555  {
1556  return QgsGeometry();
1557  }
1558 
1559  QgsGeos geos( d->geometry );
1560  QgsAbstractGeometry *simplifiedGeom = geos.simplify( tolerance );
1561  if ( !simplifiedGeom )
1562  {
1563  return QgsGeometry();
1564  }
1565  return QgsGeometry( simplifiedGeom );
1566 }
1567 
1568 QgsGeometry QgsGeometry::densifyByCount( int extraNodesPerSegment ) const
1569 {
1570  QgsInternalGeometryEngine engine( *this );
1571 
1572  return engine.densifyByCount( extraNodesPerSegment );
1573 }
1574 
1576 {
1577  QgsInternalGeometryEngine engine( *this );
1578 
1579  return engine.densifyByDistance( distance );
1580 }
1581 
1583 {
1584  if ( !d->geometry )
1585  {
1586  return QgsGeometry();
1587  }
1588 
1589  QgsGeos geos( d->geometry );
1591  bool ok = geos.centroid( centroid );
1592  if ( !ok )
1593  {
1594  return QgsGeometry();
1595  }
1596  return QgsGeometry( centroid.clone() );
1597 }
1598 
1600 {
1601  if ( !d->geometry )
1602  {
1603  return QgsGeometry();
1604  }
1605 
1606  QgsGeos geos( d->geometry );
1607  QgsPointV2 pt;
1608  bool ok = geos.pointOnSurface( pt );
1609  if ( !ok )
1610  {
1611  return QgsGeometry();
1612  }
1613  return QgsGeometry( pt.clone() );
1614 }
1615 
1616 QgsGeometry QgsGeometry::poleOfInaccessibility( double precision, double *distanceToBoundary ) const
1617 {
1618  QgsInternalGeometryEngine engine( *this );
1619 
1620  return engine.poleOfInaccessibility( precision, distanceToBoundary );
1621 }
1622 
1624 {
1625  if ( !d->geometry )
1626  {
1627  return QgsGeometry();
1628  }
1629  QgsGeos geos( d->geometry );
1630  QgsAbstractGeometry *cHull = geos.convexHull();
1631  if ( !cHull )
1632  {
1633  return QgsGeometry();
1634  }
1635  return QgsGeometry( cHull );
1636 }
1637 
1638 QgsGeometry QgsGeometry::voronoiDiagram( const QgsGeometry &extent, double tolerance, bool edgesOnly ) const
1639 {
1640  if ( !d->geometry )
1641  {
1642  return QgsGeometry();
1643  }
1644 
1645  QgsGeos geos( d->geometry );
1646  return geos.voronoiDiagram( extent.geometry(), tolerance, edgesOnly );
1647 }
1648 
1649 QgsGeometry QgsGeometry::delaunayTriangulation( double tolerance, bool edgesOnly ) const
1650 {
1651  if ( !d->geometry )
1652  {
1653  return QgsGeometry();
1654  }
1655 
1656  QgsGeos geos( d->geometry );
1657  return geos.delaunayTriangulation( tolerance, edgesOnly );
1658 }
1659 
1661 {
1662  if ( !d->geometry )
1663  {
1664  return QgsGeometry();
1665  }
1666 
1667  QgsGeometry line = *this;
1669  line = QgsGeometry( d->geometry->boundary() );
1670 
1671  QgsGeos geos( line.geometry() );
1672  QgsAbstractGeometry *result = geos.interpolate( distance );
1673  if ( !result )
1674  {
1675  return QgsGeometry();
1676  }
1677  return QgsGeometry( result );
1678 }
1679 
1680 double QgsGeometry::lineLocatePoint( const QgsGeometry &point ) const
1681 {
1682  if ( type() != QgsWkbTypes::LineGeometry )
1683  return -1;
1684 
1685  if ( QgsWkbTypes::flatType( point.wkbType() ) != QgsWkbTypes::Point )
1686  return -1;
1687 
1688  QgsGeometry segmentized = *this;
1690  {
1691  segmentized = QgsGeometry( static_cast< QgsCurve * >( d->geometry )->segmentize() );
1692  }
1693 
1694  QgsGeos geos( d->geometry );
1695  return geos.lineLocatePoint( *( static_cast< QgsPointV2 * >( point.d->geometry ) ) );
1696 }
1697 
1699 {
1700  if ( !d->geometry )
1701  return 0.0;
1702 
1703  // always operate on segmentized geometries
1704  QgsGeometry segmentized = *this;
1706  {
1707  segmentized = QgsGeometry( static_cast< QgsCurve * >( d->geometry )->segmentize() );
1708  }
1709 
1710  QgsVertexId previous;
1711  QgsVertexId next;
1712  if ( !QgsGeometryUtils::verticesAtDistance( *segmentized.geometry(), distance, previous, next ) )
1713  return 0.0;
1714 
1715  if ( previous == next )
1716  {
1717  // distance coincided exactly with a vertex
1718  QgsVertexId v2 = previous;
1719  QgsVertexId v1;
1720  QgsVertexId v3;
1721  QgsGeometryUtils::adjacentVertices( *segmentized.geometry(), v2, v1, v3 );
1722  if ( v1.isValid() && v3.isValid() )
1723  {
1724  QgsPointV2 p1 = segmentized.geometry()->vertexAt( v1 );
1725  QgsPointV2 p2 = segmentized.geometry()->vertexAt( v2 );
1726  QgsPointV2 p3 = segmentized.geometry()->vertexAt( v3 );
1727  double angle1 = QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1728  double angle2 = QgsGeometryUtils::lineAngle( p2.x(), p2.y(), p3.x(), p3.y() );
1729  return QgsGeometryUtils::averageAngle( angle1, angle2 );
1730  }
1731  else if ( v3.isValid() )
1732  {
1733  QgsPointV2 p1 = segmentized.geometry()->vertexAt( v2 );
1734  QgsPointV2 p2 = segmentized.geometry()->vertexAt( v3 );
1735  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1736  }
1737  else
1738  {
1739  QgsPointV2 p1 = segmentized.geometry()->vertexAt( v1 );
1740  QgsPointV2 p2 = segmentized.geometry()->vertexAt( v2 );
1741  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1742  }
1743  }
1744  else
1745  {
1746  QgsPointV2 p1 = segmentized.geometry()->vertexAt( previous );
1747  QgsPointV2 p2 = segmentized.geometry()->vertexAt( next );
1748  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1749  }
1750 }
1751 
1753 {
1754  if ( !d->geometry || geometry.isNull() )
1755  {
1756  return QgsGeometry();
1757  }
1758 
1759  QgsGeos geos( d->geometry );
1760 
1761  QgsAbstractGeometry *resultGeom = geos.intersection( *( geometry.d->geometry ) );
1762  return QgsGeometry( resultGeom );
1763 }
1764 
1766 {
1767  if ( !d->geometry || geometry.isNull() )
1768  {
1769  return QgsGeometry();
1770  }
1771 
1772  QgsGeos geos( d->geometry );
1773 
1774  QgsAbstractGeometry *resultGeom = geos.combine( *( geometry.d->geometry ) );
1775  if ( !resultGeom )
1776  {
1777  return QgsGeometry();
1778  }
1779  return QgsGeometry( resultGeom );
1780 }
1781 
1783 {
1784  if ( !d->geometry )
1785  {
1786  return QgsGeometry();
1787  }
1788 
1790  {
1791  // special case - a single linestring was passed
1792  return QgsGeometry( *this );
1793  }
1794 
1795  QgsGeos geos( d->geometry );
1796  return geos.mergeLines();
1797 }
1798 
1800 {
1801  if ( !d->geometry || geometry.isNull() )
1802  {
1803  return QgsGeometry();
1804  }
1805 
1806  QgsGeos geos( d->geometry );
1807 
1808  QgsAbstractGeometry *resultGeom = geos.difference( *( geometry.d->geometry ) );
1809  if ( !resultGeom )
1810  {
1811  return QgsGeometry();
1812  }
1813  return QgsGeometry( resultGeom );
1814 }
1815 
1817 {
1818  if ( !d->geometry || geometry.isNull() )
1819  {
1820  return QgsGeometry();
1821  }
1822 
1823  QgsGeos geos( d->geometry );
1824 
1825  QgsAbstractGeometry *resultGeom = geos.symDifference( *( geometry.d->geometry ) );
1826  if ( !resultGeom )
1827  {
1828  return QgsGeometry();
1829  }
1830  return QgsGeometry( resultGeom );
1831 }
1832 
1833 QgsGeometry QgsGeometry::extrude( double x, double y )
1834 {
1835  QgsInternalGeometryEngine engine( *this );
1836 
1837  return engine.extrude( x, y );
1838 }
1839 
1840 QByteArray QgsGeometry::exportToWkb() const
1841 {
1842  return d->geometry ? d->geometry->asWkb() : QByteArray();
1843 }
1844 
1845 QList<QgsGeometry> QgsGeometry::asGeometryCollection() const
1846 {
1847  QList<QgsGeometry> geometryList;
1848  if ( !d->geometry )
1849  {
1850  return geometryList;
1851  }
1852 
1853  QgsGeometryCollection *gc = dynamic_cast<QgsGeometryCollection *>( d->geometry );
1854  if ( gc )
1855  {
1856  int numGeom = gc->numGeometries();
1857  geometryList.reserve( numGeom );
1858  for ( int i = 0; i < numGeom; ++i )
1859  {
1860  geometryList.append( QgsGeometry( gc->geometryN( i )->clone() ) );
1861  }
1862  }
1863  else //a singlepart geometry
1864  {
1865  geometryList.append( QgsGeometry( d->geometry->clone() ) );
1866  }
1867 
1868  return geometryList;
1869 }
1870 
1871 QPointF QgsGeometry::asQPointF() const
1872 {
1873  QgsPoint point = asPoint();
1874  return point.toQPointF();
1875 }
1876 
1877 QPolygonF QgsGeometry::asQPolygonF() const
1878 {
1879  QPolygonF result;
1880  QgsPolyline polyline;
1882  if ( type == QgsWkbTypes::LineString || type == QgsWkbTypes::LineString25D )
1883  {
1884  polyline = asPolyline();
1885  }
1886  else if ( type == QgsWkbTypes::Polygon || type == QgsWkbTypes::Polygon25D )
1887  {
1888  QgsPolygon polygon = asPolygon();
1889  if ( polygon.size() < 1 )
1890  return result;
1891  polyline = polygon.at( 0 );
1892  }
1893  else
1894  {
1895  return result;
1896  }
1897 
1898  QgsPolyline::const_iterator lineIt = polyline.constBegin();
1899  for ( ; lineIt != polyline.constEnd(); ++lineIt )
1900  {
1901  result << lineIt->toQPointF();
1902  }
1903  return result;
1904 }
1905 
1906 bool QgsGeometry::deleteRing( int ringNum, int partNum )
1907 {
1908  if ( !d->geometry )
1909  {
1910  return false;
1911  }
1912 
1913  detach( true );
1914  bool ok = QgsGeometryEditUtils::deleteRing( d->geometry, ringNum, partNum );
1915  return ok;
1916 }
1917 
1918 bool QgsGeometry::deletePart( int partNum )
1919 {
1920  if ( !d->geometry )
1921  {
1922  return false;
1923  }
1924 
1925  if ( !isMultipart() && partNum < 1 )
1926  {
1927  setGeometry( nullptr );
1928  return true;
1929  }
1930 
1931  detach( true );
1932  bool ok = QgsGeometryEditUtils::deletePart( d->geometry, partNum );
1933  return ok;
1934 }
1935 
1936 int QgsGeometry::avoidIntersections( const QList<QgsVectorLayer *> &avoidIntersectionsLayers, const QHash<QgsVectorLayer *, QSet<QgsFeatureId> > &ignoreFeatures )
1937 {
1938  if ( !d->geometry )
1939  {
1940  return 1;
1941  }
1942 
1943  QgsAbstractGeometry *diffGeom = QgsGeometryEditUtils::avoidIntersections( *( d->geometry ), avoidIntersectionsLayers, ignoreFeatures );
1944  if ( diffGeom )
1945  {
1946  detach( false );
1947  d->geometry = diffGeom;
1948  }
1949  return 0;
1950 }
1951 
1952 
1954 {
1955  if ( !d->geometry )
1956  return QgsGeometry();
1957 
1958  QString errorMsg;
1960  if ( !g )
1961  return QgsGeometry();
1962 
1963  return QgsGeometry( g );
1964 }
1965 
1966 
1967 void QgsGeometry::validateGeometry( QList<QgsGeometry::Error> &errors )
1968 {
1970 }
1971 
1973 {
1974  if ( !d->geometry )
1975  {
1976  return false;
1977  }
1978 
1979  QgsGeos geos( d->geometry );
1980  return geos.isValid();
1981 }
1982 
1984 {
1985  if ( !d->geometry )
1986  return false;
1987 
1988  QgsGeos geos( d->geometry );
1989  return geos.isSimple();
1990 }
1991 
1993 {
1994  if ( !d->geometry || !g.d->geometry )
1995  {
1996  return false;
1997  }
1998 
1999  QgsGeos geos( d->geometry );
2000  return geos.isEqual( *( g.d->geometry ) );
2001 }
2002 
2003 QgsGeometry QgsGeometry::unaryUnion( const QList<QgsGeometry> &geometries )
2004 {
2005  QgsGeos geos( nullptr );
2006 
2007  QList<QgsAbstractGeometry *> geomV2List;
2008  QList<QgsGeometry>::const_iterator it = geometries.constBegin();
2009  for ( ; it != geometries.constEnd(); ++it )
2010  {
2011  if ( !( ( *it ).isNull() ) )
2012  {
2013  geomV2List.append( ( *it ).geometry() );
2014  }
2015  }
2016 
2017  QgsAbstractGeometry *geom = geos.combine( geomV2List );
2018  return QgsGeometry( geom );
2019 }
2020 
2021 QgsGeometry QgsGeometry::polygonize( const QList<QgsGeometry> &geometryList )
2022 {
2023  QgsGeos geos( nullptr );
2024 
2025  QList<QgsAbstractGeometry *> geomV2List;
2026  QList<QgsGeometry>::const_iterator it = geometryList.constBegin();
2027  for ( ; it != geometryList.constEnd(); ++it )
2028  {
2029  if ( !( ( *it ).isNull() ) )
2030  {
2031  geomV2List.append( ( *it ).geometry() );
2032  }
2033  }
2034 
2035  return geos.polygonize( geomV2List );
2036 }
2037 
2039 {
2041  {
2042  return;
2043  }
2044 
2045  QgsAbstractGeometry *straightGeom = d->geometry->segmentize();
2046  detach( false );
2047 
2048  d->geometry = straightGeom;
2049 }
2050 
2052 {
2053  if ( !d->geometry )
2054  {
2055  return false;
2056  }
2057 
2058  return d->geometry->hasCurvedSegments();
2059 }
2060 
2062 {
2063  if ( !d->geometry )
2064  {
2065  return 1;
2066  }
2067 
2068  detach();
2069  d->geometry->transform( ct );
2070  return 0;
2071 }
2072 
2073 int QgsGeometry::transform( const QTransform &ct )
2074 {
2075  if ( !d->geometry )
2076  {
2077  return 1;
2078  }
2079 
2080  detach();
2081  d->geometry->transform( ct );
2082  return 0;
2083 }
2084 
2086 {
2087  if ( d->geometry )
2088  {
2089  detach();
2090  d->geometry->transform( mtp.transform() );
2091  }
2092 }
2093 
2094 #if 0
2095 void QgsGeometry::clip( const QgsRectangle &rect )
2096 {
2097  if ( d->geometry )
2098  {
2099  detach();
2100  d->geometry->clip( rect );
2101  removeWkbGeos();
2102  }
2103 }
2104 #endif
2105 
2106 void QgsGeometry::draw( QPainter &p ) const
2107 {
2108  if ( d->geometry )
2109  {
2110  d->geometry->draw( p );
2111  }
2112 }
2113 
2114 static bool vertexIndexInfo( const QgsAbstractGeometry *g, int vertexIndex, int &partIndex, int &ringIndex, int &vertex )
2115 {
2116  if ( vertexIndex < 0 )
2117  return false; // clearly something wrong
2118 
2119  if ( const QgsGeometryCollection *geomCollection = dynamic_cast<const QgsGeometryCollection *>( g ) )
2120  {
2121  partIndex = 0;
2122  int offset = 0;
2123  for ( int i = 0; i < geomCollection->numGeometries(); ++i )
2124  {
2125  const QgsAbstractGeometry *part = geomCollection->geometryN( i );
2126 
2127  // count total number of vertices in the part
2128  int numPoints = 0;
2129  for ( int k = 0; k < part->ringCount(); ++k )
2130  numPoints += part->vertexCount( 0, k );
2131 
2132  if ( vertexIndex < numPoints )
2133  {
2134  int nothing;
2135  return vertexIndexInfo( part, vertexIndex, nothing, ringIndex, vertex ); // set ring_index + index
2136  }
2137  vertexIndex -= numPoints;
2138  offset += numPoints;
2139  partIndex++;
2140  }
2141  }
2142  else if ( const QgsCurvePolygon *curvePolygon = dynamic_cast<const QgsCurvePolygon *>( g ) )
2143  {
2144  const QgsCurve *ring = curvePolygon->exteriorRing();
2145  if ( vertexIndex < ring->numPoints() )
2146  {
2147  partIndex = 0;
2148  ringIndex = 0;
2149  vertex = vertexIndex;
2150  return true;
2151  }
2152  vertexIndex -= ring->numPoints();
2153  ringIndex = 1;
2154  for ( int i = 0; i < curvePolygon->numInteriorRings(); ++i )
2155  {
2156  const QgsCurve *ring = curvePolygon->interiorRing( i );
2157  if ( vertexIndex < ring->numPoints() )
2158  {
2159  partIndex = 0;
2160  vertex = vertexIndex;
2161  return true;
2162  }
2163  vertexIndex -= ring->numPoints();
2164  ringIndex += 1;
2165  }
2166  }
2167  else if ( const QgsCurve *curve = dynamic_cast<const QgsCurve *>( g ) )
2168  {
2169  if ( vertexIndex < curve->numPoints() )
2170  {
2171  partIndex = 0;
2172  ringIndex = 0;
2173  vertex = vertexIndex;
2174  return true;
2175  }
2176  }
2177  else if ( dynamic_cast<const QgsPointV2 *>( g ) )
2178  {
2179  if ( vertexIndex == 0 )
2180  {
2181  partIndex = 0;
2182  ringIndex = 0;
2183  vertex = 0;
2184  return true;
2185  }
2186  }
2187 
2188  return false;
2189 }
2190 
2192 {
2193  if ( !d->geometry )
2194  {
2195  return false;
2196  }
2197 
2198  id.type = QgsVertexId::SegmentVertex;
2199 
2200  bool res = vertexIndexInfo( d->geometry, nr, id.part, id.ring, id.vertex );
2201  if ( !res )
2202  return false;
2203 
2204  // now let's find out if it is a straight or circular segment
2205  const QgsAbstractGeometry *g = d->geometry;
2206  if ( const QgsGeometryCollection *geomCollection = dynamic_cast<const QgsGeometryCollection *>( g ) )
2207  {
2208  g = geomCollection->geometryN( id.part );
2209  }
2210 
2211  if ( const QgsCurvePolygon *curvePolygon = dynamic_cast<const QgsCurvePolygon *>( g ) )
2212  {
2213  g = id.ring == 0 ? curvePolygon->exteriorRing() : curvePolygon->interiorRing( id.ring - 1 );
2214  }
2215 
2216  if ( const QgsCurve *curve = dynamic_cast<const QgsCurve *>( g ) )
2217  {
2218  QgsPointV2 p;
2219  res = curve->pointAt( id.vertex, p, id.type );
2220  if ( !res )
2221  return false;
2222  }
2223 
2224  return true;
2225 }
2226 
2228 {
2229  if ( !d->geometry )
2230  {
2231  return -1;
2232  }
2233 
2235 
2236  int vertexCount = 0;
2237  for ( int part = 0; part < coords.size(); ++part )
2238  {
2239  const QgsRingSequence &featureCoords = coords.at( part );
2240  for ( int ring = 0; ring < featureCoords.size(); ++ring )
2241  {
2242  const QgsPointSequence &ringCoords = featureCoords.at( ring );
2243  for ( int vertex = 0; vertex < ringCoords.size(); ++vertex )
2244  {
2245  if ( vertex == id.vertex && ring == id.ring && part == id.part )
2246  {
2247  return vertexCount;
2248  }
2249  ++vertexCount;
2250  }
2251  }
2252  }
2253  return -1;
2254 }
2255 
2256 void QgsGeometry::convertPointList( const QList<QgsPoint> &input, QgsPointSequence &output )
2257 {
2258  output.clear();
2259  QList<QgsPoint>::const_iterator it = input.constBegin();
2260  for ( ; it != input.constEnd(); ++it )
2261  {
2262  output.append( QgsPointV2( it->x(), it->y() ) );
2263  }
2264 }
2265 
2266 void QgsGeometry::convertPointList( const QgsPointSequence &input, QList<QgsPoint> &output )
2267 {
2268  output.clear();
2269  QgsPointSequence::const_iterator it = input.constBegin();
2270  for ( ; it != input.constEnd(); ++it )
2271  {
2272  output.append( QgsPoint( it->x(), it->y() ) );
2273  }
2274 }
2275 
2276 QgsGeometry::operator bool() const
2277 {
2278  return d->geometry;
2279 }
2280 
2281 void QgsGeometry::convertToPolyline( const QgsPointSequence &input, QgsPolyline &output )
2282 {
2283  output.clear();
2284  output.resize( input.size() );
2285 
2286  for ( int i = 0; i < input.size(); ++i )
2287  {
2288  const QgsPointV2 &pt = input.at( i );
2289  output[i].setX( pt.x() );
2290  output[i].setY( pt.y() );
2291  }
2292 }
2293 
2294 void QgsGeometry::convertPolygon( const QgsPolygonV2 &input, QgsPolygon &output )
2295 {
2296  output.clear();
2297  QgsCoordinateSequence coords = input.coordinateSequence();
2298  if ( coords.size() < 1 )
2299  {
2300  return;
2301  }
2302  const QgsRingSequence &rings = coords[0];
2303  output.resize( rings.size() );
2304  for ( int i = 0; i < rings.size(); ++i )
2305  {
2306  convertToPolyline( rings[i], output[i] );
2307  }
2308 }
2309 
2310 GEOSContextHandle_t QgsGeometry::getGEOSHandler()
2311 {
2312  return QgsGeos::getGEOSHandler();
2313 }
2314 
2316 {
2317  return QgsGeometry( new QgsPointV2( point.x(), point.y() ) );
2318 }
2319 
2320 QgsGeometry QgsGeometry::fromQPolygonF( const QPolygonF &polygon )
2321 {
2322  if ( polygon.isClosed() )
2323  {
2325  }
2326  else
2327  {
2329  }
2330 }
2331 
2333 {
2334  QgsPolygon result;
2335  result << createPolylineFromQPolygonF( polygon );
2336  return result;
2337 }
2338 
2340 {
2341  QgsPolyline result;
2342  QPolygonF::const_iterator it = polygon.constBegin();
2343  for ( ; it != polygon.constEnd(); ++it )
2344  {
2345  result.append( QgsPoint( *it ) );
2346  }
2347  return result;
2348 }
2349 
2350 bool QgsGeometry::compare( const QgsPolyline &p1, const QgsPolyline &p2, double epsilon )
2351 {
2352  if ( p1.count() != p2.count() )
2353  return false;
2354 
2355  for ( int i = 0; i < p1.count(); ++i )
2356  {
2357  if ( !p1.at( i ).compare( p2.at( i ), epsilon ) )
2358  return false;
2359  }
2360  return true;
2361 }
2362 
2363 bool QgsGeometry::compare( const QgsPolygon &p1, const QgsPolygon &p2, double epsilon )
2364 {
2365  if ( p1.count() != p2.count() )
2366  return false;
2367 
2368  for ( int i = 0; i < p1.count(); ++i )
2369  {
2370  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
2371  return false;
2372  }
2373  return true;
2374 }
2375 
2376 
2377 bool QgsGeometry::compare( const QgsMultiPolygon &p1, const QgsMultiPolygon &p2, double epsilon )
2378 {
2379  if ( p1.count() != p2.count() )
2380  return false;
2381 
2382  for ( int i = 0; i < p1.count(); ++i )
2383  {
2384  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
2385  return false;
2386  }
2387  return true;
2388 }
2389 
2390 QgsGeometry QgsGeometry::smooth( const unsigned int iterations, const double offset, double minimumDistance, double maxAngle ) const
2391 {
2392  if ( d->geometry->isEmpty() )
2393  return QgsGeometry();
2394 
2395  QgsGeometry geom = *this;
2397  geom = QgsGeometry( d->geometry->segmentize() );
2398 
2399  switch ( QgsWkbTypes::flatType( geom.wkbType() ) )
2400  {
2401  case QgsWkbTypes::Point:
2403  //can't smooth a point based geometry
2404  return geom;
2405 
2407  {
2408  QgsLineString *lineString = static_cast< QgsLineString * >( d->geometry );
2409  return QgsGeometry( smoothLine( *lineString, iterations, offset, minimumDistance, maxAngle ) );
2410  }
2411 
2413  {
2414  QgsMultiLineString *multiLine = static_cast< QgsMultiLineString * >( d->geometry );
2415 
2416  QgsMultiLineString *resultMultiline = new QgsMultiLineString();
2417  for ( int i = 0; i < multiLine->numGeometries(); ++i )
2418  {
2419  resultMultiline->addGeometry( smoothLine( *( static_cast< QgsLineString * >( multiLine->geometryN( i ) ) ), iterations, offset, minimumDistance, maxAngle ) );
2420  }
2421  return QgsGeometry( resultMultiline );
2422  }
2423 
2424  case QgsWkbTypes::Polygon:
2425  {
2426  QgsPolygonV2 *poly = static_cast< QgsPolygonV2 * >( d->geometry );
2427  return QgsGeometry( smoothPolygon( *poly, iterations, offset, minimumDistance, maxAngle ) );
2428  }
2429 
2431  {
2432  QgsMultiPolygonV2 *multiPoly = static_cast< QgsMultiPolygonV2 * >( d->geometry );
2433 
2434  QgsMultiPolygonV2 *resultMultiPoly = new QgsMultiPolygonV2();
2435  for ( int i = 0; i < multiPoly->numGeometries(); ++i )
2436  {
2437  resultMultiPoly->addGeometry( smoothPolygon( *( static_cast< QgsPolygonV2 * >( multiPoly->geometryN( i ) ) ), iterations, offset, minimumDistance, maxAngle ) );
2438  }
2439  return QgsGeometry( resultMultiPoly );
2440  }
2441 
2442  case QgsWkbTypes::Unknown:
2443  default:
2444  return QgsGeometry( *this );
2445  }
2446 }
2447 
2448 inline QgsPointV2 interpolatePointOnLine( const QgsPointV2 &p1, const QgsPointV2 &p2, const double offset )
2449 {
2450  double deltaX = p2.x() - p1.x();
2451  double deltaY = p2.y() - p1.y();
2452  return QgsPointV2( p1.x() + deltaX * offset, p1.y() + deltaY * offset );
2453 }
2454 
2455 QgsLineString *smoothCurve( const QgsLineString &line, const unsigned int iterations,
2456  const double offset, double squareDistThreshold, double maxAngleRads,
2457  bool isRing )
2458 {
2459  std::unique_ptr< QgsLineString > result( new QgsLineString( line ) );
2460  for ( unsigned int iteration = 0; iteration < iterations; ++iteration )
2461  {
2462  QgsPointSequence outputLine;
2463  outputLine.reserve( 2 * ( result->numPoints() - 1 ) );
2464  bool skipFirst = false;
2465  bool skipLast = false;
2466  if ( isRing )
2467  {
2468  QgsPointV2 p1 = result->pointN( result->numPoints() - 2 );
2469  QgsPointV2 p2 = result->pointN( 0 );
2470  QgsPointV2 p3 = result->pointN( 1 );
2471  double angle = QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(),
2472  p3.x(), p3.y() );
2473  angle = qAbs( M_PI - angle );
2474  skipFirst = angle > maxAngleRads;
2475  }
2476  for ( int i = 0; i < result->numPoints() - 1; i++ )
2477  {
2478  QgsPointV2 p1 = result->pointN( i );
2479  QgsPointV2 p2 = result->pointN( i + 1 );
2480 
2481  double angle = M_PI;
2482  if ( i == 0 && isRing )
2483  {
2484  QgsPointV2 p3 = result->pointN( result->numPoints() - 2 );
2485  angle = QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(),
2486  p3.x(), p3.y() );
2487  }
2488  else if ( i < result->numPoints() - 2 )
2489  {
2490  QgsPointV2 p3 = result->pointN( i + 2 );
2491  angle = QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(),
2492  p3.x(), p3.y() );
2493  }
2494  else if ( i == result->numPoints() - 2 && isRing )
2495  {
2496  QgsPointV2 p3 = result->pointN( 1 );
2497  angle = QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(),
2498  p3.x(), p3.y() );
2499  }
2500 
2501  skipLast = angle < M_PI - maxAngleRads || angle > M_PI + maxAngleRads;
2502 
2503  // don't apply distance threshold to first or last segment
2504  if ( i == 0 || i >= result->numPoints() - 2
2505  || QgsGeometryUtils::sqrDistance2D( p1, p2 ) > squareDistThreshold )
2506  {
2507  if ( !isRing )
2508  {
2509  if ( !skipFirst )
2510  outputLine << ( i == 0 ? result->pointN( i ) : interpolatePointOnLine( p1, p2, offset ) );
2511  if ( !skipLast )
2512  outputLine << ( i == result->numPoints() - 2 ? result->pointN( i + 1 ) : interpolatePointOnLine( p1, p2, 1.0 - offset ) );
2513  else
2514  outputLine << p2;
2515  }
2516  else
2517  {
2518  // ring
2519  if ( !skipFirst )
2520  outputLine << interpolatePointOnLine( p1, p2, offset );
2521  else if ( i == 0 )
2522  outputLine << p1;
2523  if ( !skipLast )
2524  outputLine << interpolatePointOnLine( p1, p2, 1.0 - offset );
2525  else
2526  outputLine << p2;
2527  }
2528  }
2529  skipFirst = skipLast;
2530  }
2531 
2532  if ( isRing && outputLine.at( 0 ) != outputLine.at( outputLine.count() - 1 ) )
2533  outputLine << outputLine.at( 0 );
2534 
2535  result->setPoints( outputLine );
2536  }
2537  return result.release();
2538 }
2539 
2540 QgsLineString *QgsGeometry::smoothLine( const QgsLineString &line, const unsigned int iterations, const double offset, double minimumDistance, double maxAngle ) const
2541 {
2542  double maxAngleRads = maxAngle * M_PI / 180.0;
2543  double squareDistThreshold = minimumDistance > 0 ? minimumDistance * minimumDistance : -1;
2544  return smoothCurve( line, iterations, offset, squareDistThreshold, maxAngleRads, false );
2545 }
2546 
2547 QgsPolygonV2 *QgsGeometry::smoothPolygon( const QgsPolygonV2 &polygon, const unsigned int iterations, const double offset, double minimumDistance, double maxAngle ) const
2548 {
2549  double maxAngleRads = maxAngle * M_PI / 180.0;
2550  double squareDistThreshold = minimumDistance > 0 ? minimumDistance * minimumDistance : -1;
2551  std::unique_ptr< QgsPolygonV2 > resultPoly( new QgsPolygonV2 );
2552 
2553  resultPoly->setExteriorRing( smoothCurve( *( static_cast< const QgsLineString *>( polygon.exteriorRing() ) ), iterations, offset,
2554  squareDistThreshold, maxAngleRads, true ) );
2555 
2556  for ( int i = 0; i < polygon.numInteriorRings(); ++i )
2557  {
2558  resultPoly->addInteriorRing( smoothCurve( *( static_cast< const QgsLineString *>( polygon.interiorRing( i ) ) ), iterations, offset,
2559  squareDistThreshold, maxAngleRads, true ) );
2560  }
2561  return resultPoly.release();
2562 }
2563 
2564 QgsGeometry QgsGeometry::convertToPoint( bool destMultipart ) const
2565 {
2566  switch ( type() )
2567  {
2569  {
2570  bool srcIsMultipart = isMultipart();
2571 
2572  if ( ( destMultipart && srcIsMultipart ) ||
2573  ( !destMultipart && !srcIsMultipart ) )
2574  {
2575  // return a copy of the same geom
2576  return QgsGeometry( *this );
2577  }
2578  if ( destMultipart )
2579  {
2580  // layer is multipart => make a multipoint with a single point
2581  return fromMultiPoint( QgsMultiPoint() << asPoint() );
2582  }
2583  else
2584  {
2585  // destination is singlepart => make a single part if possible
2586  QgsMultiPoint multiPoint = asMultiPoint();
2587  if ( multiPoint.count() == 1 )
2588  {
2589  return fromPoint( multiPoint[0] );
2590  }
2591  }
2592  return QgsGeometry();
2593  }
2594 
2596  {
2597  // only possible if destination is multipart
2598  if ( !destMultipart )
2599  return QgsGeometry();
2600 
2601  // input geometry is multipart
2602  if ( isMultipart() )
2603  {
2604  QgsMultiPolyline multiLine = asMultiPolyline();
2605  QgsMultiPoint multiPoint;
2606  for ( QgsMultiPolyline::const_iterator multiLineIt = multiLine.constBegin(); multiLineIt != multiLine.constEnd(); ++multiLineIt )
2607  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2608  multiPoint << *lineIt;
2609  return fromMultiPoint( multiPoint );
2610  }
2611  // input geometry is not multipart: copy directly the line into a multipoint
2612  else
2613  {
2614  QgsPolyline line = asPolyline();
2615  if ( !line.isEmpty() )
2616  return fromMultiPoint( line );
2617  }
2618  return QgsGeometry();
2619  }
2620 
2622  {
2623  // can only transform if destination is multipoint
2624  if ( !destMultipart )
2625  return QgsGeometry();
2626 
2627  // input geometry is multipart: make a multipoint from multipolygon
2628  if ( isMultipart() )
2629  {
2630  QgsMultiPolygon multiPolygon = asMultiPolygon();
2631  QgsMultiPoint multiPoint;
2632  for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
2633  for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
2634  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2635  multiPoint << *lineIt;
2636  return fromMultiPoint( multiPoint );
2637  }
2638  // input geometry is not multipart: make a multipoint from polygon
2639  else
2640  {
2641  QgsPolygon polygon = asPolygon();
2642  QgsMultiPoint multiPoint;
2643  for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
2644  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2645  multiPoint << *lineIt;
2646  return fromMultiPoint( multiPoint );
2647  }
2648  }
2649 
2650  default:
2651  return QgsGeometry();
2652  }
2653 }
2654 
2655 QgsGeometry QgsGeometry::convertToLine( bool destMultipart ) const
2656 {
2657  switch ( type() )
2658  {
2660  {
2661  if ( !isMultipart() )
2662  return QgsGeometry();
2663 
2664  QgsMultiPoint multiPoint = asMultiPoint();
2665  if ( multiPoint.count() < 2 )
2666  return QgsGeometry();
2667 
2668  if ( destMultipart )
2669  return fromMultiPolyline( QgsMultiPolyline() << multiPoint );
2670  else
2671  return fromPolyline( multiPoint );
2672  }
2673 
2675  {
2676  bool srcIsMultipart = isMultipart();
2677 
2678  if ( ( destMultipart && srcIsMultipart ) ||
2679  ( !destMultipart && ! srcIsMultipart ) )
2680  {
2681  // return a copy of the same geom
2682  return QgsGeometry( *this );
2683  }
2684  if ( destMultipart )
2685  {
2686  // destination is multipart => makes a multipoint with a single line
2687  QgsPolyline line = asPolyline();
2688  if ( !line.isEmpty() )
2689  return fromMultiPolyline( QgsMultiPolyline() << line );
2690  }
2691  else
2692  {
2693  // destination is singlepart => make a single part if possible
2694  QgsMultiPolyline multiLine = asMultiPolyline();
2695  if ( multiLine.count() == 1 )
2696  return fromPolyline( multiLine[0] );
2697  }
2698  return QgsGeometry();
2699  }
2700 
2702  {
2703  // input geometry is multipolygon
2704  if ( isMultipart() )
2705  {
2706  QgsMultiPolygon multiPolygon = asMultiPolygon();
2707  QgsMultiPolyline multiLine;
2708  for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
2709  for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
2710  multiLine << *multiLineIt;
2711 
2712  if ( destMultipart )
2713  {
2714  // destination is multipart
2715  return fromMultiPolyline( multiLine );
2716  }
2717  else if ( multiLine.count() == 1 )
2718  {
2719  // destination is singlepart => make a single part if possible
2720  return fromPolyline( multiLine[0] );
2721  }
2722  }
2723  // input geometry is single polygon
2724  else
2725  {
2726  QgsPolygon polygon = asPolygon();
2727  // if polygon has rings
2728  if ( polygon.count() > 1 )
2729  {
2730  // cannot fit a polygon with rings in a single line layer
2731  // TODO: would it be better to remove rings?
2732  if ( destMultipart )
2733  {
2734  QgsPolygon polygon = asPolygon();
2735  QgsMultiPolyline multiLine;
2736  for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
2737  multiLine << *multiLineIt;
2738  return fromMultiPolyline( multiLine );
2739  }
2740  }
2741  // no rings
2742  else if ( polygon.count() == 1 )
2743  {
2744  if ( destMultipart )
2745  {
2746  return fromMultiPolyline( polygon );
2747  }
2748  else
2749  {
2750  return fromPolyline( polygon[0] );
2751  }
2752  }
2753  }
2754  return QgsGeometry();
2755  }
2756 
2757  default:
2758  return QgsGeometry();
2759  }
2760 }
2761 
2762 QgsGeometry QgsGeometry::convertToPolygon( bool destMultipart ) const
2763 {
2764  switch ( type() )
2765  {
2767  {
2768  if ( !isMultipart() )
2769  return QgsGeometry();
2770 
2771  QgsMultiPoint multiPoint = asMultiPoint();
2772  if ( multiPoint.count() < 3 )
2773  return QgsGeometry();
2774 
2775  if ( multiPoint.last() != multiPoint.first() )
2776  multiPoint << multiPoint.first();
2777 
2778  QgsPolygon polygon = QgsPolygon() << multiPoint;
2779  if ( destMultipart )
2780  return fromMultiPolygon( QgsMultiPolygon() << polygon );
2781  else
2782  return fromPolygon( polygon );
2783  }
2784 
2786  {
2787  // input geometry is multiline
2788  if ( isMultipart() )
2789  {
2790  QgsMultiPolyline multiLine = asMultiPolyline();
2791  QgsMultiPolygon multiPolygon;
2792  for ( QgsMultiPolyline::iterator multiLineIt = multiLine.begin(); multiLineIt != multiLine.end(); ++multiLineIt )
2793  {
2794  // do not create polygon for a 1 segment line
2795  if ( ( *multiLineIt ).count() < 3 )
2796  return QgsGeometry();
2797  if ( ( *multiLineIt ).count() == 3 && ( *multiLineIt ).first() == ( *multiLineIt ).last() )
2798  return QgsGeometry();
2799 
2800  // add closing node
2801  if ( ( *multiLineIt ).first() != ( *multiLineIt ).last() )
2802  *multiLineIt << ( *multiLineIt ).first();
2803  multiPolygon << ( QgsPolygon() << *multiLineIt );
2804  }
2805  // check that polygons were inserted
2806  if ( !multiPolygon.isEmpty() )
2807  {
2808  if ( destMultipart )
2809  {
2810  return fromMultiPolygon( multiPolygon );
2811  }
2812  else if ( multiPolygon.count() == 1 )
2813  {
2814  // destination is singlepart => make a single part if possible
2815  return fromPolygon( multiPolygon[0] );
2816  }
2817  }
2818  }
2819  // input geometry is single line
2820  else
2821  {
2822  QgsPolyline line = asPolyline();
2823 
2824  // do not create polygon for a 1 segment line
2825  if ( line.count() < 3 )
2826  return QgsGeometry();
2827  if ( line.count() == 3 && line.first() == line.last() )
2828  return QgsGeometry();
2829 
2830  // add closing node
2831  if ( line.first() != line.last() )
2832  line << line.first();
2833 
2834  // destination is multipart
2835  if ( destMultipart )
2836  {
2837  return fromMultiPolygon( QgsMultiPolygon() << ( QgsPolygon() << line ) );
2838  }
2839  else
2840  {
2841  return fromPolygon( QgsPolygon() << line );
2842  }
2843  }
2844  return QgsGeometry();
2845  }
2846 
2848  {
2849  bool srcIsMultipart = isMultipart();
2850 
2851  if ( ( destMultipart && srcIsMultipart ) ||
2852  ( !destMultipart && ! srcIsMultipart ) )
2853  {
2854  // return a copy of the same geom
2855  return QgsGeometry( *this );
2856  }
2857  if ( destMultipart )
2858  {
2859  // destination is multipart => makes a multipoint with a single polygon
2860  QgsPolygon polygon = asPolygon();
2861  if ( !polygon.isEmpty() )
2862  return fromMultiPolygon( QgsMultiPolygon() << polygon );
2863  }
2864  else
2865  {
2866  QgsMultiPolygon multiPolygon = asMultiPolygon();
2867  if ( multiPolygon.count() == 1 )
2868  {
2869  // destination is singlepart => make a single part if possible
2870  return fromPolygon( multiPolygon[0] );
2871  }
2872  }
2873  return QgsGeometry();
2874  }
2875 
2876  default:
2877  return QgsGeometry();
2878  }
2879 }
2880 
2882 {
2883  return new QgsGeos( geometry );
2884 }
2885 
2886 QDataStream &operator<<( QDataStream &out, const QgsGeometry &geometry )
2887 {
2888  out << geometry.exportToWkb();
2889  return out;
2890 }
2891 
2892 QDataStream &operator>>( QDataStream &in, QgsGeometry &geometry )
2893 {
2894  QByteArray byteArray;
2895  in >> byteArray;
2896  if ( byteArray.isEmpty() )
2897  {
2898  geometry.setGeometry( nullptr );
2899  return in;
2900  }
2901 
2902  geometry.fromWkb( byteArray );
2903  return in;
2904 }
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:38
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:1709
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.
QList< QgsPointV2 > QgsPointSequence
QgsGeometry mergeLines(QString *errorMsg=nullptr) const
Merges any connected lines in a LineString/MultiLineString geometry and converts them to single line ...
Definition: qgsgeos.cpp:1860
void points(QgsPointSequence &pt) const override
Returns a list of points within the curve.
static Type multiType(Type type)
Returns the multi type for a WKB type.
Definition: qgswkbtypes.h:293
virtual bool deleteVertex(QgsVertexId position)=0
Deletes a vertex within the geometry.
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:550
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer&#39;s length...
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:1914
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:48
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:1299
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:96
void setX(double x)
Sets the point&#39;s x-coordinate.
Definition: qgspointv2.h:141
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:1449
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:580
double y() const
Returns the point&#39;s y-coordinate.
Definition: qgspointv2.h:91
QgsGeometry closestPoint(const QgsGeometry &other, QString *errorMsg=nullptr) const
Returns the closest point on the geometry to the other geometry.
Definition: qgsgeos.cpp:1879
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 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:1463
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:2569
static GEOSGeometry * asGeos(const QgsAbstractGeometry *geom, double precision=0)
Definition: qgsgeos.cpp:1078
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:1725
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:35
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:66
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.
static QgsGeometry fromQPointF(QPointF point)
Construct geometry from a QPointF.
QgsLineString * smoothCurve(const QgsLineString &line, const unsigned int iterations, const double offset, double squareDistThreshold, double maxAngleRads, bool isRing)
QgsGeometry convexHull() const
Returns the smallest convex polygon that contains all the points in the geometry. ...
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:118
Point geometry type, with support for z-dimension and m-values.
Definition: qgspointv2.h:37
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Returns a copy of the geometry which has been densified by adding the specified number of extra nodes...
QList< QgsGeometry > asGeometryCollection() const
Return contents of the geometry as a list of geometries.
bool deleteVertex(int atVertex)
Deletes the vertex at the given position number and item (first number is index 0) Returns false if a...
double yAt(int index) const override
Returns the y-coordinate of the specified node in the line string.
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:652
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:76
QVector< QgsPoint > QgsMultiPoint
A collection of QgsPoints that share a common collection of attributes.
Definition: qgsgeometry.h:62
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:85
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...
double sqrDistToVertexAt(QgsPoint &point SIP_IN, int atVertex) const
Returns the squared cartesian distance between the given point to the given vertex index (vertex at t...
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:1752
QString exportToWkt(int precision=17) const
Exports the geometry to WKT.
QgsGeometry singleSidedBuffer(double distance, int segments, BufferSide side, JoinStyle joinStyle=JoinStyleRound, double mitreLimit=2.0) const
Returns a single sided buffer for a (multi)line geometry.
virtual double area() const
Returns the area of the geometry.
virtual int ringCount(int part=0) const =0
Returns the number of rings of which this geometry is built.
Abstract base class for curved geometry type.
Definition: qgscurve.h:34
QVector< QgsPolyline > QgsPolygon
Polygon: first item of the list is outer ring, inner rings (if any) start from second item...
Definition: qgsgeometry.h:55
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
bool touches(const QgsGeometry &geometry) const
Test for if geometry touch another (uses GEOS)
Abstract base class for all geometries.
virtual QgsCoordinateSequence coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
void convertToStraightSegment()
Converts the geometry to straight line segments, if it is a curved geometry type. ...
const QgsCurve * exteriorRing() const
Does vector analysis using the geos library and handles import, export, exception handling*...
Definition: qgsgeos.h:31
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:2060
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
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:106
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:69
static QgsGeometry fromMultiPolygon(const QgsMultiPolygon &multipoly)
Creates a new geometry from a QgsMultiPolygon.
double interpolateAngle(double distance) const
Returns the angle parallel to the linestring or polygon boundary at the specified distance along the ...
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:91
static QgsAbstractGeometry * fromPolyline(const QgsPolyline &polyline)
Construct geometry from a polyline.
BufferSide
Side of line to buffer.
Definition: qgsgeometry.h:573
static QgsGeometry unaryUnion(const QList< QgsGeometry > &geometries)
Compute the unary union on a list of geometries.
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:136
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
int vertexNrFromVertexId(QgsVertexId i) const
Returns the vertex number corresponding to a vertex idd.
virtual QgsCoordinateSequence coordinateSequence() const =0
Retrieves the sequence of geometries, rings and nodes.
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:865
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:1432
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:598
GEOSGeometry * exportToGeos(double precision=0) const
Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destr...
virtual void draw(QPainter &p) const =0
Draws the geometry using the specified QPainter.
QgsMultiPolygon asMultiPolygon() const
Return contents of the geometry as a multi polygon if wkbType is WKBMultiPolygon, otherwise an empty ...
double distance(const QgsAbstractGeometry &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp: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:1361
bool vertexIdFromVertexNr(int nr, QgsVertexId &id) const
Calculates the vertex ID from a vertex number.
bool isSimple() const
Determines whether the geometry is simple (according to OGC definition), i.e.
void setGeometry(QgsAbstractGeometry *geometry)
Sets the underlying geometry store.
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:40
QPointF asQPointF() const
Return contents of the geometry as a QPointF if wkbType is WKBPoint, otherwise returns a null QPointF...
virtual int vertexCount(int part=0, int ring=0) const =0
Returns the number of vertexes of which this geometry is built.
virtual QgsLineString * curveToLine(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const =0
Returns a new line string geometry corresponding to a segmentized approximation of the curve...
void validateGeometry(QList< QgsGeometry::Error > &errors)
Validate geometry and produce a list of geometry errors.
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:1987
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
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:96
int transform(const QgsCoordinateTransform &ct)
Transform this geometry as described by CoordinateTransform ct.
bool pointOnSurface(QgsPointV2 &pt, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1403
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
void adjacentVertices(int atVertex, int &beforeVertex, int &afterVertex) const
Returns the indexes of the vertices before and after the given vertex index.
QgsGeometry convertToType(QgsWkbTypes::GeometryType destType, bool destMultipart=false) const
Try to convert the geometry to the requested type.
Multi polygon geometry collection.
Contains geometry relation and modification algorithms.
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:101
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:2026
JoinStyle
Join styles for buffers.
Definition: qgsgeometry.h:588
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Densifies the geometry by adding the specified number of extra nodes within each segment of the geome...
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:423
QgsGeometry delaunayTriangulation(double tolerance=0.0, bool edgesOnly=false) const
Returns the Delaunay triangulation for the vertices of the geometry.
QgsGeometry smooth(const unsigned int iterations=1, const double offset=0.25, double minimumDistance=-1.0, double maxAngle=180.0) const
Smooths a geometry by rounding off corners using the Chaikin algorithm.
virtual bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
static QgsGeometry polygonize(const QList< QgsGeometry > &geometries)
Creates a GeometryCollection geometry containing possible polygons formed from the constituent linewo...
void removeInteriorRings(double minimumAllowedArea=-1)
Removes the interior rings from the polygon.
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
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
virtual int numPoints() const =0
Returns the number of points in the curve.
static double distanceToVertex(const QgsAbstractGeometry &geom, QgsVertexId id)
Returns the distance along a geometry from its first vertex to the specified vertex.
QgsAbstractGeometry * geometry() const
Returns the underlying geometry store.
double lineLocatePoint(const QgsGeometry &point) const
Returns a distance representing the location along this linestring of the closest point on this lines...
bool disjoint(const QgsGeometry &geometry) const
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.
bool isSimple(QString *errorMsg=nullptr) const override
Determines whether the geometry is simple (according to OGC definition).
Definition: qgsgeos.cpp:1497
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:1331
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:125
static QgsGeometry fromMultiPolyline(const QgsMultiPolyline &multiline)
Creates a new geometry from a QgsMultiPolyline object.
QDataStream & operator>>(QDataStream &in, QgsGeometry &geometry)
Reads a geometry from stream in into geometry. QGIS version compatibility is not guaranteed.
int avoidIntersections(const QList< QgsVectorLayer *> &avoidIntersectionsLayers, const QHash< QgsVectorLayer *, QSet< QgsFeatureId > > &ignoreFeatures=(QHash< QgsVectorLayer *, QSet< QgsFeatureId > >()))
Modifies geometry to avoid intersections with the layers specified in project properties.
void extend(double startDistance, double endDistance)
Extends the line geometry by extrapolating out the start or end of the line by a specified distance...
double x
Definition: qgspoint.h:41
QgsGeometry difference(const QgsGeometry &geometry) const
Returns a geometry representing the points making up this geometry that do not make up other...