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