QGIS API Documentation  2.14.0-Essen
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  detach( false );
136  if ( d->geometry )
137  {
138  delete d->geometry;
139  d->geometry = nullptr;
140  }
141  removeWkbGeos();
142 
143  d->geometry = geometry;
144 }
145 
147 {
148  return !d->geometry;
149 }
150 
152 {
154  if ( !geom )
155  {
156  return nullptr;
157  }
158  return new QgsGeometry( geom );
159 }
160 
162 {
164  if ( geom )
165  {
166  return new QgsGeometry( geom );
167  }
168  return nullptr;
169 }
170 
172 {
174  if ( geom )
175  {
176  return new QgsGeometry( geom );
177  }
178  return nullptr;
179 }
180 
182 {
184  if ( geom )
185  {
186  return new QgsGeometry( geom );
187  }
188  return nullptr;
189 }
190 
192 {
194  if ( geom )
195  {
196  return new QgsGeometry( geom );
197  }
198  return nullptr;
199 }
200 
202 {
204  if ( geom )
205  {
206  return new QgsGeometry( geom );
207  }
208  return nullptr;
209 }
210 
212 {
214  if ( geom )
215  {
216  return new QgsGeometry( geom );
217  }
218  return nullptr;
219 }
220 
222 {
223  QgsPolyline ring;
224  ring.append( QgsPoint( rect.xMinimum(), rect.yMinimum() ) );
225  ring.append( QgsPoint( rect.xMaximum(), rect.yMinimum() ) );
226  ring.append( QgsPoint( rect.xMaximum(), rect.yMaximum() ) );
227  ring.append( QgsPoint( rect.xMinimum(), rect.yMaximum() ) );
228  ring.append( QgsPoint( rect.xMinimum(), rect.yMinimum() ) );
229 
230  QgsPolygon polygon;
231  polygon.append( ring );
232 
233  return fromPolygon( polygon );
234 }
235 
236 void QgsGeometry::fromWkb( unsigned char *wkb, int length )
237 {
238  detach( false );
239 
240  if ( d->geometry )
241  {
242  delete d->geometry;
243  removeWkbGeos();
244  }
246  if ( d->geometry )
247  {
248  d->mWkb = wkb;
249  d->mWkbSize = length;
250  }
251  else
252  {
253  delete [] wkb;
254  d->mWkb = nullptr;
255  d->mWkbSize = 0;
256  }
257 }
258 
259 const unsigned char *QgsGeometry::asWkb() const
260 {
261  if ( !d->geometry )
262  {
263  return nullptr;
264  }
265 
266  if ( !d->mWkb )
267  {
268  d->mWkb = d->geometry->asWkb( d->mWkbSize );
269  }
270  return d->mWkb;
271 }
272 
274 {
275  if ( !d->geometry )
276  {
277  return 0;
278  }
279 
280  if ( !d->mWkb )
281  {
282  d->mWkb = d->geometry->asWkb( d->mWkbSize );
283  }
284  return d->mWkbSize;
285 }
286 
287 const GEOSGeometry* QgsGeometry::asGeos( double precision ) const
288 {
289  if ( !d->geometry )
290  {
291  return nullptr;
292  }
293 
294  if ( !d->mGeos )
295  {
296  d->mGeos = QgsGeos::asGeos( d->geometry, precision );
297  }
298  return d->mGeos;
299 }
300 
301 
303 {
304  if ( !d->geometry )
305  {
306  return QGis::WKBUnknown;
307  }
308  else
309  {
310  return QGis::fromNewWkbType( d->geometry->wkbType() );
311  }
312 }
313 
314 
316 {
317  if ( !d->geometry )
318  {
319  return QGis::UnknownGeometry;
320  }
321  return static_cast< QGis::GeometryType >( QgsWKBTypes::geometryType( d->geometry->wkbType() ) );
322 }
323 
325 {
326  if ( !d->geometry )
327  {
328  return false;
329  }
330  return QgsWKBTypes::isMultiType( d->geometry->wkbType() );
331 }
332 
333 void QgsGeometry::fromGeos( GEOSGeometry *geos )
334 {
335  detach( false );
336  delete d->geometry;
337  d->geometry = QgsGeos::fromGeos( geos );
338  d->mGeos = geos;
339 }
340 
341 QgsPoint QgsGeometry::closestVertex( const QgsPoint& point, int& atVertex, int& beforeVertex, int& afterVertex, double& sqrDist ) const
342 {
343  if ( !d->geometry )
344  {
345  return QgsPoint( 0, 0 );
346  }
347 
348  QgsPointV2 pt( point.x(), point.y() );
349  QgsVertexId id;
350 
351  QgsPointV2 vp = QgsGeometryUtils::closestVertex( *( d->geometry ), pt, id );
352  if ( !id.isValid() )
353  {
354  sqrDist = -1;
355  return QgsPoint( 0, 0 );
356  }
357  sqrDist = QgsGeometryUtils::sqrDistance2D( pt, vp );
358 
359  atVertex = vertexNrFromVertexId( id );
360  adjacentVertices( atVertex, beforeVertex, afterVertex );
361  return QgsPoint( vp.x(), vp.y() );
362 }
363 
364 void QgsGeometry::adjacentVertices( int atVertex, int& beforeVertex, int& afterVertex ) const
365 {
366  if ( !d->geometry )
367  {
368  return;
369  }
370 
371  QgsVertexId id;
372  if ( !vertexIdFromVertexNr( atVertex, id ) )
373  {
374  beforeVertex = -1;
375  afterVertex = -1;
376  return;
377  }
378 
379  QgsVertexId beforeVertexId, afterVertexId;
380  QgsGeometryUtils::adjacentVertices( *( d->geometry ), id, beforeVertexId, afterVertexId );
381  beforeVertex = vertexNrFromVertexId( beforeVertexId );
382  afterVertex = vertexNrFromVertexId( afterVertexId );
383 }
384 
385 bool QgsGeometry::moveVertex( double x, double y, int atVertex )
386 {
387  if ( !d->geometry )
388  {
389  return false;
390  }
391 
392  QgsVertexId id;
393  if ( !vertexIdFromVertexNr( atVertex, id ) )
394  {
395  return false;
396  }
397 
398  detach( true );
399 
400  removeWkbGeos();
401  return d->geometry->moveVertex( id, QgsPointV2( x, y ) );
402 }
403 
404 bool QgsGeometry::moveVertex( const QgsPointV2& p, int atVertex )
405 {
406  if ( !d->geometry )
407  {
408  return false;
409  }
410 
411  QgsVertexId id;
412  if ( !vertexIdFromVertexNr( atVertex, id ) )
413  {
414  return false;
415  }
416 
417  detach( true );
418 
419  removeWkbGeos();
420  return d->geometry->moveVertex( id, p );
421 }
422 
423 bool QgsGeometry::deleteVertex( int atVertex )
424 {
425  if ( !d->geometry )
426  {
427  return false;
428  }
429 
430  //maintain compatibility with < 2.10 API
431  if ( d->geometry->geometryType() == "MultiPoint" )
432  {
433  detach( true );
434  removeWkbGeos();
435  //delete geometry instead of point
436  return static_cast< QgsGeometryCollectionV2* >( d->geometry )->removeGeometry( atVertex );
437  }
438 
439  //if it is a point, set the geometry to nullptr
441  {
442  detach( false );
443  delete d->geometry;
444  removeWkbGeos();
445  d->geometry = nullptr;
446  return true;
447  }
448 
449  QgsVertexId id;
450  if ( !vertexIdFromVertexNr( atVertex, id ) )
451  {
452  return false;
453  }
454 
455  detach( true );
456 
457  removeWkbGeos();
458  return d->geometry->deleteVertex( id );
459 }
460 
461 bool QgsGeometry::insertVertex( double x, double y, int beforeVertex )
462 {
463  if ( !d->geometry )
464  {
465  return false;
466  }
467 
468  //maintain compatibility with < 2.10 API
469  if ( d->geometry->geometryType() == "MultiPoint" )
470  {
471  detach( true );
472  removeWkbGeos();
473  //insert geometry instead of point
474  return static_cast< QgsGeometryCollectionV2* >( d->geometry )->insertGeometry( new QgsPointV2( x, y ), beforeVertex );
475  }
476 
477  QgsVertexId id;
478  if ( !vertexIdFromVertexNr( beforeVertex, id ) )
479  {
480  return false;
481  }
482 
483  detach( true );
484 
485  removeWkbGeos();
486 
487  return d->geometry->insertVertex( id, QgsPointV2( x, y ) );
488 }
489 
490 QgsPoint QgsGeometry::vertexAt( int atVertex ) const
491 {
492  if ( !d->geometry )
493  {
494  return QgsPoint( 0, 0 );
495  }
496 
497  QgsVertexId vId;
498  ( void )vertexIdFromVertexNr( atVertex, vId );
499  if ( vId.vertex < 0 )
500  {
501  return QgsPoint( 0, 0 );
502  }
503  QgsPointV2 pt = d->geometry->vertexAt( vId );
504  return QgsPoint( pt.x(), pt.y() );
505 }
506 
507 double QgsGeometry::sqrDistToVertexAt( QgsPoint& point, int atVertex ) const
508 {
509  QgsPoint vertexPoint = vertexAt( atVertex );
510  return QgsGeometryUtils::sqrDistance2D( QgsPointV2( vertexPoint.x(), vertexPoint.y() ), QgsPointV2( point.x(), point.y() ) );
511 }
512 
514 {
515  QgsGeos geos( d->geometry );
516  return geos.closestPoint( other );
517 }
518 
520 {
521  QgsGeos geos( d->geometry );
522  return geos.shortestLine( other );
523 }
524 
525 double QgsGeometry::closestVertexWithContext( const QgsPoint& point, int& atVertex ) const
526 {
527  if ( !d->geometry )
528  {
529  return 0.0;
530  }
531 
532  QgsVertexId vId;
533  QgsPointV2 pt( point.x(), point.y() );
534  QgsPointV2 closestPoint = QgsGeometryUtils::closestVertex( *( d->geometry ), pt, vId );
535  atVertex = vertexNrFromVertexId( vId );
536  return QgsGeometryUtils::sqrDistance2D( closestPoint, pt );
537 }
538 
540  const QgsPoint& point,
541  QgsPoint& minDistPoint,
542  int& afterVertex,
543  double *leftOf,
544  double epsilon ) const
545 {
546  if ( !d->geometry )
547  {
548  return 0;
549  }
550 
551  QgsPointV2 segmentPt;
552  QgsVertexId vertexAfter;
553  bool leftOfBool;
554 
555  double sqrDist = d->geometry->closestSegment( QgsPointV2( point.x(), point.y() ), segmentPt, vertexAfter, &leftOfBool, epsilon );
556 
557  minDistPoint.setX( segmentPt.x() );
558  minDistPoint.setY( segmentPt.y() );
559  afterVertex = vertexNrFromVertexId( vertexAfter );
560  if ( leftOf )
561  {
562  *leftOf = leftOfBool ? 1.0 : -1.0;
563  }
564  return sqrDist;
565 }
566 
568 {
569  detach( true );
570 
571  removeWkbGeos();
572  QgsLineStringV2* ringLine = new QgsLineStringV2();
573  QgsPointSequenceV2 ringPoints;
574  convertPointList( ring, ringPoints );
575  ringLine->setPoints( ringPoints );
576  return addRing( ringLine );
577 }
578 
580 {
581  if ( !d->geometry )
582  {
583  delete ring;
584  return 1;
585  }
586 
587  detach( true );
588 
589  removeWkbGeos();
590  return QgsGeometryEditUtils::addRing( d->geometry, ring );
591 }
592 
594 {
596  convertPointList( points, l );
597  return addPart( l, geomType );
598 }
599 
601 {
602  QgsAbstractGeometryV2* partGeom = nullptr;
603  if ( points.size() == 1 )
604  {
605  partGeom = new QgsPointV2( points[0] );
606  }
607  else if ( points.size() > 1 )
608  {
609  QgsLineStringV2* ringLine = new QgsLineStringV2();
610  ringLine->setPoints( points );
611  partGeom = ringLine;
612  }
613  return addPart( partGeom, geomType );
614 }
615 
617 {
618  if ( !d->geometry )
619  {
620  detach( false );
621  switch ( geomType )
622  {
623  case QGis::Point:
624  d->geometry = new QgsMultiPointV2();
625  break;
626  case QGis::Line:
627  d->geometry = new QgsMultiLineStringV2();
628  break;
629  case QGis::Polygon:
630  d->geometry = new QgsMultiPolygonV2();
631  break;
632  default:
633  return 1;
634  }
635  }
636  else
637  {
638  detach( true );
639  removeWkbGeos();
640  }
641 
643  return QgsGeometryEditUtils::addPart( d->geometry, part );
644 }
645 
646 int QgsGeometry::addPart( const QgsGeometry *newPart )
647 {
648  if ( !d->geometry || !newPart || !newPart->d || !newPart->d->geometry )
649  {
650  return 1;
651  }
652 
653  return addPart( newPart->d->geometry->clone() );
654 }
655 
656 int QgsGeometry::addPart( GEOSGeometry *newPart )
657 {
658  if ( !d->geometry || !newPart )
659  {
660  return 1;
661  }
662 
663  detach( true );
664 
665  QgsAbstractGeometryV2* geom = QgsGeos::fromGeos( newPart );
666  removeWkbGeos();
667  return QgsGeometryEditUtils::addPart( d->geometry, geom );
668 }
669 
670 int QgsGeometry::translate( double dx, double dy )
671 {
672  if ( !d->geometry )
673  {
674  return 1;
675  }
676 
677  detach( true );
678 
680  removeWkbGeos();
681  return 0;
682 }
683 
684 int QgsGeometry::rotate( double rotation, const QgsPoint& center )
685 {
686  if ( !d->geometry )
687  {
688  return 1;
689  }
690 
691  detach( true );
692 
693  QTransform t = QTransform::fromTranslate( center.x(), center.y() );
694  t.rotate( -rotation );
695  t.translate( -center.x(), -center.y() );
696  d->geometry->transform( t );
697  removeWkbGeos();
698  return 0;
699 }
700 
701 int QgsGeometry::splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries, bool topological, QList<QgsPoint> &topologyTestPoints )
702 {
703  if ( !d->geometry )
704  {
705  return 0;
706  }
707 
709  QgsLineStringV2 splitLineString;
710  QgsPointSequenceV2 splitLinePointsV2;
711  convertPointList( splitLine, splitLinePointsV2 );
712  splitLineString.setPoints( splitLinePointsV2 );
714 
715  QgsGeos geos( d->geometry );
716  int result = geos.splitGeometry( splitLineString, newGeoms, topological, tp );
717 
718  if ( result == 0 )
719  {
720  detach( false );
721  d->geometry = newGeoms.at( 0 );
722 
723  newGeometries.clear();
724  for ( int i = 1; i < newGeoms.size(); ++i )
725  {
726  newGeometries.push_back( new QgsGeometry( newGeoms.at( i ) ) );
727  }
728  }
729 
730  convertPointList( tp, topologyTestPoints );
731  removeWkbGeos();
732  return result;
733 }
734 
736 int QgsGeometry::reshapeGeometry( const QList<QgsPoint>& reshapeWithLine )
737 {
738  if ( !d->geometry )
739  {
740  return 0;
741  }
742 
743  QgsPointSequenceV2 reshapeLine;
744  convertPointList( reshapeWithLine, reshapeLine );
745  QgsLineStringV2 reshapeLineString;
746  reshapeLineString.setPoints( reshapeLine );
747 
748  QgsGeos geos( d->geometry );
749  int errorCode = 0;
750  QgsAbstractGeometryV2* geom = geos.reshapeGeometry( reshapeLineString, &errorCode );
751  if ( errorCode == 0 && geom )
752  {
753  detach( false );
754  delete d->geometry;
755  d->geometry = geom;
756  removeWkbGeos();
757  return 0;
758  }
759  return errorCode;
760 }
761 
763 {
764  if ( !d->geometry || !other->d->geometry )
765  {
766  return 0;
767  }
768 
769  QgsGeos geos( d->geometry );
770 
771  QgsAbstractGeometryV2* diffGeom = geos.intersection( *( other->geometry() ) );
772  if ( !diffGeom )
773  {
774  return 1;
775  }
776 
777  detach( false );
778 
779  delete d->geometry;
780  d->geometry = diffGeom;
781  removeWkbGeos();
782  return 0;
783 }
784 
786 {
787  if ( d->geometry )
788  {
789  return d->geometry->boundingBox();
790  }
791  return QgsRectangle();
792 }
793 
794 bool QgsGeometry::intersects( const QgsRectangle& r ) const
795 {
796  QgsGeometry* g = fromRect( r );
797  bool res = intersects( g );
798  delete g;
799  return res;
800 }
801 
803 {
804  if ( !d->geometry || !geometry || !geometry->d->geometry )
805  {
806  return false;
807  }
808 
809  QgsGeos geos( d->geometry );
810  return geos.intersects( *( geometry->d->geometry ) );
811 }
812 
813 bool QgsGeometry::contains( const QgsPoint* p ) const
814 {
815  if ( !d->geometry || !p )
816  {
817  return false;
818  }
819 
820  QgsPointV2 pt( p->x(), p->y() );
821  QgsGeos geos( d->geometry );
822  return geos.contains( pt );
823 }
824 
826 {
827  if ( !d->geometry || !geometry || !geometry->d->geometry )
828  {
829  return false;
830  }
831 
832  QgsGeos geos( d->geometry );
833  return geos.contains( *( geometry->d->geometry ) );
834 }
835 
837 {
838  if ( !d->geometry || !geometry || !geometry->d->geometry )
839  {
840  return false;
841  }
842 
843  QgsGeos geos( d->geometry );
844  return geos.disjoint( *( geometry->d->geometry ) );
845 }
846 
848 {
849  if ( !d->geometry || !geometry || !geometry->d->geometry )
850  {
851  return false;
852  }
853 
854  QgsGeos geos( d->geometry );
855  return geos.isEqual( *( geometry->d->geometry ) );
856 }
857 
859 {
860  if ( !d->geometry || !geometry || !geometry->d->geometry )
861  {
862  return false;
863  }
864 
865  QgsGeos geos( d->geometry );
866  return geos.touches( *( geometry->d->geometry ) );
867 }
868 
870 {
871  if ( !d->geometry || !geometry || !geometry->d->geometry )
872  {
873  return false;
874  }
875 
876  QgsGeos geos( d->geometry );
877  return geos.overlaps( *( geometry->d->geometry ) );
878 }
879 
881 {
882  if ( !d->geometry || !geometry || !geometry->d->geometry )
883  {
884  return false;
885  }
886 
887  QgsGeos geos( d->geometry );
888  return geos.within( *( geometry->d->geometry ) );
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.crosses( *( geometry->d->geometry ) );
900 }
901 
902 QString QgsGeometry::exportToWkt( int precision ) const
903 {
904  if ( !d->geometry )
905  {
906  return QString();
907  }
908  return d->geometry->asWkt( precision );
909 }
910 
911 QString QgsGeometry::exportToGeoJSON( int precision ) const
912 {
913  if ( !d->geometry )
914  {
915  return QString();
916  }
917  return d->geometry->asJSON( precision );
918 }
919 
920 QgsGeometry* QgsGeometry::convertToType( QGis::GeometryType destType, bool destMultipart ) const
921 {
922  switch ( destType )
923  {
924  case QGis::Point:
925  return convertToPoint( destMultipart );
926 
927  case QGis::Line:
928  return convertToLine( destMultipart );
929 
930  case QGis::Polygon:
931  return convertToPolygon( destMultipart );
932 
933  default:
934  return nullptr;
935  }
936 }
937 
939 {
940  if ( !d->geometry )
941  {
942  return false;
943  }
944 
945  if ( isMultipart() ) //already multitype, no need to convert
946  {
947  return true;
948  }
949 
950  QgsGeometryCollectionV2* multiGeom = dynamic_cast<QgsGeometryCollectionV2*>
952  if ( !multiGeom )
953  {
954  return false;
955  }
956 
957  detach( true );
958  multiGeom->addGeometry( d->geometry );
959  d->geometry = multiGeom;
960  removeWkbGeos();
961  return true;
962 }
963 
965 {
966  if ( !d->geometry )
967  {
968  return false;
969  }
970 
971  if ( !isMultipart() ) //already single part, no need to convert
972  {
973  return true;
974  }
975 
976  QgsGeometryCollectionV2* multiGeom = dynamic_cast<QgsGeometryCollectionV2*>( d->geometry );
977  if ( !multiGeom || multiGeom->partCount() < 1 )
978  return false;
979 
980  QgsAbstractGeometryV2* firstPart = multiGeom->geometryN( 0 )->clone();
981  detach( false );
982 
983  d->geometry = firstPart;
984  removeWkbGeos();
985  return true;
986 }
987 
989 {
990  if ( !d->geometry || d->geometry->geometryType() != "Point" )
991  {
992  return QgsPoint();
993  }
994  QgsPointV2* pt = dynamic_cast<QgsPointV2*>( d->geometry );
995  if ( !pt )
996  {
997  return QgsPoint();
998  }
999 
1000  return QgsPoint( pt->x(), pt->y() );
1001 }
1002 
1004 {
1005  QgsPolyline polyLine;
1006  if ( !d->geometry )
1007  {
1008  return polyLine;
1009  }
1010 
1011  bool doSegmentation = ( d->geometry->geometryType() == "CompoundCurve" || d->geometry->geometryType() == "CircularString" );
1012  QgsLineStringV2* line = nullptr;
1013  if ( doSegmentation )
1014  {
1015  QgsCurveV2* curve = dynamic_cast<QgsCurveV2*>( d->geometry );
1016  if ( !curve )
1017  {
1018  return polyLine;
1019  }
1020  line = curve->curveToLine();
1021  }
1022  else
1023  {
1024  line = dynamic_cast<QgsLineStringV2*>( d->geometry );
1025  if ( !line )
1026  {
1027  return polyLine;
1028  }
1029  }
1030 
1031  int nVertices = line->numPoints();
1032  polyLine.resize( nVertices );
1033  for ( int i = 0; i < nVertices; ++i )
1034  {
1035  QgsPointV2 pt = line->pointN( i );
1036  polyLine[i].setX( pt.x() );
1037  polyLine[i].setY( pt.y() );
1038  }
1039 
1040  if ( doSegmentation )
1041  {
1042  delete line;
1043  }
1044 
1045  return polyLine;
1046 }
1047 
1049 {
1050  if ( !d->geometry )
1051  return QgsPolygon();
1052 
1053  bool doSegmentation = ( d->geometry->geometryType() == "CurvePolygon" );
1054 
1055  QgsPolygonV2* p = nullptr;
1056  if ( doSegmentation )
1057  {
1058  QgsCurvePolygonV2* curvePoly = dynamic_cast<QgsCurvePolygonV2*>( d->geometry );
1059  if ( !curvePoly )
1060  {
1061  return QgsPolygon();
1062  }
1063  p = curvePoly->toPolygon();
1064  }
1065  else
1066  {
1067  p = dynamic_cast<QgsPolygonV2*>( d->geometry );
1068  }
1069 
1070  if ( !p )
1071  {
1072  return QgsPolygon();
1073  }
1074 
1075  QgsPolygon polygon;
1076  convertPolygon( *p, polygon );
1077 
1078  if ( doSegmentation )
1079  {
1080  delete p;
1081  }
1082  return polygon;
1083 }
1084 
1086 {
1087  if ( !d->geometry || d->geometry->geometryType() != "MultiPoint" )
1088  {
1089  return QgsMultiPoint();
1090  }
1091 
1092  const QgsMultiPointV2* mp = dynamic_cast<QgsMultiPointV2*>( d->geometry );
1093  if ( !mp )
1094  {
1095  return QgsMultiPoint();
1096  }
1097 
1098  int nPoints = mp->numGeometries();
1099  QgsMultiPoint multiPoint( nPoints );
1100  for ( int i = 0; i < nPoints; ++i )
1101  {
1102  const QgsPointV2* pt = static_cast<const QgsPointV2*>( mp->geometryN( i ) );
1103  multiPoint[i].setX( pt->x() );
1104  multiPoint[i].setY( pt->y() );
1105  }
1106  return multiPoint;
1107 }
1108 
1110 {
1111  if ( !d->geometry )
1112  {
1113  return QgsMultiPolyline();
1114  }
1115 
1116  QgsGeometryCollectionV2* geomCollection = dynamic_cast<QgsGeometryCollectionV2*>( d->geometry );
1117  if ( !geomCollection )
1118  {
1119  return QgsMultiPolyline();
1120  }
1121 
1122  int nLines = geomCollection->numGeometries();
1123  if ( nLines < 1 )
1124  {
1125  return QgsMultiPolyline();
1126  }
1127 
1128  QgsMultiPolyline mpl;
1129  for ( int i = 0; i < nLines; ++i )
1130  {
1131  bool deleteLine = false;
1132  const QgsLineStringV2* line = dynamic_cast<const QgsLineStringV2*>( geomCollection->geometryN( i ) );
1133  if ( !line )
1134  {
1135  const QgsCurveV2* curve = dynamic_cast<const QgsCurveV2*>( geomCollection->geometryN( i ) );
1136  if ( !curve )
1137  {
1138  continue;
1139  }
1140  deleteLine = true;
1141  line = curve->curveToLine();
1142  }
1143 
1144  QgsPointSequenceV2 lineCoords;
1145  line->points( lineCoords );
1146  QgsPolyline polyLine;
1147  convertToPolyline( lineCoords, polyLine );
1148  mpl.append( polyLine );
1149 
1150  if ( deleteLine )
1151  {
1152  delete line;
1153  }
1154  }
1155  return mpl;
1156 }
1157 
1159 {
1160  if ( !d->geometry )
1161  {
1162  return QgsMultiPolygon();
1163  }
1164 
1165  QgsGeometryCollectionV2* geomCollection = dynamic_cast<QgsGeometryCollectionV2*>( d->geometry );
1166  if ( !geomCollection )
1167  {
1168  return QgsMultiPolygon();
1169  }
1170 
1171  int nPolygons = geomCollection->numGeometries();
1172  if ( nPolygons < 1 )
1173  {
1174  return QgsMultiPolygon();
1175  }
1176 
1177  QgsMultiPolygon mp;
1178  for ( int i = 0; i < nPolygons; ++i )
1179  {
1180  const QgsPolygonV2* polygon = dynamic_cast<const QgsPolygonV2*>( geomCollection->geometryN( i ) );
1181  if ( !polygon )
1182  {
1183  const QgsCurvePolygonV2* cPolygon = dynamic_cast<const QgsCurvePolygonV2*>( geomCollection->geometryN( i ) );
1184  if ( cPolygon )
1185  {
1186  polygon = cPolygon->toPolygon();
1187  }
1188  else
1189  {
1190  continue;
1191  }
1192  }
1193 
1194  QgsPolygon poly;
1195  convertPolygon( *polygon, poly );
1196  mp.append( poly );
1197  }
1198  return mp;
1199 }
1200 
1201 double QgsGeometry::area() const
1202 {
1203  if ( !d->geometry )
1204  {
1205  return -1.0;
1206  }
1207  QgsGeos g( d->geometry );
1208 
1209 #if 0
1210  //debug: compare geos area with calculation in QGIS
1211  double geosArea = g.area();
1212  double qgisArea = 0;
1213  QgsSurfaceV2* surface = dynamic_cast<QgsSurfaceV2*>( d->geometry );
1214  if ( surface )
1215  {
1216  qgisArea = surface->area();
1217  }
1218 #endif
1219 
1220  return g.area();
1221 }
1222 
1223 double QgsGeometry::length() const
1224 {
1225  if ( !d->geometry )
1226  {
1227  return -1.0;
1228  }
1229  QgsGeos g( d->geometry );
1230  return g.length();
1231 }
1232 
1233 double QgsGeometry::distance( const QgsGeometry& geom ) const
1234 {
1235  if ( !d->geometry || !geom.d->geometry )
1236  {
1237  return -1.0;
1238  }
1239 
1240  QgsGeos g( d->geometry );
1241  return g.distance( *( geom.d->geometry ) );
1242 }
1243 
1244 QgsGeometry* QgsGeometry::buffer( double distance, int segments ) const
1245 {
1246  if ( !d->geometry )
1247  {
1248  return nullptr;
1249  }
1250 
1251  QgsGeos g( d->geometry );
1252  QgsAbstractGeometryV2* geom = g.buffer( distance, segments );
1253  if ( !geom )
1254  {
1255  return nullptr;
1256  }
1257  return new QgsGeometry( geom );
1258 }
1259 
1260 QgsGeometry* QgsGeometry::buffer( double distance, int segments, int endCapStyle, int joinStyle, double mitreLimit ) const
1261 {
1262  if ( !d->geometry )
1263  {
1264  return nullptr;
1265  }
1266 
1267  QgsGeos g( d->geometry );
1268  QgsAbstractGeometryV2* geom = g.buffer( distance, segments, endCapStyle, joinStyle, mitreLimit );
1269  if ( !geom )
1270  {
1271  return nullptr;
1272  }
1273  return new QgsGeometry( geom );
1274 }
1275 
1276 QgsGeometry* QgsGeometry::offsetCurve( double distance, int segments, int joinStyle, double mitreLimit ) const
1277 {
1278  if ( !d->geometry )
1279  {
1280  return nullptr;
1281  }
1282 
1283  QgsGeos geos( d->geometry );
1284  QgsAbstractGeometryV2* offsetGeom = geos.offsetCurve( distance, segments, joinStyle, mitreLimit );
1285  if ( !offsetGeom )
1286  {
1287  return nullptr;
1288  }
1289  return new QgsGeometry( offsetGeom );
1290 }
1291 
1292 QgsGeometry* QgsGeometry::simplify( double tolerance ) const
1293 {
1294  if ( !d->geometry )
1295  {
1296  return nullptr;
1297  }
1298 
1299  QgsGeos geos( d->geometry );
1300  QgsAbstractGeometryV2* simplifiedGeom = geos.simplify( tolerance );
1301  if ( !simplifiedGeom )
1302  {
1303  return nullptr;
1304  }
1305  return new QgsGeometry( simplifiedGeom );
1306 }
1307 
1309 {
1310  if ( !d->geometry )
1311  {
1312  return nullptr;
1313  }
1314 
1315  QgsGeos geos( d->geometry );
1317  bool ok = geos.centroid( centroid );
1318  if ( !ok )
1319  {
1320  return nullptr;
1321  }
1322  return new QgsGeometry( centroid.clone() );
1323 }
1324 
1326 {
1327  if ( !d->geometry )
1328  {
1329  return nullptr;
1330  }
1331 
1332  QgsGeos geos( d->geometry );
1333  QgsPointV2 pt;
1334  bool ok = geos.pointOnSurface( pt );
1335  if ( !ok )
1336  {
1337  return nullptr;
1338  }
1339  return new QgsGeometry( pt.clone() );
1340 }
1341 
1343 {
1344  if ( !d->geometry )
1345  {
1346  return nullptr;
1347  }
1348  QgsGeos geos( d->geometry );
1349  QgsAbstractGeometryV2* cHull = geos.convexHull();
1350  if ( !cHull )
1351  {
1352  return nullptr;
1353  }
1354  return new QgsGeometry( cHull );
1355 }
1356 
1358 {
1359  if ( !d->geometry )
1360  {
1361  return nullptr;
1362  }
1363  QgsGeos geos( d->geometry );
1364  QgsAbstractGeometryV2* result = geos.interpolate( distance );
1365  if ( !result )
1366  {
1367  return nullptr;
1368  }
1369  return new QgsGeometry( result );
1370 }
1371 
1373 {
1374  if ( !d->geometry || !geometry->d->geometry )
1375  {
1376  return nullptr;
1377  }
1378 
1379  QgsGeos geos( d->geometry );
1380 
1381  QgsAbstractGeometryV2* resultGeom = geos.intersection( *( geometry->d->geometry ) );
1382  return new QgsGeometry( resultGeom );
1383 }
1384 
1386 {
1387  if ( !d->geometry || !geometry->d->geometry )
1388  {
1389  return nullptr;
1390  }
1391 
1392  QgsGeos geos( d->geometry );
1393 
1394  QgsAbstractGeometryV2* resultGeom = geos.combine( *( geometry->d->geometry ) );
1395  if ( !resultGeom )
1396  {
1397  return nullptr;
1398  }
1399  return new QgsGeometry( resultGeom );
1400 }
1401 
1403 {
1404  if ( !d->geometry || !geometry->d->geometry )
1405  {
1406  return nullptr;
1407  }
1408 
1409  QgsGeos geos( d->geometry );
1410 
1411  QgsAbstractGeometryV2* resultGeom = geos.difference( *( geometry->d->geometry ) );
1412  if ( !resultGeom )
1413  {
1414  return nullptr;
1415  }
1416  return new QgsGeometry( resultGeom );
1417 }
1418 
1420 {
1421  if ( !d->geometry || !geometry->d->geometry )
1422  {
1423  return nullptr;
1424  }
1425 
1426  QgsGeos geos( d->geometry );
1427 
1428  QgsAbstractGeometryV2* resultGeom = geos.symDifference( *( geometry->d->geometry ) );
1429  if ( !resultGeom )
1430  {
1431  return nullptr;
1432  }
1433  return new QgsGeometry( resultGeom );
1434 }
1435 
1436 QgsGeometry QgsGeometry::extrude( double x, double y )
1437 {
1438  QgsInternalGeometryEngine engine( *this );
1439 
1440  return engine.extrude( x, y );
1441 }
1442 
1444 {
1445  QList<QgsGeometry*> geometryList;
1446  if ( !d->geometry )
1447  {
1448  return geometryList;
1449  }
1450 
1451  QgsGeometryCollectionV2* gc = dynamic_cast<QgsGeometryCollectionV2*>( d->geometry );
1452  if ( gc )
1453  {
1454  int numGeom = gc->numGeometries();
1455  geometryList.reserve( numGeom );
1456  for ( int i = 0; i < numGeom; ++i )
1457  {
1458  geometryList.append( new QgsGeometry( gc->geometryN( i )->clone() ) );
1459  }
1460  }
1461  else //a singlepart geometry
1462  {
1463  geometryList.append( new QgsGeometry( d->geometry->clone() ) );
1464  }
1465 
1466  return geometryList;
1467 }
1468 
1470 {
1471  QgsPoint point = asPoint();
1472  return point.toQPointF();
1473 }
1474 
1476 {
1477  QPolygonF result;
1478  QgsPolyline polyline;
1480  if ( type == QGis::WKBLineString || type == QGis::WKBLineString25D )
1481  {
1482  polyline = asPolyline();
1483  }
1484  else if ( type == QGis::WKBPolygon || type == QGis::WKBPolygon25D )
1485  {
1486  QgsPolygon polygon = asPolygon();
1487  if ( polygon.size() < 1 )
1488  return result;
1489  polyline = polygon.at( 0 );
1490  }
1491  else
1492  {
1493  return result;
1494  }
1495 
1496  QgsPolyline::const_iterator lineIt = polyline.constBegin();
1497  for ( ; lineIt != polyline.constEnd(); ++lineIt )
1498  {
1499  result << lineIt->toQPointF();
1500  }
1501  return result;
1502 }
1503 
1504 bool QgsGeometry::deleteRing( int ringNum, int partNum )
1505 {
1506  if ( !d->geometry )
1507  {
1508  return false;
1509  }
1510 
1511  detach( true );
1512 
1513  return QgsGeometryEditUtils::deleteRing( d->geometry, ringNum, partNum );
1514 }
1515 
1516 bool QgsGeometry::deletePart( int partNum )
1517 {
1518  if ( !d->geometry )
1519  {
1520  return false;
1521  }
1522 
1523  if ( !isMultipart() && partNum < 1 )
1524  {
1525  setGeometry( nullptr );
1526  return true;
1527  }
1528 
1529  detach( true );
1530  bool ok = QgsGeometryEditUtils::deletePart( d->geometry, partNum );
1531  removeWkbGeos();
1532  return ok;
1533 }
1534 
1536 {
1537  if ( !d->geometry )
1538  {
1539  return 1;
1540  }
1541 
1542  QgsAbstractGeometryV2* diffGeom = QgsGeometryEditUtils::avoidIntersections( *( d->geometry ), ignoreFeatures );
1543  if ( diffGeom )
1544  {
1545  detach( false );
1546  d->geometry = diffGeom;
1547  removeWkbGeos();
1548  }
1549  return 0;
1550 }
1551 
1553 {
1555 }
1556 
1558 {
1559  if ( !d->geometry )
1560  {
1561  return false;
1562  }
1563 
1564  QgsGeos geos( d->geometry );
1565  return geos.isValid();
1566 }
1567 
1569 {
1570  if ( !d->geometry || !g.d->geometry )
1571  {
1572  return false;
1573  }
1574 
1575  QgsGeos geos( d->geometry );
1576  return geos.isEqual( *( g.d->geometry ) );
1577 }
1578 
1580 {
1581  if ( !d->geometry )
1582  {
1583  return false;
1584  }
1585 
1586  QgsGeos geos( d->geometry );
1587  return geos.isEmpty();
1588 }
1589 
1591 {
1592  QgsGeos geos( nullptr );
1593 
1594  QList<QgsAbstractGeometryV2*> geomV2List;
1595  QList<QgsGeometry*>::const_iterator it = geometryList.constBegin();
1596  for ( ; it != geometryList.constEnd(); ++it )
1597  {
1598  if ( *it )
1599  {
1600  geomV2List.append(( *it )->geometry() );
1601  }
1602  }
1603 
1604  QgsAbstractGeometryV2* geom = geos.combine( geomV2List );
1605  return new QgsGeometry( geom );
1606 }
1607 
1609 {
1611  {
1612  return;
1613  }
1614 
1615  QgsAbstractGeometryV2* straightGeom = d->geometry->segmentize();
1616  detach( false );
1617 
1618  d->geometry = straightGeom;
1619  removeWkbGeos();
1620 }
1621 
1623 {
1624  if ( !d->geometry )
1625  {
1626  return false;
1627  }
1628 
1629  return d->geometry->hasCurvedSegments();
1630 }
1631 
1633 {
1634  if ( !d->geometry )
1635  {
1636  return 1;
1637  }
1638 
1639  detach();
1640  d->geometry->transform( ct );
1641  removeWkbGeos();
1642  return 0;
1643 }
1644 
1646 {
1647  if ( !d->geometry )
1648  {
1649  return 1;
1650  }
1651 
1652  detach();
1653  d->geometry->transform( ct );
1654  removeWkbGeos();
1655  return 0;
1656 }
1657 
1659 {
1660  if ( d->geometry )
1661  {
1662  detach();
1663  d->geometry->transform( mtp.transform() );
1664  }
1665 }
1666 
1667 #if 0
1668 void QgsGeometry::clip( const QgsRectangle& rect )
1669 {
1670  if ( d->geometry )
1671  {
1672  detach();
1673  d->geometry->clip( rect );
1674  removeWkbGeos();
1675  }
1676 }
1677 #endif
1678 
1679 void QgsGeometry::draw( QPainter& p ) const
1680 {
1681  if ( d->geometry )
1682  {
1683  d->geometry->draw( p );
1684  }
1685 }
1686 
1688 {
1689  if ( !d->geometry )
1690  {
1691  return false;
1692  }
1693 
1695 
1696  int vertexCount = 0;
1697  for ( int part = 0; part < coords.size(); ++part )
1698  {
1699  const QgsRingSequenceV2 &featureCoords = coords.at( part );
1700  for ( int ring = 0; ring < featureCoords.size(); ++ring )
1701  {
1702  const QgsPointSequenceV2 &ringCoords = featureCoords.at( ring );
1703  for ( int vertex = 0; vertex < ringCoords.size(); ++vertex )
1704  {
1705  if ( vertexCount == nr )
1706  {
1707  id.part = part;
1708  id.ring = ring;
1709  id.vertex = vertex;
1710  return true;
1711  }
1712  ++vertexCount;
1713  }
1714  }
1715  }
1716  return false;
1717 }
1718 
1720 {
1721  if ( !d->geometry )
1722  {
1723  return -1;
1724  }
1725 
1727 
1728  int vertexCount = 0;
1729  for ( int part = 0; part < coords.size(); ++part )
1730  {
1731  const QgsRingSequenceV2 &featureCoords = coords.at( part );
1732  for ( int ring = 0; ring < featureCoords.size(); ++ring )
1733  {
1734  const QgsPointSequenceV2 &ringCoords = featureCoords.at( ring );
1735  for ( int vertex = 0; vertex < ringCoords.size(); ++vertex )
1736  {
1737  if ( vertex == id.vertex && ring == id.ring && part == id.part )
1738  {
1739  return vertexCount;
1740  }
1741  ++vertexCount;
1742  }
1743  }
1744  }
1745  return -1;
1746 }
1747 
1749 {
1750  output.clear();
1752  for ( ; it != input.constEnd(); ++it )
1753  {
1754  output.append( QgsPointV2( it->x(), it->y() ) );
1755  }
1756 }
1757 
1759 {
1760  output.clear();
1762  for ( ; it != input.constEnd(); ++it )
1763  {
1764  output.append( QgsPoint( it->x(), it->y() ) );
1765  }
1766 }
1767 
1768 void QgsGeometry::convertToPolyline( const QgsPointSequenceV2 &input, QgsPolyline& output )
1769 {
1770  output.clear();
1771  output.resize( input.size() );
1772 
1773  for ( int i = 0; i < input.size(); ++i )
1774  {
1775  const QgsPointV2& pt = input.at( i );
1776  output[i].setX( pt.x() );
1777  output[i].setY( pt.y() );
1778  }
1779 }
1780 
1781 void QgsGeometry::convertPolygon( const QgsPolygonV2& input, QgsPolygon& output )
1782 {
1783  output.clear();
1785  if ( coords.size() < 1 )
1786  {
1787  return;
1788  }
1789  const QgsRingSequenceV2 &rings = coords[0];
1790  output.resize( rings.size() );
1791  for ( int i = 0; i < rings.size(); ++i )
1792  {
1793  convertToPolyline( rings[i], output[i] );
1794  }
1795 }
1796 
1797 GEOSContextHandle_t QgsGeometry::getGEOSHandler()
1798 {
1799  return QgsGeos::getGEOSHandler();
1800 }
1801 
1803 {
1804  return new QgsGeometry( new QgsPointV2( point.x(), point.y() ) );
1805 }
1806 
1808 {
1809  if ( polygon.isClosed() )
1810  {
1812  }
1813  else
1814  {
1816  }
1817 }
1818 
1820 {
1821  QgsPolygon result;
1822  result << createPolylineFromQPolygonF( polygon );
1823  return result;
1824 }
1825 
1827 {
1828  QgsPolyline result;
1829  QPolygonF::const_iterator it = polygon.constBegin();
1830  for ( ; it != polygon.constEnd(); ++it )
1831  {
1832  result.append( QgsPoint( *it ) );
1833  }
1834  return result;
1835 }
1836 
1837 bool QgsGeometry::compare( const QgsPolyline &p1, const QgsPolyline &p2, double epsilon )
1838 {
1839  if ( p1.count() != p2.count() )
1840  return false;
1841 
1842  for ( int i = 0; i < p1.count(); ++i )
1843  {
1844  if ( !p1.at( i ).compare( p2.at( i ), epsilon ) )
1845  return false;
1846  }
1847  return true;
1848 }
1849 
1850 bool QgsGeometry::compare( const QgsPolygon &p1, const QgsPolygon &p2, double epsilon )
1851 {
1852  if ( p1.count() != p2.count() )
1853  return false;
1854 
1855  for ( int i = 0; i < p1.count(); ++i )
1856  {
1857  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
1858  return false;
1859  }
1860  return true;
1861 }
1862 
1863 
1864 bool QgsGeometry::compare( const QgsMultiPolygon &p1, const QgsMultiPolygon &p2, double epsilon )
1865 {
1866  if ( p1.count() != p2.count() )
1867  return false;
1868 
1869  for ( int i = 0; i < p1.count(); ++i )
1870  {
1871  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
1872  return false;
1873  }
1874  return true;
1875 }
1876 
1877 QgsGeometry* QgsGeometry::smooth( const unsigned int iterations, const double offset ) const
1878 {
1879  switch ( wkbType() )
1880  {
1881  case QGis::WKBPoint:
1882  case QGis::WKBPoint25D:
1883  case QGis::WKBMultiPoint:
1885  //can't smooth a point based geometry
1886  return new QgsGeometry( *this );
1887 
1888  case QGis::WKBLineString:
1890  {
1891  QgsPolyline line = asPolyline();
1892  return QgsGeometry::fromPolyline( smoothLine( line, iterations, offset ) );
1893  }
1894 
1897  {
1898  QgsMultiPolyline multiline = asMultiPolyline();
1899  QgsMultiPolyline resultMultiline;
1900  QgsMultiPolyline::const_iterator lineIt = multiline.constBegin();
1901  for ( ; lineIt != multiline.constEnd(); ++lineIt )
1902  {
1903  resultMultiline << smoothLine( *lineIt, iterations, offset );
1904  }
1905  return QgsGeometry::fromMultiPolyline( resultMultiline );
1906  }
1907 
1908  case QGis::WKBPolygon:
1909  case QGis::WKBPolygon25D:
1910  {
1911  QgsPolygon poly = asPolygon();
1912  return QgsGeometry::fromPolygon( smoothPolygon( poly, iterations, offset ) );
1913  }
1914 
1915  case QGis::WKBMultiPolygon:
1917  {
1918  QgsMultiPolygon multipoly = asMultiPolygon();
1919  QgsMultiPolygon resultMultipoly;
1920  QgsMultiPolygon::const_iterator polyIt = multipoly.constBegin();
1921  for ( ; polyIt != multipoly.constEnd(); ++polyIt )
1922  {
1923  resultMultipoly << smoothPolygon( *polyIt, iterations, offset );
1924  }
1925  return QgsGeometry::fromMultiPolygon( resultMultipoly );
1926  }
1927 
1928  case QGis::WKBUnknown:
1929  default:
1930  return new QgsGeometry( *this );
1931  }
1932 }
1933 
1934 inline QgsPoint interpolatePointOnLine( const QgsPoint& p1, const QgsPoint& p2, const double offset )
1935 {
1936  double deltaX = p2.x() - p1.x();
1937  double deltaY = p2.y() - p1.y();
1938  return QgsPoint( p1.x() + deltaX * offset, p1.y() + deltaY * offset );
1939 }
1940 
1941 QgsPolyline QgsGeometry::smoothLine( const QgsPolyline& polyline, const unsigned int iterations, const double offset ) const
1942 {
1943  QgsPolyline result = polyline;
1944  for ( unsigned int iteration = 0; iteration < iterations; ++iteration )
1945  {
1946  QgsPolyline outputLine = QgsPolyline();
1947  outputLine.reserve( 2 * ( result.count() - 1 ) );
1948  for ( int i = 0; i < result.count() - 1; i++ )
1949  {
1950  const QgsPoint& p1 = result.at( i );
1951  const QgsPoint& p2 = result.at( i + 1 );
1952  outputLine << ( i == 0 ? result.at( i ) : interpolatePointOnLine( p1, p2, offset ) );
1953  outputLine << ( i == result.count() - 2 ? result.at( i + 1 ) : interpolatePointOnLine( p1, p2, 1.0 - offset ) );
1954  }
1955  result = outputLine;
1956  }
1957  return result;
1958 }
1959 
1960 QgsPolygon QgsGeometry::smoothPolygon( const QgsPolygon& polygon, const unsigned int iterations, const double offset ) const
1961 {
1962  QgsPolygon resultPoly;
1963  QgsPolygon::const_iterator ringIt = polygon.constBegin();
1964  for ( ; ringIt != polygon.constEnd(); ++ringIt )
1965  {
1966  QgsPolyline resultRing = *ringIt;
1967  for ( unsigned int iteration = 0; iteration < iterations; ++iteration )
1968  {
1969  QgsPolyline outputRing = QgsPolyline();
1970  outputRing.reserve( 2 * ( resultRing.count() - 1 ) + 1 );
1971  for ( int i = 0; i < resultRing.count() - 1; ++i )
1972  {
1973  const QgsPoint& p1 = resultRing.at( i );
1974  const QgsPoint& p2 = resultRing.at( i + 1 );
1975  outputRing << interpolatePointOnLine( p1, p2, offset );
1976  outputRing << interpolatePointOnLine( p1, p2, 1.0 - offset );
1977  }
1978  //close polygon
1979  outputRing << outputRing.at( 0 );
1980 
1981  resultRing = outputRing;
1982  }
1983  resultPoly << resultRing;
1984  }
1985  return resultPoly;
1986 }
1987 
1988 QgsGeometry* QgsGeometry::convertToPoint( bool destMultipart ) const
1989 {
1990  switch ( type() )
1991  {
1992  case QGis::Point:
1993  {
1994  bool srcIsMultipart = isMultipart();
1995 
1996  if (( destMultipart && srcIsMultipart ) ||
1997  ( !destMultipart && !srcIsMultipart ) )
1998  {
1999  // return a copy of the same geom
2000  return new QgsGeometry( *this );
2001  }
2002  if ( destMultipart )
2003  {
2004  // layer is multipart => make a multipoint with a single point
2005  return fromMultiPoint( QgsMultiPoint() << asPoint() );
2006  }
2007  else
2008  {
2009  // destination is singlepart => make a single part if possible
2010  QgsMultiPoint multiPoint = asMultiPoint();
2011  if ( multiPoint.count() == 1 )
2012  {
2013  return fromPoint( multiPoint[0] );
2014  }
2015  }
2016  return nullptr;
2017  }
2018 
2019  case QGis::Line:
2020  {
2021  // only possible if destination is multipart
2022  if ( !destMultipart )
2023  return nullptr;
2024 
2025  // input geometry is multipart
2026  if ( isMultipart() )
2027  {
2028  QgsMultiPolyline multiLine = asMultiPolyline();
2029  QgsMultiPoint multiPoint;
2030  for ( QgsMultiPolyline::const_iterator multiLineIt = multiLine.constBegin(); multiLineIt != multiLine.constEnd(); ++multiLineIt )
2031  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2032  multiPoint << *lineIt;
2033  return fromMultiPoint( multiPoint );
2034  }
2035  // input geometry is not multipart: copy directly the line into a multipoint
2036  else
2037  {
2038  QgsPolyline line = asPolyline();
2039  if ( !line.isEmpty() )
2040  return fromMultiPoint( line );
2041  }
2042  return nullptr;
2043  }
2044 
2045  case QGis::Polygon:
2046  {
2047  // can only transform if destination is multipoint
2048  if ( !destMultipart )
2049  return nullptr;
2050 
2051  // input geometry is multipart: make a multipoint from multipolygon
2052  if ( isMultipart() )
2053  {
2054  QgsMultiPolygon multiPolygon = asMultiPolygon();
2055  QgsMultiPoint multiPoint;
2056  for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
2057  for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
2058  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2059  multiPoint << *lineIt;
2060  return fromMultiPoint( multiPoint );
2061  }
2062  // input geometry is not multipart: make a multipoint from polygon
2063  else
2064  {
2065  QgsPolygon polygon = asPolygon();
2066  QgsMultiPoint multiPoint;
2067  for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
2068  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2069  multiPoint << *lineIt;
2070  return fromMultiPoint( multiPoint );
2071  }
2072  }
2073 
2074  default:
2075  return nullptr;
2076  }
2077 }
2078 
2079 QgsGeometry* QgsGeometry::convertToLine( bool destMultipart ) const
2080 {
2081  switch ( type() )
2082  {
2083  case QGis::Point:
2084  {
2085  if ( !isMultipart() )
2086  return nullptr;
2087 
2088  QgsMultiPoint multiPoint = asMultiPoint();
2089  if ( multiPoint.count() < 2 )
2090  return nullptr;
2091 
2092  if ( destMultipart )
2093  return fromMultiPolyline( QgsMultiPolyline() << multiPoint );
2094  else
2095  return fromPolyline( multiPoint );
2096  }
2097 
2098  case QGis::Line:
2099  {
2100  bool srcIsMultipart = isMultipart();
2101 
2102  if (( destMultipart && srcIsMultipart ) ||
2103  ( !destMultipart && ! srcIsMultipart ) )
2104  {
2105  // return a copy of the same geom
2106  return new QgsGeometry( *this );
2107  }
2108  if ( destMultipart )
2109  {
2110  // destination is multipart => makes a multipoint with a single line
2111  QgsPolyline line = asPolyline();
2112  if ( !line.isEmpty() )
2113  return fromMultiPolyline( QgsMultiPolyline() << line );
2114  }
2115  else
2116  {
2117  // destination is singlepart => make a single part if possible
2118  QgsMultiPolyline multiLine = asMultiPolyline();
2119  if ( multiLine.count() == 1 )
2120  return fromPolyline( multiLine[0] );
2121  }
2122  return nullptr;
2123  }
2124 
2125  case QGis::Polygon:
2126  {
2127  // input geometry is multipolygon
2128  if ( isMultipart() )
2129  {
2130  QgsMultiPolygon multiPolygon = asMultiPolygon();
2131  QgsMultiPolyline multiLine;
2132  for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
2133  for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
2134  multiLine << *multiLineIt;
2135 
2136  if ( destMultipart )
2137  {
2138  // destination is multipart
2139  return fromMultiPolyline( multiLine );
2140  }
2141  else if ( multiLine.count() == 1 )
2142  {
2143  // destination is singlepart => make a single part if possible
2144  return fromPolyline( multiLine[0] );
2145  }
2146  }
2147  // input geometry is single polygon
2148  else
2149  {
2150  QgsPolygon polygon = asPolygon();
2151  // if polygon has rings
2152  if ( polygon.count() > 1 )
2153  {
2154  // cannot fit a polygon with rings in a single line layer
2155  // TODO: would it be better to remove rings?
2156  if ( destMultipart )
2157  {
2158  QgsPolygon polygon = asPolygon();
2159  QgsMultiPolyline multiLine;
2160  for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
2161  multiLine << *multiLineIt;
2162  return fromMultiPolyline( multiLine );
2163  }
2164  }
2165  // no rings
2166  else if ( polygon.count() == 1 )
2167  {
2168  if ( destMultipart )
2169  {
2170  return fromMultiPolyline( polygon );
2171  }
2172  else
2173  {
2174  return fromPolyline( polygon[0] );
2175  }
2176  }
2177  }
2178  return nullptr;
2179  }
2180 
2181  default:
2182  return nullptr;
2183  }
2184 }
2185 
2186 QgsGeometry* QgsGeometry::convertToPolygon( bool destMultipart ) const
2187 {
2188  switch ( type() )
2189  {
2190  case QGis::Point:
2191  {
2192  if ( !isMultipart() )
2193  return nullptr;
2194 
2195  QgsMultiPoint multiPoint = asMultiPoint();
2196  if ( multiPoint.count() < 3 )
2197  return nullptr;
2198 
2199  if ( multiPoint.last() != multiPoint.first() )
2200  multiPoint << multiPoint.first();
2201 
2202  QgsPolygon polygon = QgsPolygon() << multiPoint;
2203  if ( destMultipart )
2204  return fromMultiPolygon( QgsMultiPolygon() << polygon );
2205  else
2206  return fromPolygon( polygon );
2207  }
2208 
2209  case QGis::Line:
2210  {
2211  // input geometry is multiline
2212  if ( isMultipart() )
2213  {
2214  QgsMultiPolyline multiLine = asMultiPolyline();
2215  QgsMultiPolygon multiPolygon;
2216  for ( QgsMultiPolyline::iterator multiLineIt = multiLine.begin(); multiLineIt != multiLine.end(); ++multiLineIt )
2217  {
2218  // do not create polygon for a 1 segment line
2219  if (( *multiLineIt ).count() < 3 )
2220  return nullptr;
2221  if (( *multiLineIt ).count() == 3 && ( *multiLineIt ).first() == ( *multiLineIt ).last() )
2222  return nullptr;
2223 
2224  // add closing node
2225  if (( *multiLineIt ).first() != ( *multiLineIt ).last() )
2226  *multiLineIt << ( *multiLineIt ).first();
2227  multiPolygon << ( QgsPolygon() << *multiLineIt );
2228  }
2229  // check that polygons were inserted
2230  if ( !multiPolygon.isEmpty() )
2231  {
2232  if ( destMultipart )
2233  {
2234  return fromMultiPolygon( multiPolygon );
2235  }
2236  else if ( multiPolygon.count() == 1 )
2237  {
2238  // destination is singlepart => make a single part if possible
2239  return fromPolygon( multiPolygon[0] );
2240  }
2241  }
2242  }
2243  // input geometry is single line
2244  else
2245  {
2246  QgsPolyline line = asPolyline();
2247 
2248  // do not create polygon for a 1 segment line
2249  if ( line.count() < 3 )
2250  return nullptr;
2251  if ( line.count() == 3 && line.first() == line.last() )
2252  return nullptr;
2253 
2254  // add closing node
2255  if ( line.first() != line.last() )
2256  line << line.first();
2257 
2258  // destination is multipart
2259  if ( destMultipart )
2260  {
2261  return fromMultiPolygon( QgsMultiPolygon() << ( QgsPolygon() << line ) );
2262  }
2263  else
2264  {
2265  return fromPolygon( QgsPolygon() << line );
2266  }
2267  }
2268  return nullptr;
2269  }
2270 
2271  case QGis::Polygon:
2272  {
2273  bool srcIsMultipart = isMultipart();
2274 
2275  if (( destMultipart && srcIsMultipart ) ||
2276  ( !destMultipart && ! srcIsMultipart ) )
2277  {
2278  // return a copy of the same geom
2279  return new QgsGeometry( *this );
2280  }
2281  if ( destMultipart )
2282  {
2283  // destination is multipart => makes a multipoint with a single polygon
2284  QgsPolygon polygon = asPolygon();
2285  if ( !polygon.isEmpty() )
2286  return fromMultiPolygon( QgsMultiPolygon() << polygon );
2287  }
2288  else
2289  {
2290  QgsMultiPolygon multiPolygon = asMultiPolygon();
2291  if ( multiPolygon.count() == 1 )
2292  {
2293  // destination is singlepart => make a single part if possible
2294  return fromPolygon( multiPolygon[0] );
2295  }
2296  }
2297  return nullptr;
2298  }
2299 
2300  default:
2301  return nullptr;
2302  }
2303 }
2304 
2306 {
2307  return new QgsGeos( geometry );
2308 }
2309 
2311 {
2312  QByteArray byteArray = QByteArray::fromRawData( reinterpret_cast< const char * >( geometry.asWkb() ), geometry.wkbSize() ); // does not copy data and does not take ownership
2313  out << byteArray;
2314  return out;
2315 }
2316 
2318 {
2319  QByteArray byteArray;
2320  in >> byteArray;
2321  if ( byteArray.isEmpty() )
2322  {
2323  geometry.setGeometry( nullptr );
2324  return in;
2325  }
2326 
2327  char *data = new char[byteArray.size()];
2328  memcpy( data, byteArray.data(), byteArray.size() );
2329  geometry.fromWkb( reinterpret_cast< unsigned char* >( data ), byteArray.size() );
2330  return in;
2331 }
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:378
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:111
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:188
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:1453
void points(QgsPointSequenceV2 &pt) const override
Returns a list of points within the curve.
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:345
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:144
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:476
QgsGeometry closestPoint(const QgsGeometry &other, QString *errorMsg=nullptr) const
Returns the closest point on the geometry to the other geometry.
Definition: qgsgeos.cpp:1776
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.
Abstract base class for all geometries.
double length(QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:362
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:862
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:57
QgsGeometry()
Constructor.
Definition: qgsgeometry.cpp:65
QgsAbstractGeometryV2 * symDifference(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:217
bool isValid(QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1419
T & first()
Multi point geometry collection.
QgsAbstractGeometryV2 * simplify(double tolerance, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1301
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:128
bool deleteRing(int ringNum, int partNum=0)
Delete a ring in polygon or multipolygon.
static GEOSContextHandle_t getGEOSHandler()
Definition: qgsgeos.cpp:2285
int size() const
QgsMultiPolygon asMultiPolygon() const
Return contents of the geometry as a multi polygon if wkbType is WKBMultiPolygon, otherwise an empty ...
QgsAbstractGeometryV2 * interpolate(double distance, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1316
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:262
bool deletePart(int partNum)
Delete part identified by the part number.
bool contains(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:272
bool isGeosEmpty() const
Check if the geometry is empty using GEOS.
bool intersects(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:247
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.
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:178
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
virtual QgsPolygonV2 * toPolygon() const
static void adjacentVertices(const QgsAbstractGeometryV2 &geom, QgsVertexId atVertex, QgsVertexId &beforeVertex, QgsVertexId &afterVertex)
Returns vertices adjacent to a specified vertex within a geometry.
virtual void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform)=0
Transforms the geometry using a coordinate transform.
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:277
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:31
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:65
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:252
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:573
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:1051
void setX(double x)
Sets the x value of the point.
Definition: qgspoint.h:105
virtual QgsRectangle boundingBox() const =0
Returns the minimal bounding box for the geometry.
virtual QString geometryType() const =0
Returns a unique string representing the geometry type.
void setY(double y)
Sets the y value of the point.
Definition: qgspoint.h:113
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
virtual QgsAbstractGeometryV2 * segmentize() const
Returns a version of the geometry without curves.
bool crosses(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:257
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
virtual QgsLineStringV2 * curveToLine() const =0
Returns a new line string geometry corresponding to a segmentized approximation of the curve...
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:1668
bool centroid(QgsPointV2 &pt, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1331
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:1811
virtual bool addGeometry(QgsAbstractGeometryV2 *g)
Adds a geometry and takes ownership.
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:1433
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.
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:1373
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:136
double distance(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:222
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 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:267
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:183
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.
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()
QgsAbstractGeometryV2 * offsetCurve(double distance, int segments, int joinStyle, double mitreLimit, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1652
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.
double area() const
Returns the area of the geometry using GEOS.
QgsAbstractGeometryV2 * convexHull(QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1402
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:1263
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:121