QGIS API Documentation  2.15.0-Master (02a0ebe)
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 || !geometry->d->geometry )
1427  {
1428  return nullptr;
1429  }
1430 
1431  QgsGeos geos( d->geometry );
1432 
1433  QgsAbstractGeometryV2* resultGeom = geos.difference( *( geometry->d->geometry ) );
1434  if ( !resultGeom )
1435  {
1436  return nullptr;
1437  }
1438  return new QgsGeometry( resultGeom );
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.symDifference( *( geometry->d->geometry ) );
1451  if ( !resultGeom )
1452  {
1453  return nullptr;
1454  }
1455  return new QgsGeometry( resultGeom );
1456 }
1457 
1458 QgsGeometry QgsGeometry::extrude( double x, double y )
1459 {
1460  QgsInternalGeometryEngine engine( *this );
1461 
1462  return engine.extrude( x, y );
1463 }
1464 
1466 {
1467  QList<QgsGeometry*> geometryList;
1468  if ( !d->geometry )
1469  {
1470  return geometryList;
1471  }
1472 
1473  QgsGeometryCollectionV2* gc = dynamic_cast<QgsGeometryCollectionV2*>( d->geometry );
1474  if ( gc )
1475  {
1476  int numGeom = gc->numGeometries();
1477  geometryList.reserve( numGeom );
1478  for ( int i = 0; i < numGeom; ++i )
1479  {
1480  geometryList.append( new QgsGeometry( gc->geometryN( i )->clone() ) );
1481  }
1482  }
1483  else //a singlepart geometry
1484  {
1485  geometryList.append( new QgsGeometry( d->geometry->clone() ) );
1486  }
1487 
1488  return geometryList;
1489 }
1490 
1492 {
1493  QgsPoint point = asPoint();
1494  return point.toQPointF();
1495 }
1496 
1498 {
1499  QPolygonF result;
1500  QgsPolyline polyline;
1502  if ( type == QGis::WKBLineString || type == QGis::WKBLineString25D )
1503  {
1504  polyline = asPolyline();
1505  }
1506  else if ( type == QGis::WKBPolygon || type == QGis::WKBPolygon25D )
1507  {
1508  QgsPolygon polygon = asPolygon();
1509  if ( polygon.size() < 1 )
1510  return result;
1511  polyline = polygon.at( 0 );
1512  }
1513  else
1514  {
1515  return result;
1516  }
1517 
1518  QgsPolyline::const_iterator lineIt = polyline.constBegin();
1519  for ( ; lineIt != polyline.constEnd(); ++lineIt )
1520  {
1521  result << lineIt->toQPointF();
1522  }
1523  return result;
1524 }
1525 
1526 bool QgsGeometry::deleteRing( int ringNum, int partNum )
1527 {
1528  if ( !d->geometry )
1529  {
1530  return false;
1531  }
1532 
1533  detach( true );
1534  bool ok = QgsGeometryEditUtils::deleteRing( d->geometry, ringNum, partNum );
1535  removeWkbGeos();
1536  return ok;
1537 }
1538 
1539 bool QgsGeometry::deletePart( int partNum )
1540 {
1541  if ( !d->geometry )
1542  {
1543  return false;
1544  }
1545 
1546  if ( !isMultipart() && partNum < 1 )
1547  {
1548  setGeometry( nullptr );
1549  return true;
1550  }
1551 
1552  detach( true );
1553  bool ok = QgsGeometryEditUtils::deletePart( d->geometry, partNum );
1554  removeWkbGeos();
1555  return ok;
1556 }
1557 
1559 {
1560  if ( !d->geometry )
1561  {
1562  return 1;
1563  }
1564 
1565  QgsAbstractGeometryV2* diffGeom = QgsGeometryEditUtils::avoidIntersections( *( d->geometry ), ignoreFeatures );
1566  if ( diffGeom )
1567  {
1568  detach( false );
1569  d->geometry = diffGeom;
1570  removeWkbGeos();
1571  }
1572  return 0;
1573 }
1574 
1576 {
1578 }
1579 
1581 {
1582  if ( !d->geometry )
1583  {
1584  return false;
1585  }
1586 
1587  QgsGeos geos( d->geometry );
1588  return geos.isValid();
1589 }
1590 
1592 {
1593  if ( !d->geometry || !g.d->geometry )
1594  {
1595  return false;
1596  }
1597 
1598  QgsGeos geos( d->geometry );
1599  return geos.isEqual( *( g.d->geometry ) );
1600 }
1601 
1603 {
1604  if ( !d->geometry )
1605  {
1606  return false;
1607  }
1608 
1609  QgsGeos geos( d->geometry );
1610  return geos.isEmpty();
1611 }
1612 
1614 {
1615  QgsGeos geos( nullptr );
1616 
1617  QList<QgsAbstractGeometryV2*> geomV2List;
1618  QList<QgsGeometry*>::const_iterator it = geometryList.constBegin();
1619  for ( ; it != geometryList.constEnd(); ++it )
1620  {
1621  if ( *it )
1622  {
1623  geomV2List.append(( *it )->geometry() );
1624  }
1625  }
1626 
1627  QgsAbstractGeometryV2* geom = geos.combine( geomV2List );
1628  return new QgsGeometry( geom );
1629 }
1630 
1632 {
1634  {
1635  return;
1636  }
1637 
1638  QgsAbstractGeometryV2* straightGeom = d->geometry->segmentize();
1639  detach( false );
1640 
1641  d->geometry = straightGeom;
1642  removeWkbGeos();
1643 }
1644 
1646 {
1647  if ( !d->geometry )
1648  {
1649  return false;
1650  }
1651 
1652  return d->geometry->hasCurvedSegments();
1653 }
1654 
1656 {
1657  if ( !d->geometry )
1658  {
1659  return 1;
1660  }
1661 
1662  detach();
1663  d->geometry->transform( ct );
1664  removeWkbGeos();
1665  return 0;
1666 }
1667 
1669 {
1670  if ( !d->geometry )
1671  {
1672  return 1;
1673  }
1674 
1675  detach();
1676  d->geometry->transform( ct );
1677  removeWkbGeos();
1678  return 0;
1679 }
1680 
1682 {
1683  if ( d->geometry )
1684  {
1685  detach();
1686  d->geometry->transform( mtp.transform() );
1687  removeWkbGeos();
1688  }
1689 }
1690 
1691 #if 0
1692 void QgsGeometry::clip( const QgsRectangle& rect )
1693 {
1694  if ( d->geometry )
1695  {
1696  detach();
1697  d->geometry->clip( rect );
1698  removeWkbGeos();
1699  }
1700 }
1701 #endif
1702 
1703 void QgsGeometry::draw( QPainter& p ) const
1704 {
1705  if ( d->geometry )
1706  {
1707  d->geometry->draw( p );
1708  }
1709 }
1710 
1712 {
1713  if ( !d->geometry )
1714  {
1715  return false;
1716  }
1717 
1719 
1720  int vertexCount = 0;
1721  for ( int part = 0; part < coords.size(); ++part )
1722  {
1723  const QgsRingSequenceV2 &featureCoords = coords.at( part );
1724  for ( int ring = 0; ring < featureCoords.size(); ++ring )
1725  {
1726  const QgsPointSequenceV2 &ringCoords = featureCoords.at( ring );
1727  for ( int vertex = 0; vertex < ringCoords.size(); ++vertex )
1728  {
1729  if ( vertexCount == nr )
1730  {
1731  id.part = part;
1732  id.ring = ring;
1733  id.vertex = vertex;
1734  return true;
1735  }
1736  ++vertexCount;
1737  }
1738  }
1739  }
1740  return false;
1741 }
1742 
1744 {
1745  if ( !d->geometry )
1746  {
1747  return -1;
1748  }
1749 
1751 
1752  int vertexCount = 0;
1753  for ( int part = 0; part < coords.size(); ++part )
1754  {
1755  const QgsRingSequenceV2 &featureCoords = coords.at( part );
1756  for ( int ring = 0; ring < featureCoords.size(); ++ring )
1757  {
1758  const QgsPointSequenceV2 &ringCoords = featureCoords.at( ring );
1759  for ( int vertex = 0; vertex < ringCoords.size(); ++vertex )
1760  {
1761  if ( vertex == id.vertex && ring == id.ring && part == id.part )
1762  {
1763  return vertexCount;
1764  }
1765  ++vertexCount;
1766  }
1767  }
1768  }
1769  return -1;
1770 }
1771 
1773 {
1774  output.clear();
1776  for ( ; it != input.constEnd(); ++it )
1777  {
1778  output.append( QgsPointV2( it->x(), it->y() ) );
1779  }
1780 }
1781 
1783 {
1784  output.clear();
1786  for ( ; it != input.constEnd(); ++it )
1787  {
1788  output.append( QgsPoint( it->x(), it->y() ) );
1789  }
1790 }
1791 
1792 void QgsGeometry::convertToPolyline( const QgsPointSequenceV2 &input, QgsPolyline& output )
1793 {
1794  output.clear();
1795  output.resize( input.size() );
1796 
1797  for ( int i = 0; i < input.size(); ++i )
1798  {
1799  const QgsPointV2& pt = input.at( i );
1800  output[i].setX( pt.x() );
1801  output[i].setY( pt.y() );
1802  }
1803 }
1804 
1805 void QgsGeometry::convertPolygon( const QgsPolygonV2& input, QgsPolygon& output )
1806 {
1807  output.clear();
1809  if ( coords.size() < 1 )
1810  {
1811  return;
1812  }
1813  const QgsRingSequenceV2 &rings = coords[0];
1814  output.resize( rings.size() );
1815  for ( int i = 0; i < rings.size(); ++i )
1816  {
1817  convertToPolyline( rings[i], output[i] );
1818  }
1819 }
1820 
1821 GEOSContextHandle_t QgsGeometry::getGEOSHandler()
1822 {
1823  return QgsGeos::getGEOSHandler();
1824 }
1825 
1827 {
1828  return new QgsGeometry( new QgsPointV2( point.x(), point.y() ) );
1829 }
1830 
1832 {
1833  if ( polygon.isClosed() )
1834  {
1836  }
1837  else
1838  {
1840  }
1841 }
1842 
1844 {
1845  QgsPolygon result;
1846  result << createPolylineFromQPolygonF( polygon );
1847  return result;
1848 }
1849 
1851 {
1852  QgsPolyline result;
1853  QPolygonF::const_iterator it = polygon.constBegin();
1854  for ( ; it != polygon.constEnd(); ++it )
1855  {
1856  result.append( QgsPoint( *it ) );
1857  }
1858  return result;
1859 }
1860 
1861 bool QgsGeometry::compare( const QgsPolyline &p1, const QgsPolyline &p2, double epsilon )
1862 {
1863  if ( p1.count() != p2.count() )
1864  return false;
1865 
1866  for ( int i = 0; i < p1.count(); ++i )
1867  {
1868  if ( !p1.at( i ).compare( p2.at( i ), epsilon ) )
1869  return false;
1870  }
1871  return true;
1872 }
1873 
1874 bool QgsGeometry::compare( const QgsPolygon &p1, const QgsPolygon &p2, double epsilon )
1875 {
1876  if ( p1.count() != p2.count() )
1877  return false;
1878 
1879  for ( int i = 0; i < p1.count(); ++i )
1880  {
1881  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
1882  return false;
1883  }
1884  return true;
1885 }
1886 
1887 
1888 bool QgsGeometry::compare( const QgsMultiPolygon &p1, const QgsMultiPolygon &p2, double epsilon )
1889 {
1890  if ( p1.count() != p2.count() )
1891  return false;
1892 
1893  for ( int i = 0; i < p1.count(); ++i )
1894  {
1895  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
1896  return false;
1897  }
1898  return true;
1899 }
1900 
1901 QgsGeometry* QgsGeometry::smooth( const unsigned int iterations, const double offset ) const
1902 {
1903  switch ( wkbType() )
1904  {
1905  case QGis::WKBPoint:
1906  case QGis::WKBPoint25D:
1907  case QGis::WKBMultiPoint:
1909  //can't smooth a point based geometry
1910  return new QgsGeometry( *this );
1911 
1912  case QGis::WKBLineString:
1914  {
1915  QgsPolyline line = asPolyline();
1916  return QgsGeometry::fromPolyline( smoothLine( line, iterations, offset ) );
1917  }
1918 
1921  {
1922  QgsMultiPolyline multiline = asMultiPolyline();
1923  QgsMultiPolyline resultMultiline;
1924  QgsMultiPolyline::const_iterator lineIt = multiline.constBegin();
1925  for ( ; lineIt != multiline.constEnd(); ++lineIt )
1926  {
1927  resultMultiline << smoothLine( *lineIt, iterations, offset );
1928  }
1929  return QgsGeometry::fromMultiPolyline( resultMultiline );
1930  }
1931 
1932  case QGis::WKBPolygon:
1933  case QGis::WKBPolygon25D:
1934  {
1935  QgsPolygon poly = asPolygon();
1936  return QgsGeometry::fromPolygon( smoothPolygon( poly, iterations, offset ) );
1937  }
1938 
1939  case QGis::WKBMultiPolygon:
1941  {
1942  QgsMultiPolygon multipoly = asMultiPolygon();
1943  QgsMultiPolygon resultMultipoly;
1944  QgsMultiPolygon::const_iterator polyIt = multipoly.constBegin();
1945  for ( ; polyIt != multipoly.constEnd(); ++polyIt )
1946  {
1947  resultMultipoly << smoothPolygon( *polyIt, iterations, offset );
1948  }
1949  return QgsGeometry::fromMultiPolygon( resultMultipoly );
1950  }
1951 
1952  case QGis::WKBUnknown:
1953  default:
1954  return new QgsGeometry( *this );
1955  }
1956 }
1957 
1958 inline QgsPoint interpolatePointOnLine( const QgsPoint& p1, const QgsPoint& p2, const double offset )
1959 {
1960  double deltaX = p2.x() - p1.x();
1961  double deltaY = p2.y() - p1.y();
1962  return QgsPoint( p1.x() + deltaX * offset, p1.y() + deltaY * offset );
1963 }
1964 
1965 QgsPolyline QgsGeometry::smoothLine( const QgsPolyline& polyline, const unsigned int iterations, const double offset ) const
1966 {
1967  QgsPolyline result = polyline;
1968  for ( unsigned int iteration = 0; iteration < iterations; ++iteration )
1969  {
1970  QgsPolyline outputLine = QgsPolyline();
1971  outputLine.reserve( 2 * ( result.count() - 1 ) );
1972  for ( int i = 0; i < result.count() - 1; i++ )
1973  {
1974  const QgsPoint& p1 = result.at( i );
1975  const QgsPoint& p2 = result.at( i + 1 );
1976  outputLine << ( i == 0 ? result.at( i ) : interpolatePointOnLine( p1, p2, offset ) );
1977  outputLine << ( i == result.count() - 2 ? result.at( i + 1 ) : interpolatePointOnLine( p1, p2, 1.0 - offset ) );
1978  }
1979  result = outputLine;
1980  }
1981  return result;
1982 }
1983 
1984 QgsPolygon QgsGeometry::smoothPolygon( const QgsPolygon& polygon, const unsigned int iterations, const double offset ) const
1985 {
1986  QgsPolygon resultPoly;
1987  QgsPolygon::const_iterator ringIt = polygon.constBegin();
1988  for ( ; ringIt != polygon.constEnd(); ++ringIt )
1989  {
1990  QgsPolyline resultRing = *ringIt;
1991  for ( unsigned int iteration = 0; iteration < iterations; ++iteration )
1992  {
1993  QgsPolyline outputRing = QgsPolyline();
1994  outputRing.reserve( 2 * ( resultRing.count() - 1 ) + 1 );
1995  for ( int i = 0; i < resultRing.count() - 1; ++i )
1996  {
1997  const QgsPoint& p1 = resultRing.at( i );
1998  const QgsPoint& p2 = resultRing.at( i + 1 );
1999  outputRing << interpolatePointOnLine( p1, p2, offset );
2000  outputRing << interpolatePointOnLine( p1, p2, 1.0 - offset );
2001  }
2002  //close polygon
2003  outputRing << outputRing.at( 0 );
2004 
2005  resultRing = outputRing;
2006  }
2007  resultPoly << resultRing;
2008  }
2009  return resultPoly;
2010 }
2011 
2012 QgsGeometry* QgsGeometry::convertToPoint( bool destMultipart ) const
2013 {
2014  switch ( type() )
2015  {
2016  case QGis::Point:
2017  {
2018  bool srcIsMultipart = isMultipart();
2019 
2020  if (( destMultipart && srcIsMultipart ) ||
2021  ( !destMultipart && !srcIsMultipart ) )
2022  {
2023  // return a copy of the same geom
2024  return new QgsGeometry( *this );
2025  }
2026  if ( destMultipart )
2027  {
2028  // layer is multipart => make a multipoint with a single point
2029  return fromMultiPoint( QgsMultiPoint() << asPoint() );
2030  }
2031  else
2032  {
2033  // destination is singlepart => make a single part if possible
2034  QgsMultiPoint multiPoint = asMultiPoint();
2035  if ( multiPoint.count() == 1 )
2036  {
2037  return fromPoint( multiPoint[0] );
2038  }
2039  }
2040  return nullptr;
2041  }
2042 
2043  case QGis::Line:
2044  {
2045  // only possible if destination is multipart
2046  if ( !destMultipart )
2047  return nullptr;
2048 
2049  // input geometry is multipart
2050  if ( isMultipart() )
2051  {
2052  QgsMultiPolyline multiLine = asMultiPolyline();
2053  QgsMultiPoint multiPoint;
2054  for ( QgsMultiPolyline::const_iterator multiLineIt = multiLine.constBegin(); multiLineIt != multiLine.constEnd(); ++multiLineIt )
2055  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2056  multiPoint << *lineIt;
2057  return fromMultiPoint( multiPoint );
2058  }
2059  // input geometry is not multipart: copy directly the line into a multipoint
2060  else
2061  {
2062  QgsPolyline line = asPolyline();
2063  if ( !line.isEmpty() )
2064  return fromMultiPoint( line );
2065  }
2066  return nullptr;
2067  }
2068 
2069  case QGis::Polygon:
2070  {
2071  // can only transform if destination is multipoint
2072  if ( !destMultipart )
2073  return nullptr;
2074 
2075  // input geometry is multipart: make a multipoint from multipolygon
2076  if ( isMultipart() )
2077  {
2078  QgsMultiPolygon multiPolygon = asMultiPolygon();
2079  QgsMultiPoint multiPoint;
2080  for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
2081  for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
2082  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2083  multiPoint << *lineIt;
2084  return fromMultiPoint( multiPoint );
2085  }
2086  // input geometry is not multipart: make a multipoint from polygon
2087  else
2088  {
2089  QgsPolygon polygon = asPolygon();
2090  QgsMultiPoint multiPoint;
2091  for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
2092  for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
2093  multiPoint << *lineIt;
2094  return fromMultiPoint( multiPoint );
2095  }
2096  }
2097 
2098  default:
2099  return nullptr;
2100  }
2101 }
2102 
2103 QgsGeometry* QgsGeometry::convertToLine( bool destMultipart ) const
2104 {
2105  switch ( type() )
2106  {
2107  case QGis::Point:
2108  {
2109  if ( !isMultipart() )
2110  return nullptr;
2111 
2112  QgsMultiPoint multiPoint = asMultiPoint();
2113  if ( multiPoint.count() < 2 )
2114  return nullptr;
2115 
2116  if ( destMultipart )
2117  return fromMultiPolyline( QgsMultiPolyline() << multiPoint );
2118  else
2119  return fromPolyline( multiPoint );
2120  }
2121 
2122  case QGis::Line:
2123  {
2124  bool srcIsMultipart = isMultipart();
2125 
2126  if (( destMultipart && srcIsMultipart ) ||
2127  ( !destMultipart && ! srcIsMultipart ) )
2128  {
2129  // return a copy of the same geom
2130  return new QgsGeometry( *this );
2131  }
2132  if ( destMultipart )
2133  {
2134  // destination is multipart => makes a multipoint with a single line
2135  QgsPolyline line = asPolyline();
2136  if ( !line.isEmpty() )
2137  return fromMultiPolyline( QgsMultiPolyline() << line );
2138  }
2139  else
2140  {
2141  // destination is singlepart => make a single part if possible
2142  QgsMultiPolyline multiLine = asMultiPolyline();
2143  if ( multiLine.count() == 1 )
2144  return fromPolyline( multiLine[0] );
2145  }
2146  return nullptr;
2147  }
2148 
2149  case QGis::Polygon:
2150  {
2151  // input geometry is multipolygon
2152  if ( isMultipart() )
2153  {
2154  QgsMultiPolygon multiPolygon = asMultiPolygon();
2155  QgsMultiPolyline multiLine;
2156  for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
2157  for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
2158  multiLine << *multiLineIt;
2159 
2160  if ( destMultipart )
2161  {
2162  // destination is multipart
2163  return fromMultiPolyline( multiLine );
2164  }
2165  else if ( multiLine.count() == 1 )
2166  {
2167  // destination is singlepart => make a single part if possible
2168  return fromPolyline( multiLine[0] );
2169  }
2170  }
2171  // input geometry is single polygon
2172  else
2173  {
2174  QgsPolygon polygon = asPolygon();
2175  // if polygon has rings
2176  if ( polygon.count() > 1 )
2177  {
2178  // cannot fit a polygon with rings in a single line layer
2179  // TODO: would it be better to remove rings?
2180  if ( destMultipart )
2181  {
2182  QgsPolygon polygon = asPolygon();
2183  QgsMultiPolyline multiLine;
2184  for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
2185  multiLine << *multiLineIt;
2186  return fromMultiPolyline( multiLine );
2187  }
2188  }
2189  // no rings
2190  else if ( polygon.count() == 1 )
2191  {
2192  if ( destMultipart )
2193  {
2194  return fromMultiPolyline( polygon );
2195  }
2196  else
2197  {
2198  return fromPolyline( polygon[0] );
2199  }
2200  }
2201  }
2202  return nullptr;
2203  }
2204 
2205  default:
2206  return nullptr;
2207  }
2208 }
2209 
2210 QgsGeometry* QgsGeometry::convertToPolygon( bool destMultipart ) const
2211 {
2212  switch ( type() )
2213  {
2214  case QGis::Point:
2215  {
2216  if ( !isMultipart() )
2217  return nullptr;
2218 
2219  QgsMultiPoint multiPoint = asMultiPoint();
2220  if ( multiPoint.count() < 3 )
2221  return nullptr;
2222 
2223  if ( multiPoint.last() != multiPoint.first() )
2224  multiPoint << multiPoint.first();
2225 
2226  QgsPolygon polygon = QgsPolygon() << multiPoint;
2227  if ( destMultipart )
2228  return fromMultiPolygon( QgsMultiPolygon() << polygon );
2229  else
2230  return fromPolygon( polygon );
2231  }
2232 
2233  case QGis::Line:
2234  {
2235  // input geometry is multiline
2236  if ( isMultipart() )
2237  {
2238  QgsMultiPolyline multiLine = asMultiPolyline();
2239  QgsMultiPolygon multiPolygon;
2240  for ( QgsMultiPolyline::iterator multiLineIt = multiLine.begin(); multiLineIt != multiLine.end(); ++multiLineIt )
2241  {
2242  // do not create polygon for a 1 segment line
2243  if (( *multiLineIt ).count() < 3 )
2244  return nullptr;
2245  if (( *multiLineIt ).count() == 3 && ( *multiLineIt ).first() == ( *multiLineIt ).last() )
2246  return nullptr;
2247 
2248  // add closing node
2249  if (( *multiLineIt ).first() != ( *multiLineIt ).last() )
2250  *multiLineIt << ( *multiLineIt ).first();
2251  multiPolygon << ( QgsPolygon() << *multiLineIt );
2252  }
2253  // check that polygons were inserted
2254  if ( !multiPolygon.isEmpty() )
2255  {
2256  if ( destMultipart )
2257  {
2258  return fromMultiPolygon( multiPolygon );
2259  }
2260  else if ( multiPolygon.count() == 1 )
2261  {
2262  // destination is singlepart => make a single part if possible
2263  return fromPolygon( multiPolygon[0] );
2264  }
2265  }
2266  }
2267  // input geometry is single line
2268  else
2269  {
2270  QgsPolyline line = asPolyline();
2271 
2272  // do not create polygon for a 1 segment line
2273  if ( line.count() < 3 )
2274  return nullptr;
2275  if ( line.count() == 3 && line.first() == line.last() )
2276  return nullptr;
2277 
2278  // add closing node
2279  if ( line.first() != line.last() )
2280  line << line.first();
2281 
2282  // destination is multipart
2283  if ( destMultipart )
2284  {
2285  return fromMultiPolygon( QgsMultiPolygon() << ( QgsPolygon() << line ) );
2286  }
2287  else
2288  {
2289  return fromPolygon( QgsPolygon() << line );
2290  }
2291  }
2292  return nullptr;
2293  }
2294 
2295  case QGis::Polygon:
2296  {
2297  bool srcIsMultipart = isMultipart();
2298 
2299  if (( destMultipart && srcIsMultipart ) ||
2300  ( !destMultipart && ! srcIsMultipart ) )
2301  {
2302  // return a copy of the same geom
2303  return new QgsGeometry( *this );
2304  }
2305  if ( destMultipart )
2306  {
2307  // destination is multipart => makes a multipoint with a single polygon
2308  QgsPolygon polygon = asPolygon();
2309  if ( !polygon.isEmpty() )
2310  return fromMultiPolygon( QgsMultiPolygon() << polygon );
2311  }
2312  else
2313  {
2314  QgsMultiPolygon multiPolygon = asMultiPolygon();
2315  if ( multiPolygon.count() == 1 )
2316  {
2317  // destination is singlepart => make a single part if possible
2318  return fromPolygon( multiPolygon[0] );
2319  }
2320  }
2321  return nullptr;
2322  }
2323 
2324  default:
2325  return nullptr;
2326  }
2327 }
2328 
2330 {
2331  return new QgsGeos( geometry );
2332 }
2333 
2335 {
2336  QByteArray byteArray = QByteArray::fromRawData( reinterpret_cast< const char * >( geometry.asWkb() ), geometry.wkbSize() ); // does not copy data and does not take ownership
2337  out << byteArray;
2338  return out;
2339 }
2340 
2342 {
2343  QByteArray byteArray;
2344  in >> byteArray;
2345  if ( byteArray.isEmpty() )
2346  {
2347  geometry.setGeometry( nullptr );
2348  return in;
2349  }
2350 
2351  char *data = new char[byteArray.size()];
2352  memcpy( data, byteArray.data(), byteArray.size() );
2353  geometry.fromWkb( reinterpret_cast< unsigned char* >( data ), byteArray.size() );
2354  return in;
2355 }
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:1797
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:2366
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.
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: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:1832
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
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: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.
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