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