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