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