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