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