QGIS API Documentation  2.15.0-Master (94d88e6)
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
452  if ( d->geometry->geometryType() == "MultiPoint" )
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
490  if ( d->geometry->geometryType() == "MultiPoint" )
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 {
1011  if ( !d->geometry || d->geometry->geometryType() != "Point" )
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 = ( d->geometry->geometryType() == "CompoundCurve" || d->geometry->geometryType() == "CircularString" );
1033  QgsLineStringV2* line = nullptr;
1034  if ( doSegmentation )
1035  {
1036  QgsCurveV2* curve = dynamic_cast<QgsCurveV2*>( d->geometry );
1037  if ( !curve )
1038  {
1039  return polyLine;
1040  }
1041  line = curve->curveToLine();
1042  }
1043  else
1044  {
1045  line = dynamic_cast<QgsLineStringV2*>( d->geometry );
1046  if ( !line )
1047  {
1048  return polyLine;
1049  }
1050  }
1051 
1052  int nVertices = line->numPoints();
1053  polyLine.resize( nVertices );
1054  for ( int i = 0; i < nVertices; ++i )
1055  {
1056  QgsPointV2 pt = line->pointN( i );
1057  polyLine[i].setX( pt.x() );
1058  polyLine[i].setY( pt.y() );
1059  }
1060 
1061  if ( doSegmentation )
1062  {
1063  delete line;
1064  }
1065 
1066  return polyLine;
1067 }
1068 
1070 {
1071  if ( !d->geometry )
1072  return QgsPolygon();
1073 
1074  bool doSegmentation = ( d->geometry->geometryType() == "CurvePolygon" );
1075 
1076  QgsPolygonV2* p = nullptr;
1077  if ( doSegmentation )
1078  {
1079  QgsCurvePolygonV2* curvePoly = dynamic_cast<QgsCurvePolygonV2*>( d->geometry );
1080  if ( !curvePoly )
1081  {
1082  return QgsPolygon();
1083  }
1084  p = curvePoly->toPolygon();
1085  }
1086  else
1087  {
1088  p = dynamic_cast<QgsPolygonV2*>( d->geometry );
1089  }
1090 
1091  if ( !p )
1092  {
1093  return QgsPolygon();
1094  }
1095 
1096  QgsPolygon polygon;
1097  convertPolygon( *p, polygon );
1098 
1099  if ( doSegmentation )
1100  {
1101  delete p;
1102  }
1103  return polygon;
1104 }
1105 
1107 {
1108  if ( !d->geometry || d->geometry->geometryType() != "MultiPoint" )
1109  {
1110  return QgsMultiPoint();
1111  }
1112 
1113  const QgsMultiPointV2* mp = dynamic_cast<QgsMultiPointV2*>( d->geometry );
1114  if ( !mp )
1115  {
1116  return QgsMultiPoint();
1117  }
1118 
1119  int nPoints = mp->numGeometries();
1120  QgsMultiPoint multiPoint( nPoints );
1121  for ( int i = 0; i < nPoints; ++i )
1122  {
1123  const QgsPointV2* pt = static_cast<const QgsPointV2*>( mp->geometryN( i ) );
1124  multiPoint[i].setX( pt->x() );
1125  multiPoint[i].setY( pt->y() );
1126  }
1127  return multiPoint;
1128 }
1129 
1131 {
1132  if ( !d->geometry )
1133  {
1134  return QgsMultiPolyline();
1135  }
1136 
1137  QgsGeometryCollectionV2* geomCollection = dynamic_cast<QgsGeometryCollectionV2*>( d->geometry );
1138  if ( !geomCollection )
1139  {
1140  return QgsMultiPolyline();
1141  }
1142 
1143  int nLines = geomCollection->numGeometries();
1144  if ( nLines < 1 )
1145  {
1146  return QgsMultiPolyline();
1147  }
1148 
1149  QgsMultiPolyline mpl;
1150  for ( int i = 0; i < nLines; ++i )
1151  {
1152  bool deleteLine = false;
1153  const QgsLineStringV2* line = dynamic_cast<const QgsLineStringV2*>( geomCollection->geometryN( i ) );
1154  if ( !line )
1155  {
1156  const QgsCurveV2* curve = dynamic_cast<const QgsCurveV2*>( geomCollection->geometryN( i ) );
1157  if ( !curve )
1158  {
1159  continue;
1160  }
1161  deleteLine = true;
1162  line = curve->curveToLine();
1163  }
1164 
1165  QgsPointSequenceV2 lineCoords;
1166  line->points( lineCoords );
1167  QgsPolyline polyLine;
1168  convertToPolyline( lineCoords, polyLine );
1169  mpl.append( polyLine );
1170 
1171  if ( deleteLine )
1172  {
1173  delete line;
1174  }
1175  }
1176  return mpl;
1177 }
1178 
1180 {
1181  if ( !d->geometry )
1182  {
1183  return QgsMultiPolygon();
1184  }
1185 
1186  QgsGeometryCollectionV2* geomCollection = dynamic_cast<QgsGeometryCollectionV2*>( d->geometry );
1187  if ( !geomCollection )
1188  {
1189  return QgsMultiPolygon();
1190  }
1191 
1192  int nPolygons = geomCollection->numGeometries();
1193  if ( nPolygons < 1 )
1194  {
1195  return QgsMultiPolygon();
1196  }
1197 
1198  QgsMultiPolygon mp;
1199  for ( int i = 0; i < nPolygons; ++i )
1200  {
1201  const QgsPolygonV2* polygon = dynamic_cast<const QgsPolygonV2*>( geomCollection->geometryN( i ) );
1202  if ( !polygon )
1203  {
1204  const QgsCurvePolygonV2* cPolygon = dynamic_cast<const QgsCurvePolygonV2*>( geomCollection->geometryN( i ) );
1205  if ( cPolygon )
1206  {
1207  polygon = cPolygon->toPolygon();
1208  }
1209  else
1210  {
1211  continue;
1212  }
1213  }
1214 
1215  QgsPolygon poly;
1216  convertPolygon( *polygon, poly );
1217  mp.append( poly );
1218  }
1219  return mp;
1220 }
1221 
1222 double QgsGeometry::area() const
1223 {
1224  if ( !d->geometry )
1225  {
1226  return -1.0;
1227  }
1228  QgsGeos g( d->geometry );
1229 
1230 #if 0
1231  //debug: compare geos area with calculation in QGIS
1232  double geosArea = g.area();
1233  double qgisArea = 0;
1234  QgsSurfaceV2* surface = dynamic_cast<QgsSurfaceV2*>( d->geometry );
1235  if ( surface )
1236  {
1237  qgisArea = surface->area();
1238  }
1239 #endif
1240 
1241  return g.area();
1242 }
1243 
1244 double QgsGeometry::length() const
1245 {
1246  if ( !d->geometry )
1247  {
1248  return -1.0;
1249  }
1250  QgsGeos g( d->geometry );
1251  return g.length();
1252 }
1253 
1254 double QgsGeometry::distance( const QgsGeometry& geom ) const
1255 {
1256  if ( !d->geometry || !geom.d->geometry )
1257  {
1258  return -1.0;
1259  }
1260 
1261  QgsGeos g( d->geometry );
1262  return g.distance( *( geom.d->geometry ) );
1263 }
1264 
1265 QgsGeometry* QgsGeometry::buffer( double distance, int segments ) const
1266 {
1267  if ( !d->geometry )
1268  {
1269  return nullptr;
1270  }
1271 
1272  QgsGeos g( d->geometry );
1273  QgsAbstractGeometryV2* geom = g.buffer( distance, segments );
1274  if ( !geom )
1275  {
1276  return nullptr;
1277  }
1278  return new QgsGeometry( geom );
1279 }
1280 
1281 QgsGeometry* QgsGeometry::buffer( double distance, int segments, int endCapStyle, int joinStyle, double mitreLimit ) const
1282 {
1283  if ( !d->geometry )
1284  {
1285  return nullptr;
1286  }
1287 
1288  QgsGeos g( d->geometry );
1289  QgsAbstractGeometryV2* geom = g.buffer( distance, segments, endCapStyle, joinStyle, mitreLimit );
1290  if ( !geom )
1291  {
1292  return nullptr;
1293  }
1294  return new QgsGeometry( geom );
1295 }
1296 
1297 QgsGeometry* QgsGeometry::offsetCurve( double distance, int segments, int joinStyle, double mitreLimit ) const
1298 {
1299  if ( !d->geometry )
1300  {
1301  return nullptr;
1302  }
1303 
1304  QgsGeos geos( d->geometry );
1305  QgsAbstractGeometryV2* offsetGeom = geos.offsetCurve( distance, segments, joinStyle, mitreLimit );
1306  if ( !offsetGeom )
1307  {
1308  return nullptr;
1309  }
1310  return new QgsGeometry( offsetGeom );
1311 }
1312 
1313 QgsGeometry* QgsGeometry::simplify( double tolerance ) const
1314 {
1315  if ( !d->geometry )
1316  {
1317  return nullptr;
1318  }
1319 
1320  QgsGeos geos( d->geometry );
1321  QgsAbstractGeometryV2* simplifiedGeom = geos.simplify( tolerance );
1322  if ( !simplifiedGeom )
1323  {
1324  return nullptr;
1325  }
1326  return new QgsGeometry( simplifiedGeom );
1327 }
1328 
1330 {
1331  if ( !d->geometry )
1332  {
1333  return nullptr;
1334  }
1335 
1336  QgsGeos geos( d->geometry );
1338  bool ok = geos.centroid( centroid );
1339  if ( !ok )
1340  {
1341  return nullptr;
1342  }
1343  return new QgsGeometry( centroid.clone() );
1344 }
1345 
1347 {
1348  if ( !d->geometry )
1349  {
1350  return nullptr;
1351  }
1352 
1353  QgsGeos geos( d->geometry );
1354  QgsPointV2 pt;
1355  bool ok = geos.pointOnSurface( pt );
1356  if ( !ok )
1357  {
1358  return nullptr;
1359  }
1360  return new QgsGeometry( pt.clone() );
1361 }
1362 
1364 {
1365  if ( !d->geometry )
1366  {
1367  return nullptr;
1368  }
1369  QgsGeos geos( d->geometry );
1370  QgsAbstractGeometryV2* cHull = geos.convexHull();
1371  if ( !cHull )
1372  {
1373  return nullptr;
1374  }
1375  return new QgsGeometry( cHull );
1376 }
1377 
1379 {
1380  if ( !d->geometry )
1381  {
1382  return nullptr;
1383  }
1384  QgsGeos geos( d->geometry );
1385  QgsAbstractGeometryV2* result = geos.interpolate( distance );
1386  if ( !result )
1387  {
1388  return nullptr;
1389  }
1390  return new QgsGeometry( result );
1391 }
1392 
1394 {
1395  if ( !d->geometry || !geometry->d->geometry )
1396  {
1397  return nullptr;
1398  }
1399 
1400  QgsGeos geos( d->geometry );
1401 
1402  QgsAbstractGeometryV2* resultGeom = geos.intersection( *( geometry->d->geometry ) );
1403  return new QgsGeometry( resultGeom );
1404 }
1405 
1407 {
1408  if ( !d->geometry || !geometry->d->geometry )
1409  {
1410  return nullptr;
1411  }
1412 
1413  QgsGeos geos( d->geometry );
1414 
1415  QgsAbstractGeometryV2* resultGeom = geos.combine( *( geometry->d->geometry ) );
1416  if ( !resultGeom )
1417  {
1418  return nullptr;
1419  }
1420  return new QgsGeometry( resultGeom );
1421 }
1422 
1424 {
1425  if ( !d->geometry || !geometry->d->geometry )
1426  {
1427  return nullptr;
1428  }
1429 
1430  QgsGeos geos( d->geometry );
1431 
1432  QgsAbstractGeometryV2* resultGeom = geos.difference( *( geometry->d->geometry ) );
1433  if ( !resultGeom )
1434  {
1435  return nullptr;
1436  }
1437  return new QgsGeometry( resultGeom );
1438 }
1439 
1441 {
1442  if ( !d->geometry || !geometry->d->geometry )
1443  {
1444  return nullptr;
1445  }
1446 
1447  QgsGeos geos( d->geometry );
1448 
1449  QgsAbstractGeometryV2* resultGeom = geos.symDifference( *( geometry->d->geometry ) );
1450  if ( !resultGeom )
1451  {
1452  return nullptr;
1453  }
1454  return new QgsGeometry( resultGeom );
1455 }
1456 
1457 QgsGeometry QgsGeometry::extrude( double x, double y )
1458 {
1459  QgsInternalGeometryEngine engine( *this );
1460 
1461  return engine.extrude( x, y );
1462 }
1463 
1465 {
1466  QList<QgsGeometry*> geometryList;
1467  if ( !d->geometry )
1468  {
1469  return geometryList;
1470  }
1471 
1472  QgsGeometryCollectionV2* gc = dynamic_cast<QgsGeometryCollectionV2*>( d->geometry );
1473  if ( gc )
1474  {
1475  int numGeom = gc->numGeometries();
1476  geometryList.reserve( numGeom );
1477  for ( int i = 0; i < numGeom; ++i )
1478  {
1479  geometryList.append( new QgsGeometry( gc->geometryN( i )->clone() ) );
1480  }
1481  }
1482  else //a singlepart geometry
1483  {
1484  geometryList.append( new QgsGeometry( d->geometry->clone() ) );
1485  }
1486 
1487  return geometryList;
1488 }
1489 
1491 {
1492  QgsPoint point = asPoint();
1493  return point.toQPointF();
1494 }
1495 
1497 {
1498  QPolygonF result;
1499  QgsPolyline polyline;
1501  if ( type == QGis::WKBLineString || type == QGis::WKBLineString25D )
1502  {
1503  polyline = asPolyline();
1504  }
1505  else if ( type == QGis::WKBPolygon || type == QGis::WKBPolygon25D )
1506  {
1507  QgsPolygon polygon = asPolygon();
1508  if ( polygon.size() < 1 )
1509  return result;
1510  polyline = polygon.at( 0 );
1511  }
1512  else
1513  {
1514  return result;
1515  }
1516 
1517  QgsPolyline::const_iterator lineIt = polyline.constBegin();
1518  for ( ; lineIt != polyline.constEnd(); ++lineIt )
1519  {
1520  result << lineIt->toQPointF();
1521  }
1522  return result;
1523 }
1524 
1525 bool QgsGeometry::deleteRing( int ringNum, int partNum )
1526 {
1527  if ( !d->geometry )
1528  {
1529  return false;
1530  }
1531 
1532  detach( true );
1533  bool ok = QgsGeometryEditUtils::deleteRing( d->geometry, ringNum, partNum );
1534  removeWkbGeos();
1535  return ok;
1536 }
1537 
1538 bool QgsGeometry::deletePart( int partNum )
1539 {
1540  if ( !d->geometry )
1541  {
1542  return false;
1543  }
1544 
1545  if ( !isMultipart() && partNum < 1 )
1546  {
1547  setGeometry( nullptr );
1548  return true;
1549  }
1550 
1551  detach( true );
1552  bool ok = QgsGeometryEditUtils::deletePart( d->geometry, partNum );
1553  removeWkbGeos();
1554  return ok;
1555 }
1556 
1558 {
1559  if ( !d->geometry )
1560  {
1561  return 1;
1562  }
1563 
1564  QgsAbstractGeometryV2* diffGeom = QgsGeometryEditUtils::avoidIntersections( *( d->geometry ), ignoreFeatures );
1565  if ( diffGeom )
1566  {
1567  detach( false );
1568  d->geometry = diffGeom;
1569  removeWkbGeos();
1570  }
1571  return 0;
1572 }
1573 
1575 {
1577 }
1578 
1580 {
1581  if ( !d->geometry )
1582  {
1583  return false;
1584  }
1585 
1586  QgsGeos geos( d->geometry );
1587  return geos.isValid();
1588 }
1589 
1591 {
1592  if ( !d->geometry || !g.d->geometry )
1593  {
1594  return false;
1595  }
1596 
1597  QgsGeos geos( d->geometry );
1598  return geos.isEqual( *( g.d->geometry ) );
1599 }
1600 
1602 {
1603  if ( !d->geometry )
1604  {
1605  return false;
1606  }
1607 
1608  QgsGeos geos( d->geometry );
1609  return geos.isEmpty();
1610 }
1611 
1613 {
1614  QgsGeos geos( nullptr );
1615 
1616  QList<QgsAbstractGeometryV2*> geomV2List;
1617  QList<QgsGeometry*>::const_iterator it = geometryList.constBegin();
1618  for ( ; it != geometryList.constEnd(); ++it )
1619  {
1620  if ( *it )
1621  {
1622  geomV2List.append(( *it )->geometry() );
1623  }
1624  }
1625 
1626  QgsAbstractGeometryV2* geom = geos.combine( geomV2List );
1627  return new QgsGeometry( geom );
1628 }
1629 
1631 {
1633  {
1634  return;
1635  }
1636 
1637  QgsAbstractGeometryV2* straightGeom = d->geometry->segmentize();
1638  detach( false );
1639 
1640  d->geometry = straightGeom;
1641  removeWkbGeos();
1642 }
1643 
1645 {
1646  if ( !d->geometry )
1647  {
1648  return false;
1649  }
1650 
1651  return d->geometry->hasCurvedSegments();
1652 }
1653 
1655 {
1656  if ( !d->geometry )
1657  {
1658  return 1;
1659  }
1660 
1661  detach();
1662  d->geometry->transform( ct );
1663  removeWkbGeos();
1664  return 0;
1665 }
1666 
1668 {
1669  if ( !d->geometry )
1670  {
1671  return 1;
1672  }
1673 
1674  detach();
1675  d->geometry->transform( ct );
1676  removeWkbGeos();
1677  return 0;
1678 }
1679 
1681 {
1682  if ( d->geometry )
1683  {
1684  detach();
1685  d->geometry->transform( mtp.transform() );
1686  removeWkbGeos();
1687  }
1688 }
1689 
1690 #if 0
1691 void QgsGeometry::clip( const QgsRectangle& rect )
1692 {
1693  if ( d->geometry )
1694  {
1695  detach();
1696  d->geometry->clip( rect );
1697  removeWkbGeos();
1698  }
1699 }
1700 #endif
1701 
1702 void QgsGeometry::draw( QPainter& p ) const
1703 {
1704  if ( d->geometry )
1705  {
1706  d->geometry->draw( p );
1707  }
1708 }
1709 
1711 {
1712  if ( !d->geometry )
1713  {
1714  return false;
1715  }
1716 
1718 
1719  int vertexCount = 0;
1720  for ( int part = 0; part < coords.size(); ++part )
1721  {
1722  const QgsRingSequenceV2 &featureCoords = coords.at( part );
1723  for ( int ring = 0; ring < featureCoords.size(); ++ring )
1724  {
1725  const QgsPointSequenceV2 &ringCoords = featureCoords.at( ring );
1726  for ( int vertex = 0; vertex < ringCoords.size(); ++vertex )
1727  {
1728  if ( vertexCount == nr )
1729  {
1730  id.part = part;
1731  id.ring = ring;
1732  id.vertex = vertex;
1733  return true;
1734  }
1735  ++vertexCount;
1736  }
1737  }
1738  }
1739  return false;
1740 }
1741 
1743 {
1744  if ( !d->geometry )
1745  {
1746  return -1;
1747  }
1748 
1750 
1751  int vertexCount = 0;
1752  for ( int part = 0; part < coords.size(); ++part )
1753  {
1754  const QgsRingSequenceV2 &featureCoords = coords.at( part );
1755  for ( int ring = 0; ring < featureCoords.size(); ++ring )
1756  {
1757  const QgsPointSequenceV2 &ringCoords = featureCoords.at( ring );
1758  for ( int vertex = 0; vertex < ringCoords.size(); ++vertex )
1759  {
1760  if ( vertex == id.vertex && ring == id.ring && part == id.part )
1761  {
1762  return vertexCount;
1763  }
1764  ++vertexCount;
1765  }
1766  }
1767  }
1768  return -1;
1769 }
1770 
1772 {
1773  output.clear();
1775  for ( ; it != input.constEnd(); ++it )
1776  {
1777  output.append( QgsPointV2( it->x(), it->y() ) );
1778  }
1779 }
1780 
1782 {
1783  output.clear();
1785  for ( ; it != input.constEnd(); ++it )
1786  {
1787  output.append( QgsPoint( it->x(), it->y() ) );
1788  }
1789 }
1790 
1791 void QgsGeometry::convertToPolyline( const QgsPointSequenceV2 &input, QgsPolyline& output )
1792 {
1793  output.clear();
1794  output.resize( input.size() );
1795 
1796  for ( int i = 0; i < input.size(); ++i )
1797  {
1798  const QgsPointV2& pt = input.at( i );
1799  output[i].setX( pt.x() );
1800  output[i].setY( pt.y() );
1801  }
1802 }
1803 
1804 void QgsGeometry::convertPolygon( const QgsPolygonV2& input, QgsPolygon& output )
1805 {
1806  output.clear();
1808  if ( coords.size() < 1 )
1809  {
1810  return;
1811  }
1812  const QgsRingSequenceV2 &rings = coords[0];
1813  output.resize( rings.size() );
1814  for ( int i = 0; i < rings.size(); ++i )
1815  {
1816  convertToPolyline( rings[i], output[i] );
1817  }
1818 }
1819 
1820 GEOSContextHandle_t QgsGeometry::getGEOSHandler()
1821 {
1822  return QgsGeos::getGEOSHandler();
1823 }
1824 
1826 {
1827  return new QgsGeometry( new QgsPointV2( point.x(), point.y() ) );
1828 }
1829 
1831 {
1832  if ( polygon.isClosed() )
1833  {
1835  }
1836  else
1837  {
1839  }
1840 }
1841 
1843 {
1844  QgsPolygon result;
1845  result << createPolylineFromQPolygonF( polygon );
1846  return result;
1847 }
1848 
1850 {
1851  QgsPolyline result;
1852  QPolygonF::const_iterator it = polygon.constBegin();
1853  for ( ; it != polygon.constEnd(); ++it )
1854  {
1855  result.append( QgsPoint( *it ) );
1856  }
1857  return result;
1858 }
1859 
1860 bool QgsGeometry::compare( const QgsPolyline &p1, const QgsPolyline &p2, double epsilon )
1861 {
1862  if ( p1.count() != p2.count() )
1863  return false;
1864 
1865  for ( int i = 0; i < p1.count(); ++i )
1866  {
1867  if ( !p1.at( i ).compare( p2.at( i ), epsilon ) )
1868  return false;
1869  }
1870  return true;
1871 }
1872 
1873 bool QgsGeometry::compare( const QgsPolygon &p1, const QgsPolygon &p2, double epsilon )
1874 {
1875  if ( p1.count() != p2.count() )
1876  return false;
1877 
1878  for ( int i = 0; i < p1.count(); ++i )
1879  {
1880  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
1881  return false;
1882  }
1883  return true;
1884 }
1885 
1886 
1887 bool QgsGeometry::compare( const QgsMultiPolygon &p1, const QgsMultiPolygon &p2, double epsilon )
1888 {
1889  if ( p1.count() != p2.count() )
1890  return false;
1891 
1892  for ( int i = 0; i < p1.count(); ++i )
1893  {
1894  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
1895  return false;
1896  }
1897  return true;
1898 }
1899 
1900 QgsGeometry* QgsGeometry::smooth( const unsigned int iterations, const double offset ) const
1901 {
1902  switch ( wkbType() )
1903  {
1904  case QGis::WKBPoint:
1905  case QGis::WKBPoint25D:
1906  case QGis::WKBMultiPoint:
1908  //can't smooth a point based geometry
1909  return new QgsGeometry( *this );
1910 
1911  case QGis::WKBLineString:
1913  {
1914  QgsPolyline line = asPolyline();
1915  return QgsGeometry::fromPolyline( smoothLine( line, iterations, offset ) );
1916  }
1917 
1920  {
1921  QgsMultiPolyline multiline = asMultiPolyline();
1922  QgsMultiPolyline resultMultiline;
1923  QgsMultiPolyline::const_iterator lineIt = multiline.constBegin();
1924  for ( ; lineIt != multiline.constEnd(); ++lineIt )
1925  {
1926  resultMultiline << smoothLine( *lineIt, iterations, offset );
1927  }
1928  return QgsGeometry::fromMultiPolyline( resultMultiline );
1929  }
1930 
1931  case QGis::WKBPolygon:
1932  case QGis::WKBPolygon25D:
1933  {
1934  QgsPolygon poly = asPolygon();
1935  return QgsGeometry::fromPolygon( smoothPolygon( poly, iterations, offset ) );
1936  }
1937 
1938  case QGis::WKBMultiPolygon:
1940  {
1941  QgsMultiPolygon multipoly = asMultiPolygon();
1942  QgsMultiPolygon resultMultipoly;
1943  QgsMultiPolygon::const_iterator polyIt = multipoly.constBegin();
1944  for ( ; polyIt != multipoly.constEnd(); ++polyIt )
1945  {
1946  resultMultipoly << smoothPolygon( *polyIt, iterations, offset );
1947  }
1948  return QgsGeometry::fromMultiPolygon( resultMultipoly );
1949  }
1950 
1951  case QGis::WKBUnknown:
1952  default:
1953  return new QgsGeometry( *this );
1954  }
1955 }
1956 
1957 inline QgsPoint interpolatePointOnLine( const QgsPoint& p1, const QgsPoint& p2, const double offset )
1958 {
1959  double deltaX = p2.x() - p1.x();
1960  double deltaY = p2.y() - p1.y();
1961  return QgsPoint( p1.x() + deltaX * offset, p1.y() + deltaY * offset );
1962 }
1963 
1964 QgsPolyline QgsGeometry::smoothLine( const QgsPolyline& polyline, const unsigned int iterations, const double offset ) const
1965 {
1966  QgsPolyline result = polyline;
1967  for ( unsigned int iteration = 0; iteration < iterations; ++iteration )
1968  {
1969  QgsPolyline outputLine = QgsPolyline();
1970  outputLine.reserve( 2 * ( result.count() - 1 ) );
1971  for ( int i = 0; i < result.count() - 1; i++ )
1972  {
1973  const QgsPoint& p1 = result.at( i );
1974  const QgsPoint& p2 = result.at( i + 1 );
1975  outputLine << ( i == 0 ? result.at( i ) : interpolatePointOnLine( p1, p2, offset ) );
1976  outputLine << ( i == result.count() - 2 ? result.at( i + 1 ) : interpolatePointOnLine( p1, p2, 1.0 - offset ) );
1977  }
1978  result = outputLine;
1979  }
1980  return result;
1981 }
1982 
1983 QgsPolygon QgsGeometry::smoothPolygon( const QgsPolygon& polygon, const unsigned int iterations, const double offset ) const
1984 {
1985  QgsPolygon resultPoly;
1986  QgsPolygon::const_iterator ringIt = polygon.constBegin();
1987  for ( ; ringIt != polygon.constEnd(); ++ringIt )
1988  {
1989  QgsPolyline resultRing = *ringIt;
1990  for ( unsigned int iteration = 0; iteration < iterations; ++iteration )
1991  {
1992  QgsPolyline outputRing = QgsPolyline();
1993  outputRing.reserve( 2 * ( resultRing.count() - 1 ) + 1 );
1994  for ( int i = 0; i < resultRing.count() - 1; ++i )
1995  {
1996  const QgsPoint& p1 = resultRing.at( i );
1997  const QgsPoint& p2 = resultRing.at( i + 1 );
1998  outputRing << interpolatePointOnLine( p1, p2, offset );
1999  outputRing << interpolatePointOnLine( p1, p2, 1.0 - offset );
2000  }
2001  //close polygon
2002  outputRing << outputRing.at( 0 );
2003 
2004  resultRing = outputRing;
2005  }
2006  resultPoly << resultRing;
2007  }
2008  return resultPoly;
2009 }
2010 
2011 QgsGeometry* QgsGeometry::convertToPoint( bool destMultipart ) const
2012 {
2013  switch ( type() )
2014  {
2015  case QGis::Point:
2016  {
2017  bool srcIsMultipart = isMultipart();
2018 
2019  if (( destMultipart && srcIsMultipart ) ||
2020  ( !destMultipart && !srcIsMultipart ) )
2021  {
2022  // return a copy of the same geom
2023  return new QgsGeometry( *this );
2024  }
2025  if ( destMultipart )
2026  {
2027  // layer is multipart => make a multipoint with a single point
2028  return fromMultiPoint( QgsMultiPoint() << asPoint() );
2029  }
2030  else
2031  {
2032  // destination is singlepart => make a single part if possible
2033  QgsMultiPoint multiPoint = asMultiPoint();
2034  if ( multiPoint.count() == 1 )
2035  {
2036  return fromPoint( multiPoint[0] );
2037  }
2038  }
2039  return nullptr;
2040  }
2041 
2042  case QGis::Line:
2043  {
2044  // only possible if destination is multipart
2045  if ( !destMultipart )
2046  return nullptr;
2047 
2048  // input geometry is multipart
2049  if ( isMultipart() )
2050  {
2051  QgsMultiPolyline multiLine = asMultiPolyline();
2052  QgsMultiPoint multiPoint;
2053  for ( QgsMultiPolyline::const_iterator multiLineIt = multiLine.constBegin(); multiLineIt != multiLine.constEnd(); ++multiLineIt )
2054  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2055  multiPoint << *lineIt;
2056  return fromMultiPoint( multiPoint );
2057  }
2058  // input geometry is not multipart: copy directly the line into a multipoint
2059  else
2060  {
2061  QgsPolyline line = asPolyline();
2062  if ( !line.isEmpty() )
2063  return fromMultiPoint( line );
2064  }
2065  return nullptr;
2066  }
2067 
2068  case QGis::Polygon:
2069  {
2070  // can only transform if destination is multipoint
2071  if ( !destMultipart )
2072  return nullptr;
2073 
2074  // input geometry is multipart: make a multipoint from multipolygon
2075  if ( isMultipart() )
2076  {
2077  QgsMultiPolygon multiPolygon = asMultiPolygon();
2078  QgsMultiPoint multiPoint;
2079  for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
2080  for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
2081  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2082  multiPoint << *lineIt;
2083  return fromMultiPoint( multiPoint );
2084  }
2085  // input geometry is not multipart: make a multipoint from polygon
2086  else
2087  {
2088  QgsPolygon polygon = asPolygon();
2089  QgsMultiPoint multiPoint;
2090  for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
2091  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2092  multiPoint << *lineIt;
2093  return fromMultiPoint( multiPoint );
2094  }
2095  }
2096 
2097  default:
2098  return nullptr;
2099  }
2100 }
2101 
2102 QgsGeometry* QgsGeometry::convertToLine( bool destMultipart ) const
2103 {
2104  switch ( type() )
2105  {
2106  case QGis::Point:
2107  {
2108  if ( !isMultipart() )
2109  return nullptr;
2110 
2111  QgsMultiPoint multiPoint = asMultiPoint();
2112  if ( multiPoint.count() < 2 )
2113  return nullptr;
2114 
2115  if ( destMultipart )
2116  return fromMultiPolyline( QgsMultiPolyline() << multiPoint );
2117  else
2118  return fromPolyline( multiPoint );
2119  }
2120 
2121  case QGis::Line:
2122  {
2123  bool srcIsMultipart = isMultipart();
2124 
2125  if (( destMultipart && srcIsMultipart ) ||
2126  ( !destMultipart && ! srcIsMultipart ) )
2127  {
2128  // return a copy of the same geom
2129  return new QgsGeometry( *this );
2130  }
2131  if ( destMultipart )
2132  {
2133  // destination is multipart => makes a multipoint with a single line
2134  QgsPolyline line = asPolyline();
2135  if ( !line.isEmpty() )
2136  return fromMultiPolyline( QgsMultiPolyline() << line );
2137  }
2138  else
2139  {
2140  // destination is singlepart => make a single part if possible
2141  QgsMultiPolyline multiLine = asMultiPolyline();
2142  if ( multiLine.count() == 1 )
2143  return fromPolyline( multiLine[0] );
2144  }
2145  return nullptr;
2146  }
2147 
2148  case QGis::Polygon:
2149  {
2150  // input geometry is multipolygon
2151  if ( isMultipart() )
2152  {
2153  QgsMultiPolygon multiPolygon = asMultiPolygon();
2154  QgsMultiPolyline multiLine;
2155  for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
2156  for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
2157  multiLine << *multiLineIt;
2158 
2159  if ( destMultipart )
2160  {
2161  // destination is multipart
2162  return fromMultiPolyline( multiLine );
2163  }
2164  else if ( multiLine.count() == 1 )
2165  {
2166  // destination is singlepart => make a single part if possible
2167  return fromPolyline( multiLine[0] );
2168  }
2169  }
2170  // input geometry is single polygon
2171  else
2172  {
2173  QgsPolygon polygon = asPolygon();
2174  // if polygon has rings
2175  if ( polygon.count() > 1 )
2176  {
2177  // cannot fit a polygon with rings in a single line layer
2178  // TODO: would it be better to remove rings?
2179  if ( destMultipart )
2180  {
2181  QgsPolygon polygon = asPolygon();
2182  QgsMultiPolyline multiLine;
2183  for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
2184  multiLine << *multiLineIt;
2185  return fromMultiPolyline( multiLine );
2186  }
2187  }
2188  // no rings
2189  else if ( polygon.count() == 1 )
2190  {
2191  if ( destMultipart )
2192  {
2193  return fromMultiPolyline( polygon );
2194  }
2195  else
2196  {
2197  return fromPolyline( polygon[0] );
2198  }
2199  }
2200  }
2201  return nullptr;
2202  }
2203 
2204  default:
2205  return nullptr;
2206  }
2207 }
2208 
2209 QgsGeometry* QgsGeometry::convertToPolygon( bool destMultipart ) const
2210 {
2211  switch ( type() )
2212  {
2213  case QGis::Point:
2214  {
2215  if ( !isMultipart() )
2216  return nullptr;
2217 
2218  QgsMultiPoint multiPoint = asMultiPoint();
2219  if ( multiPoint.count() < 3 )
2220  return nullptr;
2221 
2222  if ( multiPoint.last() != multiPoint.first() )
2223  multiPoint << multiPoint.first();
2224 
2225  QgsPolygon polygon = QgsPolygon() << multiPoint;
2226  if ( destMultipart )
2227  return fromMultiPolygon( QgsMultiPolygon() << polygon );
2228  else
2229  return fromPolygon( polygon );
2230  }
2231 
2232  case QGis::Line:
2233  {
2234  // input geometry is multiline
2235  if ( isMultipart() )
2236  {
2237  QgsMultiPolyline multiLine = asMultiPolyline();
2238  QgsMultiPolygon multiPolygon;
2239  for ( QgsMultiPolyline::iterator multiLineIt = multiLine.begin(); multiLineIt != multiLine.end(); ++multiLineIt )
2240  {
2241  // do not create polygon for a 1 segment line
2242  if (( *multiLineIt ).count() < 3 )
2243  return nullptr;
2244  if (( *multiLineIt ).count() == 3 && ( *multiLineIt ).first() == ( *multiLineIt ).last() )
2245  return nullptr;
2246 
2247  // add closing node
2248  if (( *multiLineIt ).first() != ( *multiLineIt ).last() )
2249  *multiLineIt << ( *multiLineIt ).first();
2250  multiPolygon << ( QgsPolygon() << *multiLineIt );
2251  }
2252  // check that polygons were inserted
2253  if ( !multiPolygon.isEmpty() )
2254  {
2255  if ( destMultipart )
2256  {
2257  return fromMultiPolygon( multiPolygon );
2258  }
2259  else if ( multiPolygon.count() == 1 )
2260  {
2261  // destination is singlepart => make a single part if possible
2262  return fromPolygon( multiPolygon[0] );
2263  }
2264  }
2265  }
2266  // input geometry is single line
2267  else
2268  {
2269  QgsPolyline line = asPolyline();
2270 
2271  // do not create polygon for a 1 segment line
2272  if ( line.count() < 3 )
2273  return nullptr;
2274  if ( line.count() == 3 && line.first() == line.last() )
2275  return nullptr;
2276 
2277  // add closing node
2278  if ( line.first() != line.last() )
2279  line << line.first();
2280 
2281  // destination is multipart
2282  if ( destMultipart )
2283  {
2284  return fromMultiPolygon( QgsMultiPolygon() << ( QgsPolygon() << line ) );
2285  }
2286  else
2287  {
2288  return fromPolygon( QgsPolygon() << line );
2289  }
2290  }
2291  return nullptr;
2292  }
2293 
2294  case QGis::Polygon:
2295  {
2296  bool srcIsMultipart = isMultipart();
2297 
2298  if (( destMultipart && srcIsMultipart ) ||
2299  ( !destMultipart && ! srcIsMultipart ) )
2300  {
2301  // return a copy of the same geom
2302  return new QgsGeometry( *this );
2303  }
2304  if ( destMultipart )
2305  {
2306  // destination is multipart => makes a multipoint with a single polygon
2307  QgsPolygon polygon = asPolygon();
2308  if ( !polygon.isEmpty() )
2309  return fromMultiPolygon( QgsMultiPolygon() << polygon );
2310  }
2311  else
2312  {
2313  QgsMultiPolygon multiPolygon = asMultiPolygon();
2314  if ( multiPolygon.count() == 1 )
2315  {
2316  // destination is singlepart => make a single part if possible
2317  return fromPolygon( multiPolygon[0] );
2318  }
2319  }
2320  return nullptr;
2321  }
2322 
2323  default:
2324  return nullptr;
2325  }
2326 }
2327 
2329 {
2330  return new QgsGeos( geometry );
2331 }
2332 
2334 {
2335  QByteArray byteArray = QByteArray::fromRawData( reinterpret_cast< const char * >( geometry.asWkb() ), geometry.wkbSize() ); // does not copy data and does not take ownership
2336  out << byteArray;
2337  return out;
2338 }
2339 
2341 {
2342  QByteArray byteArray;
2343  in >> byteArray;
2344  if ( byteArray.isEmpty() )
2345  {
2346  geometry.setGeometry( nullptr );
2347  return in;
2348  }
2349 
2350  char *data = new char[byteArray.size()];
2351  memcpy( data, byteArray.data(), byteArray.size() );
2352  geometry.fromWkb( reinterpret_cast< unsigned char* >( data ), byteArray.size() );
2353  return in;
2354 }
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:1456
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:476
QgsGeometry closestPoint(const QgsGeometry &other, QString *errorMsg=nullptr) const
Returns the closest point on the geometry to the other geometry.
Definition: qgsgeos.cpp:1779
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:1422
T & first()
Multi point geometry collection.
QgsAbstractGeometryV2 * simplify(double tolerance, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1304
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:2348
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:1319
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.
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: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:31
bool deref()
QgsGeometry * buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
A class to represent a point.
Definition: qgspoint.h:117
bool isClosed() const
static QgsGeometry * fromPoint(const QgsPoint &point)
Creates a new geometry from a QgsPoint object.
int translate(double dx, double dy)
Translate this geometry by dx, dy.
This class offers geometry processing methods.
bool touches(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp: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: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: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.
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: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:1671
bool centroid(QgsPointV2 &pt, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1334
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:1814
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:1436
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:1376
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()
QgsAbstractGeometryV2 * offsetCurve(double distance, int segments, int joinStyle, double mitreLimit, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1655
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.
QgsAbstractGeometryV2 * convexHull(QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1405
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:1266
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