QGIS API Documentation  2.18.3-Las Palmas (77b8c3d)
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  if ( !d->geometry )
805  {
806  return 0;
807  }
808 
809  QgsPointSequenceV2 reshapeLine;
810  convertPointList( reshapeWithLine, reshapeLine );
811  QgsLineStringV2 reshapeLineString;
812  reshapeLineString.setPoints( reshapeLine );
813 
814  QgsGeos geos( d->geometry );
815  int errorCode = 0;
816  QgsAbstractGeometryV2* geom = geos.reshapeGeometry( reshapeLineString, &errorCode );
817  if ( errorCode == 0 && geom )
818  {
819  detach( false );
820  delete d->geometry;
821  d->geometry = geom;
822  removeWkbGeos();
823  return 0;
824  }
825  return errorCode;
826 }
827 
829 {
830  if ( !d->geometry || !other->d->geometry )
831  {
832  return 0;
833  }
834 
835  QgsGeos geos( d->geometry );
836 
837  QgsAbstractGeometryV2* diffGeom = geos.intersection( *( other->geometry() ) );
838  if ( !diffGeom )
839  {
840  return 1;
841  }
842 
843  detach( false );
844 
845  delete d->geometry;
846  d->geometry = diffGeom;
847  removeWkbGeos();
848  return 0;
849 }
850 
852 {
853  if ( d->geometry )
854  {
855  return d->geometry->boundingBox();
856  }
857  return QgsRectangle();
858 }
859 
860 bool QgsGeometry::intersects( const QgsRectangle& r ) const
861 {
862  QgsGeometry* g = fromRect( r );
863  bool res = intersects( g );
864  delete g;
865  return res;
866 }
867 
869 {
870  if ( !d->geometry || !geometry || !geometry->d->geometry )
871  {
872  return false;
873  }
874 
875  QgsGeos geos( d->geometry );
876  return geos.intersects( *( geometry->d->geometry ) );
877 }
878 
879 bool QgsGeometry::contains( const QgsPoint* p ) const
880 {
881  if ( !d->geometry || !p )
882  {
883  return false;
884  }
885 
886  QgsPointV2 pt( p->x(), p->y() );
887  QgsGeos geos( d->geometry );
888  return geos.contains( pt );
889 }
890 
892 {
893  if ( !d->geometry || !geometry || !geometry->d->geometry )
894  {
895  return false;
896  }
897 
898  QgsGeos geos( d->geometry );
899  return geos.contains( *( geometry->d->geometry ) );
900 }
901 
903 {
904  if ( !d->geometry || !geometry || !geometry->d->geometry )
905  {
906  return false;
907  }
908 
909  QgsGeos geos( d->geometry );
910  return geos.disjoint( *( geometry->d->geometry ) );
911 }
912 
914 {
915  if ( !d->geometry || !geometry || !geometry->d->geometry )
916  {
917  return false;
918  }
919 
920  QgsGeos geos( d->geometry );
921  return geos.isEqual( *( geometry->d->geometry ) );
922 }
923 
925 {
926  if ( !d->geometry || !geometry || !geometry->d->geometry )
927  {
928  return false;
929  }
930 
931  QgsGeos geos( d->geometry );
932  return geos.touches( *( geometry->d->geometry ) );
933 }
934 
936 {
937  if ( !d->geometry || !geometry || !geometry->d->geometry )
938  {
939  return false;
940  }
941 
942  QgsGeos geos( d->geometry );
943  return geos.overlaps( *( geometry->d->geometry ) );
944 }
945 
947 {
948  if ( !d->geometry || !geometry || !geometry->d->geometry )
949  {
950  return false;
951  }
952 
953  QgsGeos geos( d->geometry );
954  return geos.within( *( geometry->d->geometry ) );
955 }
956 
958 {
959  if ( !d->geometry || !geometry || !geometry->d->geometry )
960  {
961  return false;
962  }
963 
964  QgsGeos geos( d->geometry );
965  return geos.crosses( *( geometry->d->geometry ) );
966 }
967 
968 QString QgsGeometry::exportToWkt( int precision ) const
969 {
970  if ( !d->geometry )
971  {
972  return QString();
973  }
974  return d->geometry->asWkt( precision );
975 }
976 
977 QString QgsGeometry::exportToGeoJSON( int precision ) const
978 {
979  if ( !d->geometry )
980  {
981  return QString( "null" );
982  }
983  return d->geometry->asJSON( precision );
984 }
985 
986 QgsGeometry* QgsGeometry::convertToType( QGis::GeometryType destType, bool destMultipart ) const
987 {
988  switch ( destType )
989  {
990  case QGis::Point:
991  return convertToPoint( destMultipart );
992 
993  case QGis::Line:
994  return convertToLine( destMultipart );
995 
996  case QGis::Polygon:
997  return convertToPolygon( destMultipart );
998 
999  default:
1000  return nullptr;
1001  }
1002 }
1003 
1005 {
1006  if ( !d->geometry )
1007  {
1008  return false;
1009  }
1010 
1011  if ( isMultipart() ) //already multitype, no need to convert
1012  {
1013  return true;
1014  }
1015 
1016  QgsGeometryCollectionV2* multiGeom = dynamic_cast<QgsGeometryCollectionV2*>
1018  if ( !multiGeom )
1019  {
1020  return false;
1021  }
1022 
1023  detach( true );
1024  multiGeom->addGeometry( d->geometry );
1025  d->geometry = multiGeom;
1026  removeWkbGeos();
1027  return true;
1028 }
1029 
1031 {
1032  if ( !d->geometry )
1033  {
1034  return false;
1035  }
1036 
1037  if ( !isMultipart() ) //already single part, no need to convert
1038  {
1039  return true;
1040  }
1041 
1042  QgsGeometryCollectionV2* multiGeom = dynamic_cast<QgsGeometryCollectionV2*>( d->geometry );
1043  if ( !multiGeom || multiGeom->partCount() < 1 )
1044  return false;
1045 
1046  QgsAbstractGeometryV2* firstPart = multiGeom->geometryN( 0 )->clone();
1047  detach( false );
1048 
1049  d->geometry = firstPart;
1050  removeWkbGeos();
1051  return true;
1052 }
1053 
1055 {
1057  {
1058  return QgsPoint();
1059  }
1060  QgsPointV2* pt = dynamic_cast<QgsPointV2*>( d->geometry );
1061  if ( !pt )
1062  {
1063  return QgsPoint();
1064  }
1065 
1066  return QgsPoint( pt->x(), pt->y() );
1067 }
1068 
1070 {
1071  QgsPolyline polyLine;
1072  if ( !d->geometry )
1073  {
1074  return polyLine;
1075  }
1076 
1077  bool doSegmentation = ( QgsWKBTypes::flatType( d->geometry->wkbType() ) == QgsWKBTypes::CompoundCurve
1079  QgsLineStringV2* line = nullptr;
1080  if ( doSegmentation )
1081  {
1082  QgsCurveV2* curve = dynamic_cast<QgsCurveV2*>( d->geometry );
1083  if ( !curve )
1084  {
1085  return polyLine;
1086  }
1087  line = curve->curveToLine();
1088  }
1089  else
1090  {
1091  line = dynamic_cast<QgsLineStringV2*>( d->geometry );
1092  if ( !line )
1093  {
1094  return polyLine;
1095  }
1096  }
1097 
1098  int nVertices = line->numPoints();
1099  polyLine.resize( nVertices );
1100  for ( int i = 0; i < nVertices; ++i )
1101  {
1102  QgsPointV2 pt = line->pointN( i );
1103  polyLine[i].setX( pt.x() );
1104  polyLine[i].setY( pt.y() );
1105  }
1106 
1107  if ( doSegmentation )
1108  {
1109  delete line;
1110  }
1111 
1112  return polyLine;
1113 }
1114 
1116 {
1117  if ( !d->geometry )
1118  return QgsPolygon();
1119 
1120  bool doSegmentation = ( QgsWKBTypes::flatType( d->geometry->wkbType() ) == QgsWKBTypes::CurvePolygon );
1121 
1122  QgsPolygonV2* p = nullptr;
1123  if ( doSegmentation )
1124  {
1125  QgsCurvePolygonV2* curvePoly = dynamic_cast<QgsCurvePolygonV2*>( d->geometry );
1126  if ( !curvePoly )
1127  {
1128  return QgsPolygon();
1129  }
1130  p = curvePoly->toPolygon();
1131  }
1132  else
1133  {
1134  p = dynamic_cast<QgsPolygonV2*>( d->geometry );
1135  }
1136 
1137  if ( !p )
1138  {
1139  return QgsPolygon();
1140  }
1141 
1142  QgsPolygon polygon;
1143  convertPolygon( *p, polygon );
1144 
1145  if ( doSegmentation )
1146  {
1147  delete p;
1148  }
1149  return polygon;
1150 }
1151 
1153 {
1155  {
1156  return QgsMultiPoint();
1157  }
1158 
1159  const QgsMultiPointV2* mp = dynamic_cast<QgsMultiPointV2*>( d->geometry );
1160  if ( !mp )
1161  {
1162  return QgsMultiPoint();
1163  }
1164 
1165  int nPoints = mp->numGeometries();
1166  QgsMultiPoint multiPoint( nPoints );
1167  for ( int i = 0; i < nPoints; ++i )
1168  {
1169  const QgsPointV2* pt = static_cast<const QgsPointV2*>( mp->geometryN( i ) );
1170  multiPoint[i].setX( pt->x() );
1171  multiPoint[i].setY( pt->y() );
1172  }
1173  return multiPoint;
1174 }
1175 
1177 {
1178  if ( !d->geometry )
1179  {
1180  return QgsMultiPolyline();
1181  }
1182 
1183  QgsGeometryCollectionV2* geomCollection = dynamic_cast<QgsGeometryCollectionV2*>( d->geometry );
1184  if ( !geomCollection )
1185  {
1186  return QgsMultiPolyline();
1187  }
1188 
1189  int nLines = geomCollection->numGeometries();
1190  if ( nLines < 1 )
1191  {
1192  return QgsMultiPolyline();
1193  }
1194 
1195  QgsMultiPolyline mpl;
1196  for ( int i = 0; i < nLines; ++i )
1197  {
1198  bool deleteLine = false;
1199  const QgsLineStringV2* line = dynamic_cast<const QgsLineStringV2*>( geomCollection->geometryN( i ) );
1200  if ( !line )
1201  {
1202  const QgsCurveV2* curve = dynamic_cast<const QgsCurveV2*>( geomCollection->geometryN( i ) );
1203  if ( !curve )
1204  {
1205  continue;
1206  }
1207  deleteLine = true;
1208  line = curve->curveToLine();
1209  }
1210 
1211  QgsPointSequenceV2 lineCoords;
1212  line->points( lineCoords );
1213  QgsPolyline polyLine;
1214  convertToPolyline( lineCoords, polyLine );
1215  mpl.append( polyLine );
1216 
1217  if ( deleteLine )
1218  {
1219  delete line;
1220  }
1221  }
1222  return mpl;
1223 }
1224 
1226 {
1227  if ( !d->geometry )
1228  {
1229  return QgsMultiPolygon();
1230  }
1231 
1232  QgsGeometryCollectionV2* geomCollection = dynamic_cast<QgsGeometryCollectionV2*>( d->geometry );
1233  if ( !geomCollection )
1234  {
1235  return QgsMultiPolygon();
1236  }
1237 
1238  int nPolygons = geomCollection->numGeometries();
1239  if ( nPolygons < 1 )
1240  {
1241  return QgsMultiPolygon();
1242  }
1243 
1244  QgsMultiPolygon mp;
1245  for ( int i = 0; i < nPolygons; ++i )
1246  {
1247  const QgsPolygonV2* polygon = dynamic_cast<const QgsPolygonV2*>( geomCollection->geometryN( i ) );
1248  if ( !polygon )
1249  {
1250  const QgsCurvePolygonV2* cPolygon = dynamic_cast<const QgsCurvePolygonV2*>( geomCollection->geometryN( i ) );
1251  if ( cPolygon )
1252  {
1253  polygon = cPolygon->toPolygon();
1254  }
1255  else
1256  {
1257  continue;
1258  }
1259  }
1260 
1261  QgsPolygon poly;
1262  convertPolygon( *polygon, poly );
1263  mp.append( poly );
1264  }
1265  return mp;
1266 }
1267 
1268 double QgsGeometry::area() const
1269 {
1270  if ( !d->geometry )
1271  {
1272  return -1.0;
1273  }
1274  QgsGeos g( d->geometry );
1275 
1276 #if 0
1277  //debug: compare geos area with calculation in QGIS
1278  double geosArea = g.area();
1279  double qgisArea = 0;
1280  QgsSurfaceV2* surface = dynamic_cast<QgsSurfaceV2*>( d->geometry );
1281  if ( surface )
1282  {
1283  qgisArea = surface->area();
1284  }
1285 #endif
1286 
1287  return g.area();
1288 }
1289 
1290 double QgsGeometry::length() const
1291 {
1292  if ( !d->geometry )
1293  {
1294  return -1.0;
1295  }
1296  QgsGeos g( d->geometry );
1297  return g.length();
1298 }
1299 
1300 double QgsGeometry::distance( const QgsGeometry& geom ) const
1301 {
1302  if ( !d->geometry || !geom.d->geometry )
1303  {
1304  return -1.0;
1305  }
1306 
1307  QgsGeos g( d->geometry );
1308  return g.distance( *( geom.d->geometry ) );
1309 }
1310 
1311 QgsGeometry* QgsGeometry::buffer( double distance, int segments ) const
1312 {
1313  if ( !d->geometry )
1314  {
1315  return nullptr;
1316  }
1317 
1318  QgsGeos g( d->geometry );
1319  QgsAbstractGeometryV2* geom = g.buffer( distance, segments );
1320  if ( !geom )
1321  {
1322  return nullptr;
1323  }
1324  return new QgsGeometry( geom );
1325 }
1326 
1327 QgsGeometry* QgsGeometry::buffer( double distance, int segments, int endCapStyle, int joinStyle, double mitreLimit ) const
1328 {
1329  if ( !d->geometry )
1330  {
1331  return nullptr;
1332  }
1333 
1334  QgsGeos g( d->geometry );
1335  QgsAbstractGeometryV2* geom = g.buffer( distance, segments, endCapStyle, joinStyle, mitreLimit );
1336  if ( !geom )
1337  {
1338  return nullptr;
1339  }
1340  return new QgsGeometry( geom );
1341 }
1342 
1343 QgsGeometry* QgsGeometry::offsetCurve( double distance, int segments, int joinStyle, double mitreLimit ) const
1344 {
1345  if ( !d->geometry )
1346  {
1347  return nullptr;
1348  }
1349 
1350  QgsGeos geos( d->geometry );
1351  QgsAbstractGeometryV2* offsetGeom = geos.offsetCurve( distance, segments, joinStyle, mitreLimit );
1352  if ( !offsetGeom )
1353  {
1354  return nullptr;
1355  }
1356  return new QgsGeometry( offsetGeom );
1357 }
1358 
1359 QgsGeometry* QgsGeometry::simplify( double tolerance ) const
1360 {
1361  if ( !d->geometry )
1362  {
1363  return nullptr;
1364  }
1365 
1366  QgsGeos geos( d->geometry );
1367  QgsAbstractGeometryV2* simplifiedGeom = geos.simplify( tolerance );
1368  if ( !simplifiedGeom )
1369  {
1370  return nullptr;
1371  }
1372  return new QgsGeometry( simplifiedGeom );
1373 }
1374 
1376 {
1377  if ( !d->geometry )
1378  {
1379  return nullptr;
1380  }
1381 
1382  QgsGeos geos( d->geometry );
1384  bool ok = geos.centroid( centroid );
1385  if ( !ok )
1386  {
1387  return nullptr;
1388  }
1389  return new QgsGeometry( centroid.clone() );
1390 }
1391 
1393 {
1394  if ( !d->geometry )
1395  {
1396  return nullptr;
1397  }
1398 
1399  QgsGeos geos( d->geometry );
1400  QgsPointV2 pt;
1401  bool ok = geos.pointOnSurface( pt );
1402  if ( !ok )
1403  {
1404  return nullptr;
1405  }
1406  return new QgsGeometry( pt.clone() );
1407 }
1408 
1410 {
1411  if ( !d->geometry )
1412  {
1413  return nullptr;
1414  }
1415  QgsGeos geos( d->geometry );
1416  QgsAbstractGeometryV2* cHull = geos.convexHull();
1417  if ( !cHull )
1418  {
1419  return nullptr;
1420  }
1421  return new QgsGeometry( cHull );
1422 }
1423 
1425 {
1426  if ( !d->geometry )
1427  {
1428  return nullptr;
1429  }
1430 
1431  QgsGeometry line = *this;
1432  if ( type() == QGis::Polygon )
1433  line = QgsGeometry( d->geometry->boundary() );
1434 
1435  QgsGeos geos( line.geometry() );
1436  QgsAbstractGeometryV2* result = geos.interpolate( distance );
1437  if ( !result )
1438  {
1439  return nullptr;
1440  }
1441  return new QgsGeometry( result );
1442 }
1443 
1444 double QgsGeometry::lineLocatePoint( const QgsGeometry& point ) const
1445 {
1446  if ( type() != QGis::Line )
1447  return -1;
1448 
1449  if ( QgsWKBTypes::flatType( point.d->geometry->wkbType() ) != QgsWKBTypes::Point )
1450  return -1;
1451 
1452  QgsGeometry segmentized = *this;
1454  {
1455  segmentized = QgsGeometry( static_cast< QgsCurveV2* >( d->geometry )->segmentize() );
1456  }
1457 
1458  QgsGeos geos( d->geometry );
1459  return geos.lineLocatePoint( *( static_cast< QgsPointV2* >( point.d->geometry ) ) );
1460 }
1461 
1463 {
1464  if ( !d->geometry )
1465  return 0.0;
1466 
1467  // always operate on segmentized geometries
1468  QgsGeometry segmentized = *this;
1470  {
1471  segmentized = QgsGeometry( static_cast< QgsCurveV2* >( d->geometry )->segmentize() );
1472  }
1473 
1474  QgsVertexId previous;
1475  QgsVertexId next;
1476  if ( !QgsGeometryUtils::verticesAtDistance( *segmentized.geometry(), distance, previous, next ) )
1477  return 0.0;
1478 
1479  if ( previous == next )
1480  {
1481  // distance coincided exactly with a vertex
1482  QgsVertexId v2 = previous;
1483  QgsVertexId v1;
1484  QgsVertexId v3;
1485  QgsGeometryUtils::adjacentVertices( *segmentized.geometry(), v2, v1, v3 );
1486  if ( v1.isValid() && v3.isValid() )
1487  {
1488  QgsPointV2 p1 = segmentized.geometry()->vertexAt( v1 );
1489  QgsPointV2 p2 = segmentized.geometry()->vertexAt( v2 );
1490  QgsPointV2 p3 = segmentized.geometry()->vertexAt( v3 );
1491  double angle1 = QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1492  double angle2 = QgsGeometryUtils::lineAngle( p2.x(), p2.y(), p3.x(), p3.y() );
1493  return QgsGeometryUtils::averageAngle( angle1, angle2 );
1494  }
1495  else if ( v3.isValid() )
1496  {
1497  QgsPointV2 p1 = segmentized.geometry()->vertexAt( v2 );
1498  QgsPointV2 p2 = segmentized.geometry()->vertexAt( v3 );
1499  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1500  }
1501  else
1502  {
1503  QgsPointV2 p1 = segmentized.geometry()->vertexAt( v1 );
1504  QgsPointV2 p2 = segmentized.geometry()->vertexAt( v2 );
1505  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1506  }
1507  }
1508  else
1509  {
1510  QgsPointV2 p1 = segmentized.geometry()->vertexAt( previous );
1511  QgsPointV2 p2 = segmentized.geometry()->vertexAt( next );
1512  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
1513  }
1514 }
1515 
1516 
1518 {
1519  if ( !d->geometry || !geometry->d->geometry )
1520  {
1521  return nullptr;
1522  }
1523 
1524  QgsGeos geos( d->geometry );
1525 
1526  QgsAbstractGeometryV2* resultGeom = geos.intersection( *( geometry->d->geometry ) );
1527  return new QgsGeometry( resultGeom );
1528 }
1529 
1531 {
1532  if ( !d->geometry || !geometry->d->geometry )
1533  {
1534  return nullptr;
1535  }
1536 
1537  QgsGeos geos( d->geometry );
1538 
1539  QgsAbstractGeometryV2* resultGeom = geos.combine( *( geometry->d->geometry ) );
1540  if ( !resultGeom )
1541  {
1542  return nullptr;
1543  }
1544  return new QgsGeometry( resultGeom );
1545 }
1546 
1548 {
1549  if ( !d->geometry )
1550  {
1551  return QgsGeometry();
1552  }
1553 
1555  {
1556  // special case - a single linestring was passed
1557  return QgsGeometry( *this );
1558  }
1559 
1560  QgsGeos geos( d->geometry );
1561  return geos.mergeLines();
1562 }
1563 
1565 {
1566  if ( !d->geometry || !geometry->d->geometry )
1567  {
1568  return nullptr;
1569  }
1570 
1571  QgsGeos geos( d->geometry );
1572 
1573  QgsAbstractGeometryV2* resultGeom = geos.difference( *( geometry->d->geometry ) );
1574  if ( !resultGeom )
1575  {
1576  return nullptr;
1577  }
1578  return new QgsGeometry( resultGeom );
1579 }
1580 
1582 {
1583  if ( !d->geometry || !geometry->d->geometry )
1584  {
1585  return nullptr;
1586  }
1587 
1588  QgsGeos geos( d->geometry );
1589 
1590  QgsAbstractGeometryV2* resultGeom = geos.symDifference( *( geometry->d->geometry ) );
1591  if ( !resultGeom )
1592  {
1593  return nullptr;
1594  }
1595  return new QgsGeometry( resultGeom );
1596 }
1597 
1598 QgsGeometry QgsGeometry::extrude( double x, double y )
1599 {
1600  QgsInternalGeometryEngine engine( *this );
1601 
1602  return engine.extrude( x, y );
1603 }
1604 
1606 {
1607  QList<QgsGeometry*> geometryList;
1608  if ( !d->geometry )
1609  {
1610  return geometryList;
1611  }
1612 
1613  QgsGeometryCollectionV2* gc = dynamic_cast<QgsGeometryCollectionV2*>( d->geometry );
1614  if ( gc )
1615  {
1616  int numGeom = gc->numGeometries();
1617  geometryList.reserve( numGeom );
1618  for ( int i = 0; i < numGeom; ++i )
1619  {
1620  geometryList.append( new QgsGeometry( gc->geometryN( i )->clone() ) );
1621  }
1622  }
1623  else //a singlepart geometry
1624  {
1625  geometryList.append( new QgsGeometry( d->geometry->clone() ) );
1626  }
1627 
1628  return geometryList;
1629 }
1630 
1632 {
1633  QgsPoint point = asPoint();
1634  return point.toQPointF();
1635 }
1636 
1638 {
1639  QPolygonF result;
1640  QgsPolyline polyline;
1642  if ( type == QGis::WKBLineString || type == QGis::WKBLineString25D )
1643  {
1644  polyline = asPolyline();
1645  }
1646  else if ( type == QGis::WKBPolygon || type == QGis::WKBPolygon25D )
1647  {
1648  QgsPolygon polygon = asPolygon();
1649  if ( polygon.size() < 1 )
1650  return result;
1651  polyline = polygon.at( 0 );
1652  }
1653  else
1654  {
1655  return result;
1656  }
1657 
1658  QgsPolyline::const_iterator lineIt = polyline.constBegin();
1659  for ( ; lineIt != polyline.constEnd(); ++lineIt )
1660  {
1661  result << lineIt->toQPointF();
1662  }
1663  return result;
1664 }
1665 
1666 bool QgsGeometry::deleteRing( int ringNum, int partNum )
1667 {
1668  if ( !d->geometry )
1669  {
1670  return false;
1671  }
1672 
1673  detach( true );
1674  bool ok = QgsGeometryEditUtils::deleteRing( d->geometry, ringNum, partNum );
1675  removeWkbGeos();
1676  return ok;
1677 }
1678 
1679 bool QgsGeometry::deletePart( int partNum )
1680 {
1681  if ( !d->geometry )
1682  {
1683  return false;
1684  }
1685 
1686  if ( !isMultipart() && partNum < 1 )
1687  {
1688  setGeometry( nullptr );
1689  return true;
1690  }
1691 
1692  detach( true );
1693  bool ok = QgsGeometryEditUtils::deletePart( d->geometry, partNum );
1694  removeWkbGeos();
1695  return ok;
1696 }
1697 
1699 {
1700  if ( !d->geometry )
1701  {
1702  return 1;
1703  }
1704 
1705  QgsAbstractGeometryV2* diffGeom = QgsGeometryEditUtils::avoidIntersections( *( d->geometry ), ignoreFeatures );
1706  if ( diffGeom )
1707  {
1708  detach( false );
1709  d->geometry = diffGeom;
1710  removeWkbGeos();
1711  }
1712  return 0;
1713 }
1714 
1716 {
1718 }
1719 
1721 {
1722  if ( !d->geometry )
1723  {
1724  return false;
1725  }
1726 
1727  QgsGeos geos( d->geometry );
1728  return geos.isValid();
1729 }
1730 
1732 {
1733  if ( !d->geometry || !g.d->geometry )
1734  {
1735  return false;
1736  }
1737 
1738  QgsGeos geos( d->geometry );
1739  return geos.isEqual( *( g.d->geometry ) );
1740 }
1741 
1743 {
1744  if ( !d->geometry )
1745  {
1746  return false;
1747  }
1748 
1749  QgsGeos geos( d->geometry );
1750  return geos.isEmpty();
1751 }
1752 
1754 {
1755  QgsGeos geos( nullptr );
1756 
1757  QList<QgsAbstractGeometryV2*> geomV2List;
1758  QList<QgsGeometry*>::const_iterator it = geometryList.constBegin();
1759  for ( ; it != geometryList.constEnd(); ++it )
1760  {
1761  if ( *it && !(( *it )->isEmpty() ) )
1762  {
1763  geomV2List.append(( *it )->geometry() );
1764  }
1765  }
1766 
1767  QgsAbstractGeometryV2* geom = geos.combine( geomV2List );
1768  return new QgsGeometry( geom );
1769 }
1770 
1772 {
1774  {
1775  return;
1776  }
1777 
1778  QgsAbstractGeometryV2* straightGeom = d->geometry->segmentize();
1779  detach( false );
1780 
1781  d->geometry = straightGeom;
1782  removeWkbGeos();
1783 }
1784 
1786 {
1787  if ( !d->geometry )
1788  {
1789  return false;
1790  }
1791 
1792  return d->geometry->hasCurvedSegments();
1793 }
1794 
1796 {
1797  if ( !d->geometry )
1798  {
1799  return 1;
1800  }
1801 
1802  detach();
1803  d->geometry->transform( ct );
1804  removeWkbGeos();
1805  return 0;
1806 }
1807 
1809 {
1810  if ( !d->geometry )
1811  {
1812  return 1;
1813  }
1814 
1815  detach();
1816  d->geometry->transform( ct );
1817  removeWkbGeos();
1818  return 0;
1819 }
1820 
1822 {
1823  if ( d->geometry )
1824  {
1825  detach();
1826  d->geometry->transform( mtp.transform() );
1827  removeWkbGeos();
1828  }
1829 }
1830 
1831 #if 0
1832 void QgsGeometry::clip( const QgsRectangle& rect )
1833 {
1834  if ( d->geometry )
1835  {
1836  detach();
1837  d->geometry->clip( rect );
1838  removeWkbGeos();
1839  }
1840 }
1841 #endif
1842 
1843 void QgsGeometry::draw( QPainter& p ) const
1844 {
1845  if ( d->geometry )
1846  {
1847  d->geometry->draw( p );
1848  }
1849 }
1850 
1852 {
1853  if ( !d->geometry )
1854  {
1855  return false;
1856  }
1857 
1859 
1860  int vertexCount = 0;
1861  for ( int part = 0; part < coords.size(); ++part )
1862  {
1863  const QgsRingSequenceV2 &featureCoords = coords.at( part );
1864  for ( int ring = 0; ring < featureCoords.size(); ++ring )
1865  {
1866  const QgsPointSequenceV2 &ringCoords = featureCoords.at( ring );
1867  for ( int vertex = 0; vertex < ringCoords.size(); ++vertex )
1868  {
1869  if ( vertexCount == nr )
1870  {
1871  id.part = part;
1872  id.ring = ring;
1873  id.vertex = vertex;
1874  return true;
1875  }
1876  ++vertexCount;
1877  }
1878  }
1879  }
1880  return false;
1881 }
1882 
1884 {
1885  if ( !d->geometry )
1886  {
1887  return -1;
1888  }
1889 
1891 
1892  int vertexCount = 0;
1893  for ( int part = 0; part < coords.size(); ++part )
1894  {
1895  const QgsRingSequenceV2 &featureCoords = coords.at( part );
1896  for ( int ring = 0; ring < featureCoords.size(); ++ring )
1897  {
1898  const QgsPointSequenceV2 &ringCoords = featureCoords.at( ring );
1899  for ( int vertex = 0; vertex < ringCoords.size(); ++vertex )
1900  {
1901  if ( vertex == id.vertex && ring == id.ring && part == id.part )
1902  {
1903  return vertexCount;
1904  }
1905  ++vertexCount;
1906  }
1907  }
1908  }
1909  return -1;
1910 }
1911 
1913 {
1914  output.clear();
1916  for ( ; it != input.constEnd(); ++it )
1917  {
1918  output.append( QgsPointV2( it->x(), it->y() ) );
1919  }
1920 }
1921 
1923 {
1924  output.clear();
1926  for ( ; it != input.constEnd(); ++it )
1927  {
1928  output.append( QgsPoint( it->x(), it->y() ) );
1929  }
1930 }
1931 
1932 void QgsGeometry::convertToPolyline( const QgsPointSequenceV2 &input, QgsPolyline& output )
1933 {
1934  output.clear();
1935  output.resize( input.size() );
1936 
1937  for ( int i = 0; i < input.size(); ++i )
1938  {
1939  const QgsPointV2& pt = input.at( i );
1940  output[i].setX( pt.x() );
1941  output[i].setY( pt.y() );
1942  }
1943 }
1944 
1945 void QgsGeometry::convertPolygon( const QgsPolygonV2& input, QgsPolygon& output )
1946 {
1947  output.clear();
1949  if ( coords.size() < 1 )
1950  {
1951  return;
1952  }
1953  const QgsRingSequenceV2 &rings = coords[0];
1954  output.resize( rings.size() );
1955  for ( int i = 0; i < rings.size(); ++i )
1956  {
1957  convertToPolyline( rings[i], output[i] );
1958  }
1959 }
1960 
1961 GEOSContextHandle_t QgsGeometry::getGEOSHandler()
1962 {
1963  return QgsGeos::getGEOSHandler();
1964 }
1965 
1967 {
1968  return new QgsGeometry( new QgsPointV2( point.x(), point.y() ) );
1969 }
1970 
1972 {
1973  if ( polygon.isClosed() )
1974  {
1976  }
1977  else
1978  {
1980  }
1981 }
1982 
1984 {
1985  QgsPolygon result;
1986  result << createPolylineFromQPolygonF( polygon );
1987  return result;
1988 }
1989 
1991 {
1992  QgsPolyline result;
1993  QPolygonF::const_iterator it = polygon.constBegin();
1994  for ( ; it != polygon.constEnd(); ++it )
1995  {
1996  result.append( QgsPoint( *it ) );
1997  }
1998  return result;
1999 }
2000 
2001 bool QgsGeometry::compare( const QgsPolyline &p1, const QgsPolyline &p2, double epsilon )
2002 {
2003  if ( p1.count() != p2.count() )
2004  return false;
2005 
2006  for ( int i = 0; i < p1.count(); ++i )
2007  {
2008  if ( !p1.at( i ).compare( p2.at( i ), epsilon ) )
2009  return false;
2010  }
2011  return true;
2012 }
2013 
2014 bool QgsGeometry::compare( const QgsPolygon &p1, const QgsPolygon &p2, double epsilon )
2015 {
2016  if ( p1.count() != p2.count() )
2017  return false;
2018 
2019  for ( int i = 0; i < p1.count(); ++i )
2020  {
2021  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
2022  return false;
2023  }
2024  return true;
2025 }
2026 
2027 
2028 bool QgsGeometry::compare( const QgsMultiPolygon &p1, const QgsMultiPolygon &p2, double epsilon )
2029 {
2030  if ( p1.count() != p2.count() )
2031  return false;
2032 
2033  for ( int i = 0; i < p1.count(); ++i )
2034  {
2035  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
2036  return false;
2037  }
2038  return true;
2039 }
2040 
2041 QgsGeometry* QgsGeometry::smooth( const unsigned int iterations, const double offset ) const
2042 {
2043  switch ( wkbType() )
2044  {
2045  case QGis::WKBPoint:
2046  case QGis::WKBPoint25D:
2047  case QGis::WKBMultiPoint:
2049  //can't smooth a point based geometry
2050  return new QgsGeometry( *this );
2051 
2052  case QGis::WKBLineString:
2054  {
2055  QgsPolyline line = asPolyline();
2056  return QgsGeometry::fromPolyline( smoothLine( line, iterations, offset ) );
2057  }
2058 
2061  {
2062  QgsMultiPolyline multiline = asMultiPolyline();
2063  QgsMultiPolyline resultMultiline;
2064  QgsMultiPolyline::const_iterator lineIt = multiline.constBegin();
2065  for ( ; lineIt != multiline.constEnd(); ++lineIt )
2066  {
2067  resultMultiline << smoothLine( *lineIt, iterations, offset );
2068  }
2069  return QgsGeometry::fromMultiPolyline( resultMultiline );
2070  }
2071 
2072  case QGis::WKBPolygon:
2073  case QGis::WKBPolygon25D:
2074  {
2075  QgsPolygon poly = asPolygon();
2076  return QgsGeometry::fromPolygon( smoothPolygon( poly, iterations, offset ) );
2077  }
2078 
2079  case QGis::WKBMultiPolygon:
2081  {
2082  QgsMultiPolygon multipoly = asMultiPolygon();
2083  QgsMultiPolygon resultMultipoly;
2084  QgsMultiPolygon::const_iterator polyIt = multipoly.constBegin();
2085  for ( ; polyIt != multipoly.constEnd(); ++polyIt )
2086  {
2087  resultMultipoly << smoothPolygon( *polyIt, iterations, offset );
2088  }
2089  return QgsGeometry::fromMultiPolygon( resultMultipoly );
2090  }
2091 
2092  case QGis::WKBUnknown:
2093  default:
2094  return new QgsGeometry( *this );
2095  }
2096 }
2097 
2098 inline QgsPoint interpolatePointOnLine( const QgsPoint& p1, const QgsPoint& p2, const double offset )
2099 {
2100  double deltaX = p2.x() - p1.x();
2101  double deltaY = p2.y() - p1.y();
2102  return QgsPoint( p1.x() + deltaX * offset, p1.y() + deltaY * offset );
2103 }
2104 
2105 QgsPolyline QgsGeometry::smoothLine( const QgsPolyline& polyline, const unsigned int iterations, const double offset ) const
2106 {
2107  QgsPolyline result = polyline;
2108  for ( unsigned int iteration = 0; iteration < iterations; ++iteration )
2109  {
2110  QgsPolyline outputLine = QgsPolyline();
2111  outputLine.reserve( 2 * ( result.count() - 1 ) );
2112  for ( int i = 0; i < result.count() - 1; i++ )
2113  {
2114  const QgsPoint& p1 = result.at( i );
2115  const QgsPoint& p2 = result.at( i + 1 );
2116  outputLine << ( i == 0 ? result.at( i ) : interpolatePointOnLine( p1, p2, offset ) );
2117  outputLine << ( i == result.count() - 2 ? result.at( i + 1 ) : interpolatePointOnLine( p1, p2, 1.0 - offset ) );
2118  }
2119  result = outputLine;
2120  }
2121  return result;
2122 }
2123 
2124 QgsPolygon QgsGeometry::smoothPolygon( const QgsPolygon& polygon, const unsigned int iterations, const double offset ) const
2125 {
2126  QgsPolygon resultPoly;
2127  QgsPolygon::const_iterator ringIt = polygon.constBegin();
2128  for ( ; ringIt != polygon.constEnd(); ++ringIt )
2129  {
2130  QgsPolyline resultRing = *ringIt;
2131  for ( unsigned int iteration = 0; iteration < iterations; ++iteration )
2132  {
2133  QgsPolyline outputRing = QgsPolyline();
2134  outputRing.reserve( 2 * ( resultRing.count() - 1 ) + 1 );
2135  for ( int i = 0; i < resultRing.count() - 1; ++i )
2136  {
2137  const QgsPoint& p1 = resultRing.at( i );
2138  const QgsPoint& p2 = resultRing.at( i + 1 );
2139  outputRing << interpolatePointOnLine( p1, p2, offset );
2140  outputRing << interpolatePointOnLine( p1, p2, 1.0 - offset );
2141  }
2142  //close polygon
2143  outputRing << outputRing.at( 0 );
2144 
2145  resultRing = outputRing;
2146  }
2147  resultPoly << resultRing;
2148  }
2149  return resultPoly;
2150 }
2151 
2152 QgsGeometry* QgsGeometry::convertToPoint( bool destMultipart ) const
2153 {
2154  switch ( type() )
2155  {
2156  case QGis::Point:
2157  {
2158  bool srcIsMultipart = isMultipart();
2159 
2160  if (( destMultipart && srcIsMultipart ) ||
2161  ( !destMultipart && !srcIsMultipart ) )
2162  {
2163  // return a copy of the same geom
2164  return new QgsGeometry( *this );
2165  }
2166  if ( destMultipart )
2167  {
2168  // layer is multipart => make a multipoint with a single point
2169  return fromMultiPoint( QgsMultiPoint() << asPoint() );
2170  }
2171  else
2172  {
2173  // destination is singlepart => make a single part if possible
2174  QgsMultiPoint multiPoint = asMultiPoint();
2175  if ( multiPoint.count() == 1 )
2176  {
2177  return fromPoint( multiPoint[0] );
2178  }
2179  }
2180  return nullptr;
2181  }
2182 
2183  case QGis::Line:
2184  {
2185  // only possible if destination is multipart
2186  if ( !destMultipart )
2187  return nullptr;
2188 
2189  // input geometry is multipart
2190  if ( isMultipart() )
2191  {
2192  QgsMultiPolyline multiLine = asMultiPolyline();
2193  QgsMultiPoint multiPoint;
2194  for ( QgsMultiPolyline::const_iterator multiLineIt = multiLine.constBegin(); multiLineIt != multiLine.constEnd(); ++multiLineIt )
2195  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2196  multiPoint << *lineIt;
2197  return fromMultiPoint( multiPoint );
2198  }
2199  // input geometry is not multipart: copy directly the line into a multipoint
2200  else
2201  {
2202  QgsPolyline line = asPolyline();
2203  if ( !line.isEmpty() )
2204  return fromMultiPoint( line );
2205  }
2206  return nullptr;
2207  }
2208 
2209  case QGis::Polygon:
2210  {
2211  // can only transform if destination is multipoint
2212  if ( !destMultipart )
2213  return nullptr;
2214 
2215  // input geometry is multipart: make a multipoint from multipolygon
2216  if ( isMultipart() )
2217  {
2218  QgsMultiPolygon multiPolygon = asMultiPolygon();
2219  QgsMultiPoint multiPoint;
2220  for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
2221  for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
2222  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2223  multiPoint << *lineIt;
2224  return fromMultiPoint( multiPoint );
2225  }
2226  // input geometry is not multipart: make a multipoint from polygon
2227  else
2228  {
2229  QgsPolygon polygon = asPolygon();
2230  QgsMultiPoint multiPoint;
2231  for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
2232  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2233  multiPoint << *lineIt;
2234  return fromMultiPoint( multiPoint );
2235  }
2236  }
2237 
2238  default:
2239  return nullptr;
2240  }
2241 }
2242 
2243 QgsGeometry* QgsGeometry::convertToLine( bool destMultipart ) const
2244 {
2245  switch ( type() )
2246  {
2247  case QGis::Point:
2248  {
2249  if ( !isMultipart() )
2250  return nullptr;
2251 
2252  QgsMultiPoint multiPoint = asMultiPoint();
2253  if ( multiPoint.count() < 2 )
2254  return nullptr;
2255 
2256  if ( destMultipart )
2257  return fromMultiPolyline( QgsMultiPolyline() << multiPoint );
2258  else
2259  return fromPolyline( multiPoint );
2260  }
2261 
2262  case QGis::Line:
2263  {
2264  bool srcIsMultipart = isMultipart();
2265 
2266  if (( destMultipart && srcIsMultipart ) ||
2267  ( !destMultipart && ! srcIsMultipart ) )
2268  {
2269  // return a copy of the same geom
2270  return new QgsGeometry( *this );
2271  }
2272  if ( destMultipart )
2273  {
2274  // destination is multipart => makes a multipoint with a single line
2275  QgsPolyline line = asPolyline();
2276  if ( !line.isEmpty() )
2277  return fromMultiPolyline( QgsMultiPolyline() << line );
2278  }
2279  else
2280  {
2281  // destination is singlepart => make a single part if possible
2282  QgsMultiPolyline multiLine = asMultiPolyline();
2283  if ( multiLine.count() == 1 )
2284  return fromPolyline( multiLine[0] );
2285  }
2286  return nullptr;
2287  }
2288 
2289  case QGis::Polygon:
2290  {
2291  // input geometry is multipolygon
2292  if ( isMultipart() )
2293  {
2294  QgsMultiPolygon multiPolygon = asMultiPolygon();
2295  QgsMultiPolyline multiLine;
2296  for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
2297  for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
2298  multiLine << *multiLineIt;
2299 
2300  if ( destMultipart )
2301  {
2302  // destination is multipart
2303  return fromMultiPolyline( multiLine );
2304  }
2305  else if ( multiLine.count() == 1 )
2306  {
2307  // destination is singlepart => make a single part if possible
2308  return fromPolyline( multiLine[0] );
2309  }
2310  }
2311  // input geometry is single polygon
2312  else
2313  {
2314  QgsPolygon polygon = asPolygon();
2315  // if polygon has rings
2316  if ( polygon.count() > 1 )
2317  {
2318  // cannot fit a polygon with rings in a single line layer
2319  // TODO: would it be better to remove rings?
2320  if ( destMultipart )
2321  {
2322  QgsPolygon polygon = asPolygon();
2323  QgsMultiPolyline multiLine;
2324  for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
2325  multiLine << *multiLineIt;
2326  return fromMultiPolyline( multiLine );
2327  }
2328  }
2329  // no rings
2330  else if ( polygon.count() == 1 )
2331  {
2332  if ( destMultipart )
2333  {
2334  return fromMultiPolyline( polygon );
2335  }
2336  else
2337  {
2338  return fromPolyline( polygon[0] );
2339  }
2340  }
2341  }
2342  return nullptr;
2343  }
2344 
2345  default:
2346  return nullptr;
2347  }
2348 }
2349 
2350 QgsGeometry* QgsGeometry::convertToPolygon( bool destMultipart ) const
2351 {
2352  switch ( type() )
2353  {
2354  case QGis::Point:
2355  {
2356  if ( !isMultipart() )
2357  return nullptr;
2358 
2359  QgsMultiPoint multiPoint = asMultiPoint();
2360  if ( multiPoint.count() < 3 )
2361  return nullptr;
2362 
2363  if ( multiPoint.last() != multiPoint.first() )
2364  multiPoint << multiPoint.first();
2365 
2366  QgsPolygon polygon = QgsPolygon() << multiPoint;
2367  if ( destMultipart )
2368  return fromMultiPolygon( QgsMultiPolygon() << polygon );
2369  else
2370  return fromPolygon( polygon );
2371  }
2372 
2373  case QGis::Line:
2374  {
2375  // input geometry is multiline
2376  if ( isMultipart() )
2377  {
2378  QgsMultiPolyline multiLine = asMultiPolyline();
2379  QgsMultiPolygon multiPolygon;
2380  for ( QgsMultiPolyline::iterator multiLineIt = multiLine.begin(); multiLineIt != multiLine.end(); ++multiLineIt )
2381  {
2382  // do not create polygon for a 1 segment line
2383  if (( *multiLineIt ).count() < 3 )
2384  return nullptr;
2385  if (( *multiLineIt ).count() == 3 && ( *multiLineIt ).first() == ( *multiLineIt ).last() )
2386  return nullptr;
2387 
2388  // add closing node
2389  if (( *multiLineIt ).first() != ( *multiLineIt ).last() )
2390  *multiLineIt << ( *multiLineIt ).first();
2391  multiPolygon << ( QgsPolygon() << *multiLineIt );
2392  }
2393  // check that polygons were inserted
2394  if ( !multiPolygon.isEmpty() )
2395  {
2396  if ( destMultipart )
2397  {
2398  return fromMultiPolygon( multiPolygon );
2399  }
2400  else if ( multiPolygon.count() == 1 )
2401  {
2402  // destination is singlepart => make a single part if possible
2403  return fromPolygon( multiPolygon[0] );
2404  }
2405  }
2406  }
2407  // input geometry is single line
2408  else
2409  {
2410  QgsPolyline line = asPolyline();
2411 
2412  // do not create polygon for a 1 segment line
2413  if ( line.count() < 3 )
2414  return nullptr;
2415  if ( line.count() == 3 && line.first() == line.last() )
2416  return nullptr;
2417 
2418  // add closing node
2419  if ( line.first() != line.last() )
2420  line << line.first();
2421 
2422  // destination is multipart
2423  if ( destMultipart )
2424  {
2425  return fromMultiPolygon( QgsMultiPolygon() << ( QgsPolygon() << line ) );
2426  }
2427  else
2428  {
2429  return fromPolygon( QgsPolygon() << line );
2430  }
2431  }
2432  return nullptr;
2433  }
2434 
2435  case QGis::Polygon:
2436  {
2437  bool srcIsMultipart = isMultipart();
2438 
2439  if (( destMultipart && srcIsMultipart ) ||
2440  ( !destMultipart && ! srcIsMultipart ) )
2441  {
2442  // return a copy of the same geom
2443  return new QgsGeometry( *this );
2444  }
2445  if ( destMultipart )
2446  {
2447  // destination is multipart => makes a multipoint with a single polygon
2448  QgsPolygon polygon = asPolygon();
2449  if ( !polygon.isEmpty() )
2450  return fromMultiPolygon( QgsMultiPolygon() << polygon );
2451  }
2452  else
2453  {
2454  QgsMultiPolygon multiPolygon = asMultiPolygon();
2455  if ( multiPolygon.count() == 1 )
2456  {
2457  // destination is singlepart => make a single part if possible
2458  return fromPolygon( multiPolygon[0] );
2459  }
2460  }
2461  return nullptr;
2462  }
2463 
2464  default:
2465  return nullptr;
2466  }
2467 }
2468 
2470 {
2471  return new QgsGeos( geometry );
2472 }
2473 
2475 {
2476  QByteArray byteArray = QByteArray::fromRawData( reinterpret_cast< const char * >( geometry.asWkb() ), geometry.wkbSize() ); // does not copy data and does not take ownership
2477  out << byteArray;
2478  return out;
2479 }
2480 
2482 {
2483  QByteArray byteArray;
2484  in >> byteArray;
2485  if ( byteArray.isEmpty() )
2486  {
2487  geometry.setGeometry( nullptr );
2488  return in;
2489  }
2490 
2491  char *data = new char[byteArray.size()];
2492  memcpy( data, byteArray.data(), byteArray.size() );
2493  geometry.fromWkb( reinterpret_cast< unsigned char* >( data ), byteArray.size() );
2494  return in;
2495 }
QTransform fromTranslate(qreal dx, qreal dy)
QgsPolyline smoothLine(const QgsPolyline &polyline, const unsigned int iterations=1, const double offset=0.25) const
Smooths a polyline using the Chaikin algorithm.
static QgsGeometry * fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
QgsGeometry * simplify(double tolerance) const
Returns a simplified version of this geometry using a specified tolerance value.
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
void clear()
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
int vertexNrFromVertexId(QgsVertexId i) const
Returns the vertex number corresponding to a vertex idd.
QgsPointV2 pointN(int i) const
Returns the specified point from inside the line string.
QgsGeometry * convexHull() const
Returns the smallest convex polygon that contains all the points in the geometry. ...
QDataStream & operator<<(QDataStream &out, const QgsGeometry &geometry)
Writes the geometry to stream out.
GeometryType
Definition: qgis.h:115
double angleAtVertex(int vertex) const
Returns the bisector angle for this geometry at the specified vertex.
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.
QgsGeometry * symDifference(const QgsGeometry *geometry) const
Returns a geometry representing the points making up this geometry that do not make up other...
QgsAbstractGeometryV2 * combine(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:191
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)
double x() const
Returns the point&#39;s x-coordinate.
Definition: qgspointv2.h:68
QPolygonF asQPolygonF() const
Return contents of the geometry as a QPolygonF.
iterator begin()
void push_back(const T &value)
QgsGeometry * difference(const QgsGeometry *geometry) const
Returns a geometry representing the points making up this geometry that do not make up other...
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer&#39;s length...
double distance(const QgsGeometry &geom) const
Returns the minimum distance between this geometry and another geometry, using GEOS.
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.
static double averageAngle(double x1, double y1, double x2, double y2, double x3, double y3)
Angle between two linear segments.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:197
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.
QgsAbstractGeometryV2 * geometry() const
Returns the underlying geometry store.
void reserve(int alloc)
QgsMultiPolyline asMultiPolyline() const
Return contents of the geometry as a multi linestring if wkbType is WKBMultiLineString, otherwise an empty list.
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
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.
QPointF asQPointF() const
Return contents of the geometry as a QPointF if wkbType is WKBPoint, otherwise returns a null QPointF...
virtual QgsCoordinateSequenceV2 coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
QgsPolygon asPolygon() const
Return contents of the geometry as a polygon if wkbType is WKBPolygon, otherwise an empty list...
const_iterator constEnd() const
QList< QgsGeometry * > asGeometryCollection() const
Return contents of the geometry as a list of geometries.
QgsPoint transform(const QgsPoint &p) const
Transform the point from map (world) coordinates to device coordinates.
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
QgsGeometry closestPoint(const QgsGeometry &other, QString *errorMsg=nullptr) const
Returns the closest point on the geometry to the other geometry.
Definition: qgsgeos.cpp:1817
QgsRectangle boundingBox() const
Returns the bounding box of this feature.
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...
QGis::GeometryType type() const
Returns type of the geometry as a QGis::GeometryType.
static QgsAbstractGeometryV2 * fromPolygon(const QgsPolygon &polygon)
Construct geometry from a polygon.
double interpolateAngle(double distance) const
Returns the angle parallel to the linestring or polygon boundary at the specified distance along the ...
Abstract base class for all geometries.
double length(QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:365
bool crosses(const QgsGeometry *geometry) const
Test for if geometry crosses another (uses GEOS)
bool ref()
void adjacentVertices(int atVertex, int &beforeVertex, int &afterVertex) const
Returns the indexes of the vertices before and after the given vertex index.
QgsGeometry * pointOnSurface() const
Returns a point within a geometry.
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
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.
static QgsAbstractGeometryV2 * fromPoint(const QgsPoint &point)
Construct geometry from a point.
static QgsAbstractGeometryV2 * fromMultiPolygon(const QgsMultiPolygon &multipoly)
Construct geometry from a multipolygon.
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 & operator=(QgsGeometry const &rhs)
Assignments will prompt a deep copy of the object.
Definition: qgsgeometry.cpp:87
Multi line string geometry collection.
static QgsPolyline createPolylineFromQPolygonF(const QPolygonF &polygon)
Creates a QgsPolyline from a QPolygonF.
static int addPart(QgsAbstractGeometryV2 *geom, QgsAbstractGeometryV2 *part)
Adds part to multi type geometry (taking ownership)
double x() const
Get the x value of the point.
Definition: qgspoint.h:185
bool deleteRing(int ringNum, int partNum=0)
Delete a ring in polygon or multipolygon.
static GEOSContextHandle_t getGEOSHandler()
Definition: qgsgeos.cpp:2416
int size() const
QgsMultiPolygon asMultiPolygon() const
Return contents of the geometry as a multi polygon if wkbType is WKBMultiPolygon, otherwise an empty ...
double y() const
Returns the point&#39;s y-coordinate.
Definition: qgspointv2.h:74
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
bool isGeosEmpty() const
Check if the geometry is empty using GEOS.
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
int splitGeometry(const QList< QgsPoint > &splitLine, QList< QgsGeometry * > &newGeometries, bool topological, QList< QgsPoint > &topologyTestPoints)
Splits this geometry according to a given line.
void clear()
bool contains(const QgsPoint *p) const
Test for containment of a point (uses GEOS)
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
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.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:202
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:187
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
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.
QString exportToGeoJSON(int precision=17) const
Exports the geometry to GeoJSON.
bool overlaps(const QgsGeometry *geometry) const
Test for if geometry overlaps another (uses GEOS)
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...
QgsAbstractGeometryV2 * intersection(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:181
QgsPolygon smoothPolygon(const QgsPolygon &polygon, const unsigned int iterations=1, const double offset=0.25) const
Smooths a polygon using the Chaikin algorithm.
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 ...
QgsGeometry * interpolate(double distance) const
Return interpolated point on line at distance.
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 bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
virtual unsigned char * asWkb(int &binarySize) const =0
Returns a WKB representation of the geometry.
virtual QgsPointV2 * clone() const override
Clones the geometry by performing a deep copy.
Definition: qgspointv2.cpp:94
static void adjacentVertices(const QgsAbstractGeometryV2 &geom, QgsVertexId atVertex, QgsVertexId &beforeVertex, QgsVertexId &afterVertex)
Returns vertices adjacent to a specified vertex within a geometry.
QGis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
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
QgsGeometry * centroid() const
Returns the center of mass of a geometry.
void validateGeometry(QList< Error > &errors)
Validate geometry and produce a list of geometry errors.
const GEOSGeometry * asGeos(double precision=0) const
Returns a geos geometry.
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
bool deref()
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...
A class to represent a point.
Definition: qgspoint.h:117
bool isClosed() const
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.
This class offers geometry processing methods.
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 draw(QPainter &p) const
Draws the geometry onto a QPainter.
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 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.
void setY(double y)
Sets the y value of the point.
Definition: qgspoint.h:170
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 validateGeometry(const QgsGeometry *g, QList< QgsGeometry::Error > &errors)
Validate geometry and produce a list of geometry errors.
double length() const
Returns the length of geometry using GEOS.
QVector< QgsPolyline > QgsMultiPolyline
A collection of QgsPolylines that share a common collection of attributes.
Definition: qgsgeometry.h:56
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 bool deletePart(QgsAbstractGeometryV2 *geom, int partNum)
Deletes a part from a geometry.
QTransform & rotate(qreal angle, Qt::Axis axis)
bool isGeosEqual(const QgsGeometry &) const
Compares the geometry with another geometry using GEOS.
QgsGeometry * intersection(const QgsGeometry *geometry) const
Returns a geometry representing the points shared by this geometry and other.
bool vertexIdFromVertexNr(int nr, QgsVertexId &id) const
Calculates the vertex ID from a vertex number.
QgsGeometry * combine(const QgsGeometry *geometry) const
Returns a geometry representing all the points in this geometry and other (a union geometry operation...
static bool deleteRing(QgsAbstractGeometryV2 *geom, int ringNum, int partNum=0)
Deletes a ring from a geometry.
QgsPolyline asPolyline() const
Return contents of the geometry as a polyline if wkbType is WKBLineString, otherwise an empty list...
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...
int numGeometries() const
Returns the number of geometries within the collection.
static QgsPolygon createPolygonFromQPolygonF(const QPolygonF &polygon)
Creates a QgsPolygon from a QPolygonF.
const T & at(int i) const
const_iterator constBegin() const
virtual bool deleteVertex(QgsVertexId position)=0
Deletes a vertex within the geometry.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
int wkbSize() const
Returns the size of the WKB in asWkb().
QgsGeometry shortestLine(const QgsGeometry &other) const
Returns the shortest line joining this geometry to another geometry.
QgsGeometry nearestPoint(const QgsGeometry &other) const
Returns the nearest point on this geometry to another geometry.
static GEOSContextHandle_t getGEOSHandler()
Return GEOS context handle.
virtual bool insertVertex(QgsVertexId position, const QgsPointV2 &vertex)=0
Inserts a vertex into the geometry.
void mapToPixel(const QgsMapToPixel &mtp)
Transforms the geometry from map units to pixels in place.
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.
bool isEmpty() const
QgsAbstractGeometryV2 * reshapeGeometry(const QgsLineStringV2 &reshapeWithLine, int *errorCode, QString *errorMsg=nullptr) const
Definition: qgsgeos.cpp:1690
bool centroid(QgsPointV2 &pt, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1346
QgsMultiPoint asMultiPoint() const
Return contents of the geometry as a multi point if wkbType is WKBMultiPoint, otherwise an empty list...
bool equals(const QgsGeometry *geometry) const
Test for if geometry equals another (uses GEOS)
const unsigned char * mWkb
Definition: qgsgeometry.cpp:60
int rotate(double rotation, const QgsPoint &center)
Rotate this geometry around the Z axis.
bool isMultipart() const
Returns true if WKB of the geometry is of WKBMulti* type.
QgsGeometry shortestLine(const QgsGeometry &other, QString *errorMsg=nullptr) const
Returns the shortest line joining this geometry to the other geometry.
Definition: qgsgeos.cpp:1852
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...
virtual double area() const
Returns the area of the geometry.
int count(const T &value) const
bool within(const QgsGeometry *geometry) const
Test for if geometry is within another (uses GEOS)
bool isEqual(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1448
Class for doing transforms between two map coordinate systems.
virtual QString asWkt(int precision=17) const =0
Returns a WKT representation of the geometry.
const QgsAbstractGeometryV2 * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
static QgsGeometry * fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
bool requiresConversionToStraightSegments() const
Returns true if the geometry is a curved geometry type which requires conversion to display as straig...
int transform(const QgsCoordinateTransform &ct)
Transform this geometry as described by CoordinateTransform ct.
double lineLocatePoint(const QgsGeometry &point) const
Returns a distance representing the location along this linestring of the closest point on this lines...
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
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
static QgsGeometry * fromPolyline(const QgsPolyline &polyline)
Creates a new geometry from a QgsPolyline object.
double y() const
Get the y value of the point.
Definition: qgspoint.h:193
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 QgsGeometry * unaryUnion(const QList< QgsGeometry * > &geometryList)
Compute the unary union on a list of geometries.
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.
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.
bool isEmpty() const
Returns true if the geometry is empty (ie, contains no underlying geometry accessible via geometry)...
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
bool isValid() const
Returns true if the vertex id is valid.
bool touches(const QgsGeometry *geometry) const
Test for if geometry touch another (uses GEOS)
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.
QString exportToWkt(int precision=17) const
Exports the geometry to WKT.
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
QgsGeometry * smooth(const unsigned int iterations=1, const double offset=0.25) const
Smooths a geometry by rounding off corners using the Chaikin algorithm.
QgsPoint asPoint() const
Return contents of the geometry as a point if wkbType is WKBPoint, otherwise returns [0...
virtual bool moveVertex(QgsVertexId position, const QgsPointV2 &newPos)=0
Moves a vertex within the geometry.
int size() const
QgsGeometry * convertToType(QGis::GeometryType destType, bool destMultipart=false) const
Try to convert the geometry to the requested type.
bool intersects(const QgsRectangle &r) const
Test for intersection with a rectangle (uses GEOS)
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.
bool isGeosValid() const
Checks validity of the geometry using GEOS.
double distanceToVertex(int vertex) const
Returns the distance along this geometry from its first vertex to the specified vertex.
const unsigned char * asWkb() const
Returns the buffer containing this geometry in WKB format.
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:192
double closestVertexWithContext(const QgsPoint &point, int &atVertex) const
Searches for the closest vertex in this geometry to the given point.
iterator end()
QgsGeometry mergeLines() const
Merges any connected lines in a LineString/MultiLineString geometry and converts them to single line ...
QgsAbstractGeometryV2 * offsetCurve(double distance, int segments, int joinStyle, double mitreLimit, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1674
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
static void convertPointList(const QList< QgsPoint > &input, QgsPointSequenceV2 &output)
Upgrades a point list from QgsPoint to QgsPointV2.
virtual QgsAbstractGeometryV2 * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
double area() const
Returns the area of the geometry using 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
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.
double sqrDistToVertexAt(QgsPoint &point, int atVertex) const
Returns the squared cartesian distance between the given point to the given vertex index (vertex at t...
QPointF toQPointF() const
Converts a point to a QPointF.
Definition: qgspoint.cpp:129