QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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  sqrDist = -1;
351  return QgsPoint( 0, 0 );
352  }
353 
354  QgsPointV2 pt( point.x(), point.y() );
355  QgsVertexId id;
356 
357  QgsPointV2 vp = QgsGeometryUtils::closestVertex( *( d->geometry ), pt, id );
358  if ( !id.isValid() )
359  {
360  sqrDist = -1;
361  return QgsPoint( 0, 0 );
362  }
363  sqrDist = QgsGeometryUtils::sqrDistance2D( pt, vp );
364 
365  atVertex = vertexNrFromVertexId( id );
366  adjacentVertices( atVertex, beforeVertex, afterVertex );
367  return QgsPoint( vp.x(), vp.y() );
368 }
369 
370 double QgsGeometry::distanceToVertex( int vertex ) const
371 {
372  if ( !d->geometry )
373  {
374  return -1;
375  }
376 
377  QgsVertexId id;
378  if ( !vertexIdFromVertexNr( vertex, id ) )
379  {
380  return -1;
381  }
382 
383  return QgsGeometryUtils::distanceToVertex( *( d->geometry ), id );
384 }
385 
386 double QgsGeometry::angleAtVertex( int vertex ) const
387 {
388  if ( !d->geometry )
389  {
390  return 0;
391  }
392 
393  QgsVertexId v2;
394  if ( !vertexIdFromVertexNr( vertex, v2 ) )
395  {
396  return 0;
397  }
398 
399  QgsVertexId v1;
400  QgsVertexId v3;
401  QgsGeometryUtils::adjacentVertices( *d->geometry, v2, v1, v3 );
402  if ( v1.isValid() && v3.isValid() )
403  {
404  QgsPointV2 p1 = d->geometry->vertexAt( v1 );
405  QgsPointV2 p2 = d->geometry->vertexAt( v2 );
406  QgsPointV2 p3 = d->geometry->vertexAt( v3 );
407  double angle1 = QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
408  double angle2 = QgsGeometryUtils::lineAngle( p2.x(), p2.y(), p3.x(), p3.y() );
409  return QgsGeometryUtils::averageAngle( angle1, angle2 );
410  }
411  else if ( v3.isValid() )
412  {
413  QgsPointV2 p1 = d->geometry->vertexAt( v2 );
414  QgsPointV2 p2 = d->geometry->vertexAt( v3 );
415  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
416  }
417  else if ( v1.isValid() )
418  {
419  QgsPointV2 p1 = d->geometry->vertexAt( v1 );
420  QgsPointV2 p2 = d->geometry->vertexAt( v2 );
421  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
422  }
423  return 0.0;
424 }
425 
426 void QgsGeometry::adjacentVertices( int atVertex, int& beforeVertex, int& afterVertex ) const
427 {
428  if ( !d->geometry )
429  {
430  return;
431  }
432 
433  QgsVertexId id;
434  if ( !vertexIdFromVertexNr( atVertex, id ) )
435  {
436  beforeVertex = -1;
437  afterVertex = -1;
438  return;
439  }
440 
441  QgsVertexId beforeVertexId, afterVertexId;
442  QgsGeometryUtils::adjacentVertices( *( d->geometry ), id, beforeVertexId, afterVertexId );
443  beforeVertex = vertexNrFromVertexId( beforeVertexId );
444  afterVertex = vertexNrFromVertexId( afterVertexId );
445 }
446 
447 bool QgsGeometry::moveVertex( double x, double y, int atVertex )
448 {
449  if ( !d->geometry )
450  {
451  return false;
452  }
453 
454  QgsVertexId id;
455  if ( !vertexIdFromVertexNr( atVertex, id ) )
456  {
457  return false;
458  }
459 
460  detach( true );
461 
462  removeWkbGeos();
463  return d->geometry->moveVertex( id, QgsPointV2( x, y ) );
464 }
465 
466 bool QgsGeometry::moveVertex( const QgsPointV2& p, int atVertex )
467 {
468  if ( !d->geometry )
469  {
470  return false;
471  }
472 
473  QgsVertexId id;
474  if ( !vertexIdFromVertexNr( atVertex, id ) )
475  {
476  return false;
477  }
478 
479  detach( true );
480 
481  removeWkbGeos();
482  return d->geometry->moveVertex( id, p );
483 }
484 
485 bool QgsGeometry::deleteVertex( int atVertex )
486 {
487  if ( !d->geometry )
488  {
489  return false;
490  }
491 
492  //maintain compatibility with < 2.10 API
494  {
495  detach( true );
496  removeWkbGeos();
497  //delete geometry instead of point
498  return static_cast< QgsGeometryCollectionV2* >( d->geometry )->removeGeometry( atVertex );
499  }
500 
501  //if it is a point, set the geometry to nullptr
503  {
504  detach( false );
505  delete d->geometry;
506  removeWkbGeos();
507  d->geometry = nullptr;
508  return true;
509  }
510 
511  QgsVertexId id;
512  if ( !vertexIdFromVertexNr( atVertex, id ) )
513  {
514  return false;
515  }
516 
517  detach( true );
518 
519  removeWkbGeos();
520  return d->geometry->deleteVertex( id );
521 }
522 
523 bool QgsGeometry::insertVertex( double x, double y, int beforeVertex )
524 {
525  if ( !d->geometry )
526  {
527  return false;
528  }
529 
530  //maintain compatibility with < 2.10 API
532  {
533  detach( true );
534  removeWkbGeos();
535  //insert geometry instead of point
536  return static_cast< QgsGeometryCollectionV2* >( d->geometry )->insertGeometry( new QgsPointV2( x, y ), beforeVertex );
537  }
538 
539  QgsVertexId id;
540  if ( !vertexIdFromVertexNr( beforeVertex, id ) )
541  {
542  return false;
543  }
544 
545  detach( true );
546 
547  removeWkbGeos();
548 
549  return d->geometry->insertVertex( id, QgsPointV2( x, y ) );
550 }
551 
552 QgsPoint QgsGeometry::vertexAt( int atVertex ) const
553 {
554  if ( !d->geometry )
555  {
556  return QgsPoint( 0, 0 );
557  }
558 
559  QgsVertexId vId;
560  ( void )vertexIdFromVertexNr( atVertex, vId );
561  if ( vId.vertex < 0 )
562  {
563  return QgsPoint( 0, 0 );
564  }
565  QgsPointV2 pt = d->geometry->vertexAt( vId );
566  return QgsPoint( pt.x(), pt.y() );
567 }
568 
569 double QgsGeometry::sqrDistToVertexAt( QgsPoint& point, int atVertex ) const
570 {
571  QgsPoint vertexPoint = vertexAt( atVertex );
572  return QgsGeometryUtils::sqrDistance2D( QgsPointV2( vertexPoint.x(), vertexPoint.y() ), QgsPointV2( point.x(), point.y() ) );
573 }
574 
576 {
577  QgsGeos geos( d->geometry );
578  return geos.closestPoint( other );
579 }
580 
582 {
583  QgsGeos geos( d->geometry );
584  return geos.shortestLine( other );
585 }
586 
587 double QgsGeometry::closestVertexWithContext( const QgsPoint& point, int& atVertex ) const
588 {
589  if ( !d->geometry )
590  {
591  return -1;
592  }
593 
594  QgsVertexId vId;
595  QgsPointV2 pt( point.x(), point.y() );
596  QgsPointV2 closestPoint = QgsGeometryUtils::closestVertex( *( d->geometry ), pt, vId );
597  if ( !vId.isValid() )
598  return -1;
599  atVertex = vertexNrFromVertexId( vId );
600  return QgsGeometryUtils::sqrDistance2D( closestPoint, pt );
601 }
602 
604  const QgsPoint& point,
605  QgsPoint& minDistPoint,
606  int& afterVertex,
607  double *leftOf,
608  double epsilon ) const
609 {
610  if ( !d->geometry )
611  {
612  return -1;
613  }
614 
615  QgsPointV2 segmentPt;
616  QgsVertexId vertexAfter;
617  bool leftOfBool;
618 
619  double sqrDist = d->geometry->closestSegment( QgsPointV2( point.x(), point.y() ), segmentPt, vertexAfter, &leftOfBool, epsilon );
620  if ( sqrDist < 0 )
621  return -1;
622 
623  minDistPoint.setX( segmentPt.x() );
624  minDistPoint.setY( segmentPt.y() );
625  afterVertex = vertexNrFromVertexId( vertexAfter );
626  if ( leftOf )
627  {
628  *leftOf = leftOfBool ? 1.0 : -1.0;
629  }
630  return sqrDist;
631 }
632 
634 {
635  detach( true );
636 
637  removeWkbGeos();
638  QgsLineStringV2* ringLine = new QgsLineStringV2();
639  QgsPointSequenceV2 ringPoints;
640  convertPointList( ring, ringPoints );
641  ringLine->setPoints( ringPoints );
642  return addRing( ringLine );
643 }
644 
646 {
647  if ( !d->geometry )
648  {
649  delete ring;
650  return 1;
651  }
652 
653  detach( true );
654 
655  removeWkbGeos();
656  return QgsGeometryEditUtils::addRing( d->geometry, ring );
657 }
658 
660 {
662  convertPointList( points, l );
663  return addPart( l, geomType );
664 }
665 
667 {
668  QgsAbstractGeometryV2* partGeom = nullptr;
669  if ( points.size() == 1 )
670  {
671  partGeom = new QgsPointV2( points[0] );
672  }
673  else if ( points.size() > 1 )
674  {
675  QgsLineStringV2* ringLine = new QgsLineStringV2();
676  ringLine->setPoints( points );
677  partGeom = ringLine;
678  }
679  return addPart( partGeom, geomType );
680 }
681 
683 {
684  if ( !d->geometry )
685  {
686  detach( false );
687  switch ( geomType )
688  {
689  case QGis::Point:
690  d->geometry = new QgsMultiPointV2();
691  break;
692  case QGis::Line:
693  d->geometry = new QgsMultiLineStringV2();
694  break;
695  case QGis::Polygon:
696  d->geometry = new QgsMultiPolygonV2();
697  break;
698  default:
699  return 1;
700  }
701  }
702  else
703  {
704  detach( true );
705  removeWkbGeos();
706  }
707 
709  return QgsGeometryEditUtils::addPart( d->geometry, part );
710 }
711 
712 int QgsGeometry::addPart( const QgsGeometry *newPart )
713 {
714  if ( !d->geometry || !newPart || !newPart->d || !newPart->d->geometry )
715  {
716  return 1;
717  }
718 
719  return addPart( newPart->d->geometry->clone() );
720 }
721 
722 int QgsGeometry::addPart( GEOSGeometry *newPart )
723 {
724  if ( !d->geometry || !newPart )
725  {
726  return 1;
727  }
728 
729  detach( true );
730 
731  QgsAbstractGeometryV2* geom = QgsGeos::fromGeos( newPart );
732  removeWkbGeos();
733  return QgsGeometryEditUtils::addPart( d->geometry, geom );
734 }
735 
736 int QgsGeometry::translate( double dx, double dy )
737 {
738  if ( !d->geometry )
739  {
740  return 1;
741  }
742 
743  detach( true );
744 
746  removeWkbGeos();
747  return 0;
748 }
749 
750 int QgsGeometry::rotate( double rotation, const QgsPoint& center )
751 {
752  if ( !d->geometry )
753  {
754  return 1;
755  }
756 
757  detach( true );
758 
759  QTransform t = QTransform::fromTranslate( center.x(), center.y() );
760  t.rotate( -rotation );
761  t.translate( -center.x(), -center.y() );
762  d->geometry->transform( t );
763  removeWkbGeos();
764  return 0;
765 }
766 
767 int QgsGeometry::splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries, bool topological, QList<QgsPoint> &topologyTestPoints )
768 {
769  if ( !d->geometry )
770  {
771  return 0;
772  }
773 
775  QgsLineStringV2 splitLineString;
776  QgsPointSequenceV2 splitLinePointsV2;
777  convertPointList( splitLine, splitLinePointsV2 );
778  splitLineString.setPoints( splitLinePointsV2 );
780 
781  QgsGeos geos( d->geometry );
782  int result = geos.splitGeometry( splitLineString, newGeoms, topological, tp );
783 
784  if ( result == 0 )
785  {
786  detach( false );
787  d->geometry = newGeoms.at( 0 );
788 
789  newGeometries.clear();
790  for ( int i = 1; i < newGeoms.size(); ++i )
791  {
792  newGeometries.push_back( new QgsGeometry( newGeoms.at( i ) ) );
793  }
794  }
795 
796  convertPointList( tp, topologyTestPoints );
797  removeWkbGeos();
798  return result;
799 }
800 
802 int QgsGeometry::reshapeGeometry( const QList<QgsPoint>& reshapeWithLine )
803 {
804  QgsPointSequenceV2 reshapeLine;
805  convertPointList( reshapeWithLine, reshapeLine );
806  return reshapeGeometry( reshapeLine );
807 }
808 
810 {
811  if ( !d->geometry )
812  {
813  return 0;
814  }
815 
816  QgsLineStringV2 reshapeLineString;
817  reshapeLineString.setPoints( reshapeLine );
818  QgsGeos geos( d->geometry );
819  int errorCode = 0;
820  QgsAbstractGeometryV2* geom = geos.reshapeGeometry( reshapeLineString, &errorCode );
821 
822  if ( errorCode == 0 && geom )
823  {
824  detach( false );
825  removeWkbGeos();
826  d->geometry = geom;
827  return 0;
828  }
829 
830  delete geom;
831 
832  return errorCode;
833 }
834 
836 {
837  if ( !d->geometry || !other->d->geometry )
838  {
839  return 0;
840  }
841 
842  QgsGeos geos( d->geometry );
843 
844  QgsAbstractGeometryV2* diffGeom = geos.intersection( *( other->geometry() ) );
845  if ( !diffGeom )
846  {
847  return 1;
848  }
849 
850  detach( false );
851 
852  delete d->geometry;
853  d->geometry = diffGeom;
854  removeWkbGeos();
855  return 0;
856 }
857 
859 {
860  if ( d->geometry )
861  {
862  return d->geometry->boundingBox();
863  }
864  return QgsRectangle();
865 }
866 
867 bool QgsGeometry::intersects( const QgsRectangle& r ) const
868 {
869  QgsGeometry* g = fromRect( r );
870  bool res = intersects( g );
871  delete g;
872  return res;
873 }
874 
876 {
877  if ( !d->geometry || !geometry || !geometry->d->geometry )
878  {
879  return false;
880  }
881 
882  QgsGeos geos( d->geometry );
883  return geos.intersects( *( geometry->d->geometry ) );
884 }
885 
886 bool QgsGeometry::contains( const QgsPoint* p ) const
887 {
888  if ( !d->geometry || !p )
889  {
890  return false;
891  }
892 
893  QgsPointV2 pt( p->x(), p->y() );
894  QgsGeos geos( d->geometry );
895  return geos.contains( pt );
896 }
897 
899 {
900  if ( !d->geometry || !geometry || !geometry->d->geometry )
901  {
902  return false;
903  }
904 
905  QgsGeos geos( d->geometry );
906  return geos.contains( *( geometry->d->geometry ) );
907 }
908 
910 {
911  if ( !d->geometry || !geometry || !geometry->d->geometry )
912  {
913  return false;
914  }
915 
916  QgsGeos geos( d->geometry );
917  return geos.disjoint( *( geometry->d->geometry ) );
918 }
919 
921 {
922  if ( !d->geometry || !geometry || !geometry->d->geometry )
923  {
924  return false;
925  }
926 
927  QgsGeos geos( d->geometry );
928  return geos.isEqual( *( geometry->d->geometry ) );
929 }
930 
932 {
933  if ( !d->geometry || !geometry || !geometry->d->geometry )
934  {
935  return false;
936  }
937 
938  QgsGeos geos( d->geometry );
939  return geos.touches( *( geometry->d->geometry ) );
940 }
941 
943 {
944  if ( !d->geometry || !geometry || !geometry->d->geometry )
945  {
946  return false;
947  }
948 
949  QgsGeos geos( d->geometry );
950  return geos.overlaps( *( geometry->d->geometry ) );
951 }
952 
954 {
955  if ( !d->geometry || !geometry || !geometry->d->geometry )
956  {
957  return false;
958  }
959 
960  QgsGeos geos( d->geometry );
961  return geos.within( *( geometry->d->geometry ) );
962 }
963 
965 {
966  if ( !d->geometry || !geometry || !geometry->d->geometry )
967  {
968  return false;
969  }
970 
971  QgsGeos geos( d->geometry );
972  return geos.crosses( *( geometry->d->geometry ) );
973 }
974 
975 QString QgsGeometry::exportToWkt( int precision ) const
976 {
977  if ( !d->geometry )
978  {
979  return QString();
980  }
981  return d->geometry->asWkt( precision );
982 }
983 
984 QString QgsGeometry::exportToGeoJSON( int precision ) const
985 {
986  if ( !d->geometry )
987  {
988  return QString( "null" );
989  }
990  return d->geometry->asJSON( precision );
991 }
992 
993 QgsGeometry* QgsGeometry::convertToType( QGis::GeometryType destType, bool destMultipart ) const
994 {
995  switch ( destType )
996  {
997  case QGis::Point:
998  return convertToPoint( destMultipart );
999 
1000  case QGis::Line:
1001  return convertToLine( destMultipart );
1002 
1003  case QGis::Polygon:
1004  return convertToPolygon( destMultipart );
1005 
1006  default:
1007  return nullptr;
1008  }
1009 }
1010 
1012 {
1013  if ( !d->geometry )
1014  {
1015  return false;
1016  }
1017 
1018  if ( isMultipart() ) //already multitype, no need to convert
1019  {
1020  return true;
1021  }
1022 
1023  QgsGeometryCollectionV2* multiGeom = dynamic_cast<QgsGeometryCollectionV2*>
1025  if ( !multiGeom )
1026  {
1027  return false;
1028  }
1029 
1030  detach( true );
1031  multiGeom->addGeometry( d->geometry );
1032  d->geometry = multiGeom;
1033  removeWkbGeos();
1034  return true;
1035 }
1036 
1038 {
1039  if ( !d->geometry )
1040  {
1041  return false;
1042  }
1043 
1044  if ( !isMultipart() ) //already single part, no need to convert
1045  {
1046  return true;
1047  }
1048 
1049  QgsGeometryCollectionV2* multiGeom = dynamic_cast<QgsGeometryCollectionV2*>( d->geometry );
1050  if ( !multiGeom || multiGeom->partCount() < 1 )
1051  return false;
1052 
1053  QgsAbstractGeometryV2* firstPart = multiGeom->geometryN( 0 )->clone();
1054  detach( false );
1055 
1056  d->geometry = firstPart;
1057  removeWkbGeos();
1058  return true;
1059 }
1060 
1062 {
1064  {
1065  return QgsPoint();
1066  }
1067  QgsPointV2* pt = dynamic_cast<QgsPointV2*>( d->geometry );
1068  if ( !pt )
1069  {
1070  return QgsPoint();
1071  }
1072 
1073  return QgsPoint( pt->x(), pt->y() );
1074 }
1075 
1077 {
1078  QgsPolyline polyLine;
1079  if ( !d->geometry )
1080  {
1081  return polyLine;
1082  }
1083 
1084  bool doSegmentation = ( QgsWKBTypes::flatType( d->geometry->wkbType() ) == QgsWKBTypes::CompoundCurve
1086  QgsLineStringV2* line = nullptr;
1087  if ( doSegmentation )
1088  {
1089  QgsCurveV2* curve = dynamic_cast<QgsCurveV2*>( d->geometry );
1090  if ( !curve )
1091  {
1092  return polyLine;
1093  }
1094  line = curve->curveToLine();
1095  }
1096  else
1097  {
1098  line = dynamic_cast<QgsLineStringV2*>( d->geometry );
1099  if ( !line )
1100  {
1101  return polyLine;
1102  }
1103  }
1104 
1105  int nVertices = line->numPoints();
1106  polyLine.resize( nVertices );
1107  for ( int i = 0; i < nVertices; ++i )
1108  {
1109  QgsPointV2 pt = line->pointN( i );
1110  polyLine[i].setX( pt.x() );
1111  polyLine[i].setY( pt.y() );
1112  }
1113 
1114  if ( doSegmentation )
1115  {
1116  delete line;
1117  }
1118 
1119  return polyLine;
1120 }
1121 
1123 {
1124  if ( !d->geometry )
1125  return QgsPolygon();
1126 
1127  bool doSegmentation = ( QgsWKBTypes::flatType( d->geometry->wkbType() ) == QgsWKBTypes::CurvePolygon );
1128 
1129  QgsPolygonV2* p = nullptr;
1130  if ( doSegmentation )
1131  {
1132  QgsCurvePolygonV2* curvePoly = dynamic_cast<QgsCurvePolygonV2*>( d->geometry );
1133  if ( !curvePoly )
1134  {
1135  return QgsPolygon();
1136  }
1137  p = curvePoly->toPolygon();
1138  }
1139  else
1140  {
1141  p = dynamic_cast<QgsPolygonV2*>( d->geometry );
1142  }
1143 
1144  if ( !p )
1145  {
1146  return QgsPolygon();
1147  }
1148 
1149  QgsPolygon polygon;
1150  convertPolygon( *p, polygon );
1151 
1152  if ( doSegmentation )
1153  {
1154  delete p;
1155  }
1156  return polygon;
1157 }
1158 
1160 {
1162  {
1163  return QgsMultiPoint();
1164  }
1165 
1166  const QgsMultiPointV2* mp = dynamic_cast<QgsMultiPointV2*>( d->geometry );
1167  if ( !mp )
1168  {
1169  return QgsMultiPoint();
1170  }
1171 
1172  int nPoints = mp->numGeometries();
1173  QgsMultiPoint multiPoint( nPoints );
1174  for ( int i = 0; i < nPoints; ++i )
1175  {
1176  const QgsPointV2* pt = static_cast<const QgsPointV2*>( mp->geometryN( i ) );
1177  multiPoint[i].setX( pt->x() );
1178  multiPoint[i].setY( pt->y() );
1179  }
1180  return multiPoint;
1181 }
1182 
1184 {
1185  if ( !d->geometry )
1186  {
1187  return QgsMultiPolyline();
1188  }
1189 
1190  QgsGeometryCollectionV2* geomCollection = dynamic_cast<QgsGeometryCollectionV2*>( d->geometry );
1191  if ( !geomCollection )
1192  {
1193  return QgsMultiPolyline();
1194  }
1195 
1196  int nLines = geomCollection->numGeometries();
1197  if ( nLines < 1 )
1198  {
1199  return QgsMultiPolyline();
1200  }
1201 
1202  QgsMultiPolyline mpl;
1203  for ( int i = 0; i < nLines; ++i )
1204  {
1205  bool deleteLine = false;
1206  const QgsLineStringV2* line = dynamic_cast<const QgsLineStringV2*>( geomCollection->geometryN( i ) );
1207  if ( !line )
1208  {
1209  const QgsCurveV2* curve = dynamic_cast<const QgsCurveV2*>( geomCollection->geometryN( i ) );
1210  if ( !curve )
1211  {
1212  continue;
1213  }
1214  deleteLine = true;
1215  line = curve->curveToLine();
1216  }
1217 
1218  QgsPointSequenceV2 lineCoords;
1219  line->points( lineCoords );
1220  QgsPolyline polyLine;
1221  convertToPolyline( lineCoords, polyLine );
1222  mpl.append( polyLine );
1223 
1224  if ( deleteLine )
1225  {
1226  delete line;
1227  }
1228  }
1229  return mpl;
1230 }
1231 
1233 {
1234  if ( !d->geometry )
1235  {
1236  return QgsMultiPolygon();
1237  }
1238 
1239  QgsGeometryCollectionV2* geomCollection = dynamic_cast<QgsGeometryCollectionV2*>( d->geometry );
1240  if ( !geomCollection )
1241  {
1242  return QgsMultiPolygon();
1243  }
1244 
1245  int nPolygons = geomCollection->numGeometries();
1246  if ( nPolygons < 1 )
1247  {
1248  return QgsMultiPolygon();
1249  }
1250 
1251  QgsMultiPolygon mp;
1252  for ( int i = 0; i < nPolygons; ++i )
1253  {
1254  const QgsPolygonV2* polygon = dynamic_cast<const QgsPolygonV2*>( geomCollection->geometryN( i ) );
1255  if ( !polygon )
1256  {
1257  const QgsCurvePolygonV2* cPolygon = dynamic_cast<const QgsCurvePolygonV2*>( geomCollection->geometryN( i ) );
1258  if ( cPolygon )
1259  {
1260  polygon = cPolygon->toPolygon();
1261  }
1262  else
1263  {
1264  continue;
1265  }
1266  }
1267 
1268  QgsPolygon poly;
1269  convertPolygon( *polygon, poly );
1270  mp.append( poly );
1271  }
1272  return mp;
1273 }
1274 
1275 double QgsGeometry::area() const
1276 {
1277  if ( !d->geometry )
1278  {
1279  return -1.0;
1280  }
1281  QgsGeos g( d->geometry );
1282 
1283 #if 0
1284  //debug: compare geos area with calculation in QGIS
1285  double geosArea = g.area();
1286  double qgisArea = 0;
1287  QgsSurfaceV2* surface = dynamic_cast<QgsSurfaceV2*>( d->geometry );
1288  if ( surface )
1289  {
1290  qgisArea = surface->area();
1291  }
1292 #endif
1293 
1294  return g.area();
1295 }
1296 
1297 double QgsGeometry::length() const
1298 {
1299  if ( !d->geometry )
1300  {
1301  return -1.0;
1302  }
1303  QgsGeos g( d->geometry );
1304  return g.length();
1305 }
1306 
1307 double QgsGeometry::distance( const QgsGeometry& geom ) const
1308 {
1309  if ( !d->geometry || !geom.d->geometry )
1310  {
1311  return -1.0;
1312  }
1313 
1314  QgsGeos g( d->geometry );
1315  return g.distance( *( geom.d->geometry ) );
1316 }
1317 
1318 QgsGeometry* QgsGeometry::buffer( double distance, int segments ) const
1319 {
1320  if ( !d->geometry )
1321  {
1322  return nullptr;
1323  }
1324 
1325  QgsGeos g( d->geometry );
1326  QgsAbstractGeometryV2* geom = g.buffer( distance, segments );
1327  if ( !geom )
1328  {
1329  return nullptr;
1330  }
1331  return new QgsGeometry( geom );
1332 }
1333 
1334 QgsGeometry* QgsGeometry::buffer( double distance, int segments, int endCapStyle, int joinStyle, double mitreLimit ) const
1335 {
1336  if ( !d->geometry )
1337  {
1338  return nullptr;
1339  }
1340 
1341  QgsGeos g( d->geometry );
1342  QgsAbstractGeometryV2* geom = g.buffer( distance, segments, endCapStyle, joinStyle, mitreLimit );
1343  if ( !geom )
1344  {
1345  return nullptr;
1346  }
1347  return new QgsGeometry( geom );
1348 }
1349 
1350 QgsGeometry* QgsGeometry::offsetCurve( double distance, int segments, int joinStyle, double mitreLimit ) const
1351 {
1352  if ( !d->geometry )
1353  {
1354  return nullptr;
1355  }
1356 
1357  QgsGeos geos( d->geometry );
1358  QgsAbstractGeometryV2* offsetGeom = geos.offsetCurve( distance, segments, joinStyle, mitreLimit );
1359  if ( !offsetGeom )
1360  {
1361  return nullptr;
1362  }
1363  return new QgsGeometry( offsetGeom );
1364 }
1365 
1366 QgsGeometry* QgsGeometry::simplify( double tolerance ) const
1367 {
1368  if ( !d->geometry )
1369  {
1370  return nullptr;
1371  }
1372 
1373  QgsGeos geos( d->geometry );
1374  QgsAbstractGeometryV2* simplifiedGeom = geos.simplify( tolerance );
1375  if ( !simplifiedGeom )
1376  {
1377  return nullptr;
1378  }
1379  return new QgsGeometry( simplifiedGeom );
1380 }
1381 
1383 {
1384  if ( !d->geometry )
1385  {
1386  return nullptr;
1387  }
1388 
1389  QgsGeos geos( d->geometry );
1391  bool ok = geos.centroid( centroid );
1392  if ( !ok )
1393  {
1394  return nullptr;
1395  }
1396  return new QgsGeometry( centroid.clone() );
1397 }
1398 
1400 {
1401  if ( !d->geometry )
1402  {
1403  return nullptr;
1404  }
1405 
1406  QgsGeos geos( d->geometry );
1407  QgsPointV2 pt;
1408  bool ok = geos.pointOnSurface( pt );
1409  if ( !ok )
1410  {
1411  return nullptr;
1412  }
1413  return new QgsGeometry( pt.clone() );
1414 }
1415 
1417 {
1418  if ( !d->geometry )
1419  {
1420  return nullptr;
1421  }
1422  QgsGeos geos( d->geometry );
1423  QgsAbstractGeometryV2* cHull = geos.convexHull();
1424  if ( !cHull )
1425  {
1426  return nullptr;
1427  }
1428  return new QgsGeometry( cHull );
1429 }
1430 
1432 {
1433  if ( !d->geometry )
1434  {
1435  return nullptr;
1436  }
1437 
1438  QgsGeometry line = *this;
1439  if ( type() == QGis::Polygon )
1440  line = QgsGeometry( d->geometry->boundary() );
1441 
1442  QgsGeos geos( line.geometry() );
1443  QgsAbstractGeometryV2* result = geos.interpolate( distance );
1444  if ( !result )
1445  {
1446  return nullptr;
1447  }
1448  return new QgsGeometry( result );
1449 }
1450 
1451 double QgsGeometry::lineLocatePoint( const QgsGeometry& point ) const
1452 {
1453  if ( type() != QGis::Line )
1454  return -1;
1455 
1456  if ( QgsWKBTypes::flatType( point.d->geometry->wkbType() ) != QgsWKBTypes::Point )
1457  return -1;
1458 
1459  QgsGeometry segmentized = *this;
1461  {
1462  segmentized = QgsGeometry( static_cast< QgsCurveV2* >( d->geometry )->segmentize() );
1463  }
1464 
1465  QgsGeos geos( d->geometry );
1466  return geos.lineLocatePoint( *( static_cast< QgsPointV2* >( point.d->geometry ) ) );
1467 }
1468 
1470 {
1471  if ( !d->geometry )
1472  return 0.0;
1473 
1474  // always operate on segmentized geometries
1475  QgsGeometry segmentized = *this;
1477  {
1478  segmentized = QgsGeometry( static_cast< QgsCurveV2* >( d->geometry )->segmentize() );
1479  }
1480 
1481  QgsVertexId previous;
1482  QgsVertexId next;
1483  if ( !QgsGeometryUtils::verticesAtDistance( *segmentized.geometry(), distance, previous, next ) )
1484  return 0.0;
1485 
1486  if ( previous == next )
1487  {
1488  // distance coincided exactly with a vertex
1489  QgsVertexId v2 = previous;
1490  QgsVertexId v1;
1491  QgsVertexId v3;
1492  QgsGeometryUtils::adjacentVertices( *segmentized.geometry(), v2, v1, v3 );
1493  if ( v1.isValid() && v3.isValid() )
1494  {
1495  QgsPointV2 p1 = segmentized.geometry()->vertexAt( v1 );
1496  QgsPointV2 p2 = segmentized.geometry()->vertexAt( v2 );
1497  QgsPointV2 p3 = segmentized.geometry()->vertexAt( v3 );
1498  double angle1 = QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1499  double angle2 = QgsGeometryUtils::lineAngle( p2.x(), p2.y(), p3.x(), p3.y() );
1500  return QgsGeometryUtils::averageAngle( angle1, angle2 );
1501  }
1502  else if ( v3.isValid() )
1503  {
1504  QgsPointV2 p1 = segmentized.geometry()->vertexAt( v2 );
1505  QgsPointV2 p2 = segmentized.geometry()->vertexAt( v3 );
1506  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1507  }
1508  else
1509  {
1510  QgsPointV2 p1 = segmentized.geometry()->vertexAt( v1 );
1511  QgsPointV2 p2 = segmentized.geometry()->vertexAt( v2 );
1512  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1513  }
1514  }
1515  else
1516  {
1517  QgsPointV2 p1 = segmentized.geometry()->vertexAt( previous );
1518  QgsPointV2 p2 = segmentized.geometry()->vertexAt( next );
1519  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1520  }
1521 }
1522 
1523 
1525 {
1526  if ( !d->geometry || !geometry->d->geometry )
1527  {
1528  return nullptr;
1529  }
1530 
1531  QgsGeos geos( d->geometry );
1532 
1533  QgsAbstractGeometryV2* resultGeom = geos.intersection( *( geometry->d->geometry ) );
1534  return new QgsGeometry( resultGeom );
1535 }
1536 
1538 {
1539  if ( !d->geometry || !geometry->d->geometry )
1540  {
1541  return nullptr;
1542  }
1543 
1544  QgsGeos geos( d->geometry );
1545 
1546  QgsAbstractGeometryV2* resultGeom = geos.combine( *( geometry->d->geometry ) );
1547  if ( !resultGeom )
1548  {
1549  return nullptr;
1550  }
1551  return new QgsGeometry( resultGeom );
1552 }
1553 
1555 {
1556  if ( !d->geometry )
1557  {
1558  return QgsGeometry();
1559  }
1560 
1562  {
1563  // special case - a single linestring was passed
1564  return QgsGeometry( *this );
1565  }
1566 
1567  QgsGeos geos( d->geometry );
1568  return geos.mergeLines();
1569 }
1570 
1572 {
1573  if ( !d->geometry || !geometry->d->geometry )
1574  {
1575  return nullptr;
1576  }
1577 
1578  QgsGeos geos( d->geometry );
1579 
1580  QgsAbstractGeometryV2* resultGeom = geos.difference( *( geometry->d->geometry ) );
1581  if ( !resultGeom )
1582  {
1583  return nullptr;
1584  }
1585  return new QgsGeometry( resultGeom );
1586 }
1587 
1589 {
1590  if ( !d->geometry || !geometry->d->geometry )
1591  {
1592  return nullptr;
1593  }
1594 
1595  QgsGeos geos( d->geometry );
1596 
1597  QgsAbstractGeometryV2* resultGeom = geos.symDifference( *( geometry->d->geometry ) );
1598  if ( !resultGeom )
1599  {
1600  return nullptr;
1601  }
1602  return new QgsGeometry( resultGeom );
1603 }
1604 
1605 QgsGeometry QgsGeometry::extrude( double x, double y )
1606 {
1607  QgsInternalGeometryEngine engine( *this );
1608 
1609  return engine.extrude( x, y );
1610 }
1611 
1613 {
1614  QList<QgsGeometry*> geometryList;
1615  if ( !d->geometry )
1616  {
1617  return geometryList;
1618  }
1619 
1620  QgsGeometryCollectionV2* gc = dynamic_cast<QgsGeometryCollectionV2*>( d->geometry );
1621  if ( gc )
1622  {
1623  int numGeom = gc->numGeometries();
1624  geometryList.reserve( numGeom );
1625  for ( int i = 0; i < numGeom; ++i )
1626  {
1627  geometryList.append( new QgsGeometry( gc->geometryN( i )->clone() ) );
1628  }
1629  }
1630  else //a singlepart geometry
1631  {
1632  geometryList.append( new QgsGeometry( d->geometry->clone() ) );
1633  }
1634 
1635  return geometryList;
1636 }
1637 
1639 {
1640  QgsPoint point = asPoint();
1641  return point.toQPointF();
1642 }
1643 
1645 {
1646  QPolygonF result;
1647  QgsPolyline polyline;
1649  if ( type == QGis::WKBLineString || type == QGis::WKBLineString25D )
1650  {
1651  polyline = asPolyline();
1652  }
1653  else if ( type == QGis::WKBPolygon || type == QGis::WKBPolygon25D )
1654  {
1655  QgsPolygon polygon = asPolygon();
1656  if ( polygon.size() < 1 )
1657  return result;
1658  polyline = polygon.at( 0 );
1659  }
1660  else
1661  {
1662  return result;
1663  }
1664 
1665  QgsPolyline::const_iterator lineIt = polyline.constBegin();
1666  for ( ; lineIt != polyline.constEnd(); ++lineIt )
1667  {
1668  result << lineIt->toQPointF();
1669  }
1670  return result;
1671 }
1672 
1673 bool QgsGeometry::deleteRing( int ringNum, int partNum )
1674 {
1675  if ( !d->geometry )
1676  {
1677  return false;
1678  }
1679 
1680  detach( true );
1681  bool ok = QgsGeometryEditUtils::deleteRing( d->geometry, ringNum, partNum );
1682  removeWkbGeos();
1683  return ok;
1684 }
1685 
1686 bool QgsGeometry::deletePart( int partNum )
1687 {
1688  if ( !d->geometry )
1689  {
1690  return false;
1691  }
1692 
1693  if ( !isMultipart() && partNum < 1 )
1694  {
1695  setGeometry( nullptr );
1696  return true;
1697  }
1698 
1699  detach( true );
1700  bool ok = QgsGeometryEditUtils::deletePart( d->geometry, partNum );
1701  removeWkbGeos();
1702  return ok;
1703 }
1704 
1706 {
1707  if ( !d->geometry )
1708  {
1709  return 1;
1710  }
1711 
1712  QgsAbstractGeometryV2* diffGeom = QgsGeometryEditUtils::avoidIntersections( *( d->geometry ), ignoreFeatures );
1713  if ( diffGeom )
1714  {
1715  detach( false );
1716  d->geometry = diffGeom;
1717  removeWkbGeos();
1718  }
1719  return 0;
1720 }
1721 
1723 {
1725 }
1726 
1728 {
1729  if ( !d->geometry )
1730  {
1731  return false;
1732  }
1733 
1734  QgsGeos geos( d->geometry );
1735  return geos.isValid();
1736 }
1737 
1739 {
1740  if ( !d->geometry || !g.d->geometry )
1741  {
1742  return false;
1743  }
1744 
1745  QgsGeos geos( d->geometry );
1746  return geos.isEqual( *( g.d->geometry ) );
1747 }
1748 
1750 {
1751  if ( !d->geometry )
1752  {
1753  return false;
1754  }
1755 
1756  QgsGeos geos( d->geometry );
1757  return geos.isEmpty();
1758 }
1759 
1761 {
1762  QgsGeos geos( nullptr );
1763 
1764  QList<QgsAbstractGeometryV2*> geomV2List;
1765  QList<QgsGeometry*>::const_iterator it = geometryList.constBegin();
1766  for ( ; it != geometryList.constEnd(); ++it )
1767  {
1768  if ( *it && !(( *it )->isEmpty() ) )
1769  {
1770  geomV2List.append(( *it )->geometry() );
1771  }
1772  }
1773 
1774  QgsAbstractGeometryV2* geom = geos.combine( geomV2List );
1775  return new QgsGeometry( geom );
1776 }
1777 
1779 {
1781  {
1782  return;
1783  }
1784 
1785  QgsAbstractGeometryV2* straightGeom = d->geometry->segmentize();
1786  detach( false );
1787 
1788  d->geometry = straightGeom;
1789  removeWkbGeos();
1790 }
1791 
1793 {
1794  if ( !d->geometry )
1795  {
1796  return false;
1797  }
1798 
1799  return d->geometry->hasCurvedSegments();
1800 }
1801 
1803 {
1804  if ( !d->geometry )
1805  {
1806  return 1;
1807  }
1808 
1809  detach();
1810  d->geometry->transform( ct );
1811  removeWkbGeos();
1812  return 0;
1813 }
1814 
1816 {
1817  if ( !d->geometry )
1818  {
1819  return 1;
1820  }
1821 
1822  detach();
1823  d->geometry->transform( ct );
1824  removeWkbGeos();
1825  return 0;
1826 }
1827 
1829 {
1830  if ( d->geometry )
1831  {
1832  detach();
1833  d->geometry->transform( mtp.transform() );
1834  removeWkbGeos();
1835  }
1836 }
1837 
1838 #if 0
1839 void QgsGeometry::clip( const QgsRectangle& rect )
1840 {
1841  if ( d->geometry )
1842  {
1843  detach();
1844  d->geometry->clip( rect );
1845  removeWkbGeos();
1846  }
1847 }
1848 #endif
1849 
1850 void QgsGeometry::draw( QPainter& p ) const
1851 {
1852  if ( d->geometry )
1853  {
1854  d->geometry->draw( p );
1855  }
1856 }
1857 
1859 {
1860  if ( !d->geometry )
1861  {
1862  return false;
1863  }
1864 
1866 
1867  int vertexCount = 0;
1868  for ( int part = 0; part < coords.size(); ++part )
1869  {
1870  const QgsRingSequenceV2 &featureCoords = coords.at( part );
1871  for ( int ring = 0; ring < featureCoords.size(); ++ring )
1872  {
1873  const QgsPointSequenceV2 &ringCoords = featureCoords.at( ring );
1874  for ( int vertex = 0; vertex < ringCoords.size(); ++vertex )
1875  {
1876  if ( vertexCount == nr )
1877  {
1878  id.part = part;
1879  id.ring = ring;
1880  id.vertex = vertex;
1881  return true;
1882  }
1883  ++vertexCount;
1884  }
1885  }
1886  }
1887  return false;
1888 }
1889 
1891 {
1892  if ( !d->geometry )
1893  {
1894  return -1;
1895  }
1896 
1898 
1899  int vertexCount = 0;
1900  for ( int part = 0; part < coords.size(); ++part )
1901  {
1902  const QgsRingSequenceV2 &featureCoords = coords.at( part );
1903  for ( int ring = 0; ring < featureCoords.size(); ++ring )
1904  {
1905  const QgsPointSequenceV2 &ringCoords = featureCoords.at( ring );
1906  for ( int vertex = 0; vertex < ringCoords.size(); ++vertex )
1907  {
1908  if ( vertex == id.vertex && ring == id.ring && part == id.part )
1909  {
1910  return vertexCount;
1911  }
1912  ++vertexCount;
1913  }
1914  }
1915  }
1916  return -1;
1917 }
1918 
1920 {
1921  output.clear();
1923  for ( ; it != input.constEnd(); ++it )
1924  {
1925  output.append( QgsPointV2( it->x(), it->y() ) );
1926  }
1927 }
1928 
1930 {
1931  output.clear();
1933  for ( ; it != input.constEnd(); ++it )
1934  {
1935  output.append( QgsPoint( it->x(), it->y() ) );
1936  }
1937 }
1938 
1939 void QgsGeometry::convertToPolyline( const QgsPointSequenceV2 &input, QgsPolyline& output )
1940 {
1941  output.clear();
1942  output.resize( input.size() );
1943 
1944  for ( int i = 0; i < input.size(); ++i )
1945  {
1946  const QgsPointV2& pt = input.at( i );
1947  output[i].setX( pt.x() );
1948  output[i].setY( pt.y() );
1949  }
1950 }
1951 
1952 void QgsGeometry::convertPolygon( const QgsPolygonV2& input, QgsPolygon& output )
1953 {
1954  output.clear();
1956  if ( coords.size() < 1 )
1957  {
1958  return;
1959  }
1960  const QgsRingSequenceV2 &rings = coords[0];
1961  output.resize( rings.size() );
1962  for ( int i = 0; i < rings.size(); ++i )
1963  {
1964  convertToPolyline( rings[i], output[i] );
1965  }
1966 }
1967 
1968 GEOSContextHandle_t QgsGeometry::getGEOSHandler()
1969 {
1970  return QgsGeos::getGEOSHandler();
1971 }
1972 
1974 {
1975  return new QgsGeometry( new QgsPointV2( point.x(), point.y() ) );
1976 }
1977 
1979 {
1980  if ( polygon.isClosed() )
1981  {
1983  }
1984  else
1985  {
1987  }
1988 }
1989 
1991 {
1992  QgsPolygon result;
1993  result << createPolylineFromQPolygonF( polygon );
1994  return result;
1995 }
1996 
1998 {
1999  QgsPolyline result;
2000  QPolygonF::const_iterator it = polygon.constBegin();
2001  for ( ; it != polygon.constEnd(); ++it )
2002  {
2003  result.append( QgsPoint( *it ) );
2004  }
2005  return result;
2006 }
2007 
2008 bool QgsGeometry::compare( const QgsPolyline &p1, const QgsPolyline &p2, double epsilon )
2009 {
2010  if ( p1.count() != p2.count() )
2011  return false;
2012 
2013  for ( int i = 0; i < p1.count(); ++i )
2014  {
2015  if ( !p1.at( i ).compare( p2.at( i ), epsilon ) )
2016  return false;
2017  }
2018  return true;
2019 }
2020 
2021 bool QgsGeometry::compare( const QgsPolygon &p1, const QgsPolygon &p2, double epsilon )
2022 {
2023  if ( p1.count() != p2.count() )
2024  return false;
2025 
2026  for ( int i = 0; i < p1.count(); ++i )
2027  {
2028  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
2029  return false;
2030  }
2031  return true;
2032 }
2033 
2034 
2035 bool QgsGeometry::compare( const QgsMultiPolygon &p1, const QgsMultiPolygon &p2, double epsilon )
2036 {
2037  if ( p1.count() != p2.count() )
2038  return false;
2039 
2040  for ( int i = 0; i < p1.count(); ++i )
2041  {
2042  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
2043  return false;
2044  }
2045  return true;
2046 }
2047 
2048 QgsGeometry* QgsGeometry::smooth( const unsigned int iterations, const double offset ) const
2049 {
2050  switch ( wkbType() )
2051  {
2052  case QGis::WKBPoint:
2053  case QGis::WKBPoint25D:
2054  case QGis::WKBMultiPoint:
2056  //can't smooth a point based geometry
2057  return new QgsGeometry( *this );
2058 
2059  case QGis::WKBLineString:
2061  {
2062  QgsPolyline line = asPolyline();
2063  return QgsGeometry::fromPolyline( smoothLine( line, iterations, offset ) );
2064  }
2065 
2068  {
2069  QgsMultiPolyline multiline = asMultiPolyline();
2070  QgsMultiPolyline resultMultiline;
2071  QgsMultiPolyline::const_iterator lineIt = multiline.constBegin();
2072  for ( ; lineIt != multiline.constEnd(); ++lineIt )
2073  {
2074  resultMultiline << smoothLine( *lineIt, iterations, offset );
2075  }
2076  return QgsGeometry::fromMultiPolyline( resultMultiline );
2077  }
2078 
2079  case QGis::WKBPolygon:
2080  case QGis::WKBPolygon25D:
2081  {
2082  QgsPolygon poly = asPolygon();
2083  return QgsGeometry::fromPolygon( smoothPolygon( poly, iterations, offset ) );
2084  }
2085 
2086  case QGis::WKBMultiPolygon:
2088  {
2089  QgsMultiPolygon multipoly = asMultiPolygon();
2090  QgsMultiPolygon resultMultipoly;
2091  QgsMultiPolygon::const_iterator polyIt = multipoly.constBegin();
2092  for ( ; polyIt != multipoly.constEnd(); ++polyIt )
2093  {
2094  resultMultipoly << smoothPolygon( *polyIt, iterations, offset );
2095  }
2096  return QgsGeometry::fromMultiPolygon( resultMultipoly );
2097  }
2098 
2099  case QGis::WKBUnknown:
2100  default:
2101  return new QgsGeometry( *this );
2102  }
2103 }
2104 
2105 inline QgsPoint interpolatePointOnLine( const QgsPoint& p1, const QgsPoint& p2, const double offset )
2106 {
2107  double deltaX = p2.x() - p1.x();
2108  double deltaY = p2.y() - p1.y();
2109  return QgsPoint( p1.x() + deltaX * offset, p1.y() + deltaY * offset );
2110 }
2111 
2112 QgsPolyline QgsGeometry::smoothLine( const QgsPolyline& polyline, const unsigned int iterations, const double offset ) const
2113 {
2114  QgsPolyline result = polyline;
2115  for ( unsigned int iteration = 0; iteration < iterations; ++iteration )
2116  {
2117  QgsPolyline outputLine = QgsPolyline();
2118  outputLine.reserve( 2 * ( result.count() - 1 ) );
2119  for ( int i = 0; i < result.count() - 1; i++ )
2120  {
2121  const QgsPoint& p1 = result.at( i );
2122  const QgsPoint& p2 = result.at( i + 1 );
2123  outputLine << ( i == 0 ? result.at( i ) : interpolatePointOnLine( p1, p2, offset ) );
2124  outputLine << ( i == result.count() - 2 ? result.at( i + 1 ) : interpolatePointOnLine( p1, p2, 1.0 - offset ) );
2125  }
2126  result = outputLine;
2127  }
2128  return result;
2129 }
2130 
2131 QgsPolygon QgsGeometry::smoothPolygon( const QgsPolygon& polygon, const unsigned int iterations, const double offset ) const
2132 {
2133  QgsPolygon resultPoly;
2134  QgsPolygon::const_iterator ringIt = polygon.constBegin();
2135  for ( ; ringIt != polygon.constEnd(); ++ringIt )
2136  {
2137  QgsPolyline resultRing = *ringIt;
2138  for ( unsigned int iteration = 0; iteration < iterations; ++iteration )
2139  {
2140  QgsPolyline outputRing = QgsPolyline();
2141  outputRing.reserve( 2 * ( resultRing.count() - 1 ) + 1 );
2142  for ( int i = 0; i < resultRing.count() - 1; ++i )
2143  {
2144  const QgsPoint& p1 = resultRing.at( i );
2145  const QgsPoint& p2 = resultRing.at( i + 1 );
2146  outputRing << interpolatePointOnLine( p1, p2, offset );
2147  outputRing << interpolatePointOnLine( p1, p2, 1.0 - offset );
2148  }
2149  //close polygon
2150  outputRing << outputRing.at( 0 );
2151 
2152  resultRing = outputRing;
2153  }
2154  resultPoly << resultRing;
2155  }
2156  return resultPoly;
2157 }
2158 
2159 QgsGeometry* QgsGeometry::convertToPoint( bool destMultipart ) const
2160 {
2161  switch ( type() )
2162  {
2163  case QGis::Point:
2164  {
2165  bool srcIsMultipart = isMultipart();
2166 
2167  if (( destMultipart && srcIsMultipart ) ||
2168  ( !destMultipart && !srcIsMultipart ) )
2169  {
2170  // return a copy of the same geom
2171  return new QgsGeometry( *this );
2172  }
2173  if ( destMultipart )
2174  {
2175  // layer is multipart => make a multipoint with a single point
2176  return fromMultiPoint( QgsMultiPoint() << asPoint() );
2177  }
2178  else
2179  {
2180  // destination is singlepart => make a single part if possible
2181  QgsMultiPoint multiPoint = asMultiPoint();
2182  if ( multiPoint.count() == 1 )
2183  {
2184  return fromPoint( multiPoint[0] );
2185  }
2186  }
2187  return nullptr;
2188  }
2189 
2190  case QGis::Line:
2191  {
2192  // only possible if destination is multipart
2193  if ( !destMultipart )
2194  return nullptr;
2195 
2196  // input geometry is multipart
2197  if ( isMultipart() )
2198  {
2199  QgsMultiPolyline multiLine = asMultiPolyline();
2200  QgsMultiPoint multiPoint;
2201  for ( QgsMultiPolyline::const_iterator multiLineIt = multiLine.constBegin(); multiLineIt != multiLine.constEnd(); ++multiLineIt )
2202  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2203  multiPoint << *lineIt;
2204  return fromMultiPoint( multiPoint );
2205  }
2206  // input geometry is not multipart: copy directly the line into a multipoint
2207  else
2208  {
2209  QgsPolyline line = asPolyline();
2210  if ( !line.isEmpty() )
2211  return fromMultiPoint( line );
2212  }
2213  return nullptr;
2214  }
2215 
2216  case QGis::Polygon:
2217  {
2218  // can only transform if destination is multipoint
2219  if ( !destMultipart )
2220  return nullptr;
2221 
2222  // input geometry is multipart: make a multipoint from multipolygon
2223  if ( isMultipart() )
2224  {
2225  QgsMultiPolygon multiPolygon = asMultiPolygon();
2226  QgsMultiPoint multiPoint;
2227  for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
2228  for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
2229  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2230  multiPoint << *lineIt;
2231  return fromMultiPoint( multiPoint );
2232  }
2233  // input geometry is not multipart: make a multipoint from polygon
2234  else
2235  {
2236  QgsPolygon polygon = asPolygon();
2237  QgsMultiPoint multiPoint;
2238  for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
2239  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2240  multiPoint << *lineIt;
2241  return fromMultiPoint( multiPoint );
2242  }
2243  }
2244 
2245  default:
2246  return nullptr;
2247  }
2248 }
2249 
2250 QgsGeometry* QgsGeometry::convertToLine( bool destMultipart ) const
2251 {
2252  switch ( type() )
2253  {
2254  case QGis::Point:
2255  {
2256  if ( !isMultipart() )
2257  return nullptr;
2258 
2259  QgsMultiPoint multiPoint = asMultiPoint();
2260  if ( multiPoint.count() < 2 )
2261  return nullptr;
2262 
2263  if ( destMultipart )
2264  return fromMultiPolyline( QgsMultiPolyline() << multiPoint );
2265  else
2266  return fromPolyline( multiPoint );
2267  }
2268 
2269  case QGis::Line:
2270  {
2271  bool srcIsMultipart = isMultipart();
2272 
2273  if (( destMultipart && srcIsMultipart ) ||
2274  ( !destMultipart && ! srcIsMultipart ) )
2275  {
2276  // return a copy of the same geom
2277  return new QgsGeometry( *this );
2278  }
2279  if ( destMultipart )
2280  {
2281  // destination is multipart => makes a multipoint with a single line
2282  QgsPolyline line = asPolyline();
2283  if ( !line.isEmpty() )
2284  return fromMultiPolyline( QgsMultiPolyline() << line );
2285  }
2286  else
2287  {
2288  // destination is singlepart => make a single part if possible
2289  QgsMultiPolyline multiLine = asMultiPolyline();
2290  if ( multiLine.count() == 1 )
2291  return fromPolyline( multiLine[0] );
2292  }
2293  return nullptr;
2294  }
2295 
2296  case QGis::Polygon:
2297  {
2298  // input geometry is multipolygon
2299  if ( isMultipart() )
2300  {
2301  QgsMultiPolygon multiPolygon = asMultiPolygon();
2302  QgsMultiPolyline multiLine;
2303  for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
2304  for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
2305  multiLine << *multiLineIt;
2306 
2307  if ( destMultipart )
2308  {
2309  // destination is multipart
2310  return fromMultiPolyline( multiLine );
2311  }
2312  else if ( multiLine.count() == 1 )
2313  {
2314  // destination is singlepart => make a single part if possible
2315  return fromPolyline( multiLine[0] );
2316  }
2317  }
2318  // input geometry is single polygon
2319  else
2320  {
2321  QgsPolygon polygon = asPolygon();
2322  // if polygon has rings
2323  if ( polygon.count() > 1 )
2324  {
2325  // cannot fit a polygon with rings in a single line layer
2326  // TODO: would it be better to remove rings?
2327  if ( destMultipart )
2328  {
2329  QgsPolygon polygon = asPolygon();
2330  QgsMultiPolyline multiLine;
2331  for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
2332  multiLine << *multiLineIt;
2333  return fromMultiPolyline( multiLine );
2334  }
2335  }
2336  // no rings
2337  else if ( polygon.count() == 1 )
2338  {
2339  if ( destMultipart )
2340  {
2341  return fromMultiPolyline( polygon );
2342  }
2343  else
2344  {
2345  return fromPolyline( polygon[0] );
2346  }
2347  }
2348  }
2349  return nullptr;
2350  }
2351 
2352  default:
2353  return nullptr;
2354  }
2355 }
2356 
2357 QgsGeometry* QgsGeometry::convertToPolygon( bool destMultipart ) const
2358 {
2359  switch ( type() )
2360  {
2361  case QGis::Point:
2362  {
2363  if ( !isMultipart() )
2364  return nullptr;
2365 
2366  QgsMultiPoint multiPoint = asMultiPoint();
2367  if ( multiPoint.count() < 3 )
2368  return nullptr;
2369 
2370  if ( multiPoint.last() != multiPoint.first() )
2371  multiPoint << multiPoint.first();
2372 
2373  QgsPolygon polygon = QgsPolygon() << multiPoint;
2374  if ( destMultipart )
2375  return fromMultiPolygon( QgsMultiPolygon() << polygon );
2376  else
2377  return fromPolygon( polygon );
2378  }
2379 
2380  case QGis::Line:
2381  {
2382  // input geometry is multiline
2383  if ( isMultipart() )
2384  {
2385  QgsMultiPolyline multiLine = asMultiPolyline();
2386  QgsMultiPolygon multiPolygon;
2387  for ( QgsMultiPolyline::iterator multiLineIt = multiLine.begin(); multiLineIt != multiLine.end(); ++multiLineIt )
2388  {
2389  // do not create polygon for a 1 segment line
2390  if (( *multiLineIt ).count() < 3 )
2391  return nullptr;
2392  if (( *multiLineIt ).count() == 3 && ( *multiLineIt ).first() == ( *multiLineIt ).last() )
2393  return nullptr;
2394 
2395  // add closing node
2396  if (( *multiLineIt ).first() != ( *multiLineIt ).last() )
2397  *multiLineIt << ( *multiLineIt ).first();
2398  multiPolygon << ( QgsPolygon() << *multiLineIt );
2399  }
2400  // check that polygons were inserted
2401  if ( !multiPolygon.isEmpty() )
2402  {
2403  if ( destMultipart )
2404  {
2405  return fromMultiPolygon( multiPolygon );
2406  }
2407  else if ( multiPolygon.count() == 1 )
2408  {
2409  // destination is singlepart => make a single part if possible
2410  return fromPolygon( multiPolygon[0] );
2411  }
2412  }
2413  }
2414  // input geometry is single line
2415  else
2416  {
2417  QgsPolyline line = asPolyline();
2418 
2419  // do not create polygon for a 1 segment line
2420  if ( line.count() < 3 )
2421  return nullptr;
2422  if ( line.count() == 3 && line.first() == line.last() )
2423  return nullptr;
2424 
2425  // add closing node
2426  if ( line.first() != line.last() )
2427  line << line.first();
2428 
2429  // destination is multipart
2430  if ( destMultipart )
2431  {
2432  return fromMultiPolygon( QgsMultiPolygon() << ( QgsPolygon() << line ) );
2433  }
2434  else
2435  {
2436  return fromPolygon( QgsPolygon() << line );
2437  }
2438  }
2439  return nullptr;
2440  }
2441 
2442  case QGis::Polygon:
2443  {
2444  bool srcIsMultipart = isMultipart();
2445 
2446  if (( destMultipart && srcIsMultipart ) ||
2447  ( !destMultipart && ! srcIsMultipart ) )
2448  {
2449  // return a copy of the same geom
2450  return new QgsGeometry( *this );
2451  }
2452  if ( destMultipart )
2453  {
2454  // destination is multipart => makes a multipoint with a single polygon
2455  QgsPolygon polygon = asPolygon();
2456  if ( !polygon.isEmpty() )
2457  return fromMultiPolygon( QgsMultiPolygon() << polygon );
2458  }
2459  else
2460  {
2461  QgsMultiPolygon multiPolygon = asMultiPolygon();
2462  if ( multiPolygon.count() == 1 )
2463  {
2464  // destination is singlepart => make a single part if possible
2465  return fromPolygon( multiPolygon[0] );
2466  }
2467  }
2468  return nullptr;
2469  }
2470 
2471  default:
2472  return nullptr;
2473  }
2474 }
2475 
2477 {
2478  return new QgsGeos( geometry );
2479 }
2480 
2482 {
2483  QByteArray byteArray = QByteArray::fromRawData( reinterpret_cast< const char * >( geometry.asWkb() ), geometry.wkbSize() ); // does not copy data and does not take ownership
2484  out << byteArray;
2485  return out;
2486 }
2487 
2489 {
2490  QByteArray byteArray;
2491  in >> byteArray;
2492  if ( byteArray.isEmpty() )
2493  {
2494  geometry.setGeometry( nullptr );
2495  return in;
2496  }
2497 
2498  char *data = new char[byteArray.size()];
2499  memcpy( data, byteArray.data(), byteArray.size() );
2500  geometry.fromWkb( reinterpret_cast< unsigned char* >( data ), byteArray.size() );
2501  return in;
2502 }
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:1798
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:1468
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:1852
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:1434
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:1316
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:1817
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:2416
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:1690
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:1346
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:1448
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:1388
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:1674
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:1417
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:1278
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.