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