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