QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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 #include <nlohmann/json.hpp>
21 
22 #include "qgis.h"
23 #include "qgsgeometry.h"
24 #include "qgsgeometryeditutils.h"
25 #include "qgsgeometryfactory.h"
26 #include "qgsgeometrymakevalid.h"
27 #include "qgsgeometryutils.h"
29 #include "qgsgeos.h"
30 #include "qgsapplication.h"
31 #include "qgslogger.h"
32 #include "qgsmaptopixel.h"
33 #include "qgsmessagelog.h"
34 #include "qgspointxy.h"
35 #include "qgsrectangle.h"
36 
37 #include "qgsvectorlayer.h"
38 #include "qgsgeometryvalidator.h"
39 
40 #include "qgsmulticurve.h"
41 #include "qgsmultilinestring.h"
42 #include "qgsmultipoint.h"
43 #include "qgsmultipolygon.h"
44 #include "qgsmultisurface.h"
45 #include "qgspoint.h"
46 #include "qgspolygon.h"
47 #include "qgslinestring.h"
48 #include "qgscircle.h"
49 #include "qgscurve.h"
50 
52 {
54  QAtomicInt ref;
55  std::unique_ptr< QgsAbstractGeometry > geometry;
56 };
57 
59  : d( new QgsGeometryPrivate() )
60 {
61 }
62 
64 {
65  if ( !d->ref.deref() )
66  delete d;
67 }
68 
70  : d( new QgsGeometryPrivate() )
71 {
72  d->geometry.reset( geom );
73  d->ref = QAtomicInt( 1 );
74 }
75 
76 QgsGeometry::QgsGeometry( std::unique_ptr<QgsAbstractGeometry> geom )
77  : d( new QgsGeometryPrivate() )
78 {
79  d->geometry = std::move( geom );
80  d->ref = QAtomicInt( 1 );
81 }
82 
84  : d( other.d )
85 {
86  mLastError = other.mLastError;
87  d->ref.ref();
88 }
89 
91 {
92  if ( this != &other )
93  {
94  if ( !d->ref.deref() )
95  {
96  delete d;
97  }
98 
99  mLastError = other.mLastError;
100  d = other.d;
101  d->ref.ref();
102  }
103  return *this;
104 }
105 
106 void QgsGeometry::detach()
107 {
108  if ( d->ref <= 1 )
109  return;
110 
111  std::unique_ptr< QgsAbstractGeometry > cGeom;
112  if ( d->geometry )
113  cGeom.reset( d->geometry->clone() );
114 
115  reset( std::move( cGeom ) );
116 }
117 
118 void QgsGeometry::reset( std::unique_ptr<QgsAbstractGeometry> newGeometry )
119 {
120  if ( d->ref > 1 )
121  {
122  ( void )d->ref.deref();
123  d = new QgsGeometryPrivate();
124  }
125  d->geometry = std::move( newGeometry );
126 }
127 
129 {
130  return d->geometry.get();
131 }
132 
134 {
135  detach();
136  return d->geometry.get();
137 }
138 
140 {
141  if ( d->geometry.get() == geometry )
142  {
143  return;
144  }
145 
146  reset( std::unique_ptr< QgsAbstractGeometry >( geometry ) );
147 }
148 
150 {
151  return !d->geometry;
152 }
153 
154 QgsGeometry QgsGeometry::fromWkt( const QString &wkt )
155 {
156  std::unique_ptr< QgsAbstractGeometry > geom = QgsGeometryFactory::geomFromWkt( wkt );
157  if ( !geom )
158  {
159  return QgsGeometry();
160  }
161  return QgsGeometry( std::move( geom ) );
162 }
163 
165 {
166  std::unique_ptr< QgsAbstractGeometry > geom( QgsGeometryFactory::fromPointXY( point ) );
167  if ( geom )
168  {
169  return QgsGeometry( geom.release() );
170  }
171  return QgsGeometry();
172 }
173 
175 {
176  std::unique_ptr< QgsAbstractGeometry > geom = QgsGeometryFactory::fromPolylineXY( polyline );
177  if ( geom )
178  {
179  return QgsGeometry( std::move( geom ) );
180  }
181  return QgsGeometry();
182 }
183 
185 {
186  return QgsGeometry( qgis::make_unique< QgsLineString >( polyline ) );
187 }
188 
190 {
191  std::unique_ptr< QgsPolygon > geom = QgsGeometryFactory::fromPolygonXY( polygon );
192  if ( geom )
193  {
194  return QgsGeometry( std::move( geom.release() ) );
195  }
196  return QgsGeometry();
197 }
198 
200 {
201  std::unique_ptr< QgsMultiPoint > geom = QgsGeometryFactory::fromMultiPointXY( multipoint );
202  if ( geom )
203  {
204  return QgsGeometry( std::move( geom ) );
205  }
206  return QgsGeometry();
207 }
208 
210 {
211  std::unique_ptr< QgsMultiLineString > geom = QgsGeometryFactory::fromMultiPolylineXY( multiline );
212  if ( geom )
213  {
214  return QgsGeometry( std::move( geom ) );
215  }
216  return QgsGeometry();
217 }
218 
220 {
221  std::unique_ptr< QgsMultiPolygon > geom = QgsGeometryFactory::fromMultiPolygonXY( multipoly );
222  if ( geom )
223  {
224  return QgsGeometry( std::move( geom ) );
225  }
226  return QgsGeometry();
227 }
228 
230 {
231  std::unique_ptr< QgsLineString > ext = qgis::make_unique< QgsLineString >(
232  QVector< double >() << rect.xMinimum()
233  << rect.xMaximum()
234  << rect.xMaximum()
235  << rect.xMinimum()
236  << rect.xMinimum(),
237  QVector< double >() << rect.yMinimum()
238  << rect.yMinimum()
239  << rect.yMaximum()
240  << rect.yMaximum()
241  << rect.yMinimum() );
242  std::unique_ptr< QgsPolygon > polygon = qgis::make_unique< QgsPolygon >();
243  polygon->setExteriorRing( ext.release() );
244  return QgsGeometry( std::move( polygon ) );
245 }
246 
247 QgsGeometry QgsGeometry::collectGeometry( const QVector< QgsGeometry > &geometries )
248 {
249  QgsGeometry collected;
250 
251  for ( const QgsGeometry &g : geometries )
252  {
253  if ( collected.isNull() )
254  {
255  collected = g;
256  collected.convertToMultiType();
257  }
258  else
259  {
260  if ( g.isMultipart() )
261  {
262  for ( auto p = g.const_parts_begin(); p != g.const_parts_end(); ++p )
263  {
264  collected.addPart( ( *p )->clone() );
265  }
266  }
267  else
268  {
269  collected.addPart( g );
270  }
271  }
272  }
273  return collected;
274 }
275 
276 QgsGeometry QgsGeometry::createWedgeBuffer( const QgsPoint &center, const double azimuth, const double angularWidth, const double outerRadius, const double innerRadius )
277 {
278  if ( std::abs( angularWidth ) >= 360.0 )
279  {
280  std::unique_ptr< QgsCompoundCurve > outerCc = qgis::make_unique< QgsCompoundCurve >();
281 
282  QgsCircle outerCircle = QgsCircle( center, outerRadius );
283  outerCc->addCurve( outerCircle.toCircularString() );
284 
285  std::unique_ptr< QgsCurvePolygon > cp = qgis::make_unique< QgsCurvePolygon >();
286  cp->setExteriorRing( outerCc.release() );
287 
288  if ( !qgsDoubleNear( innerRadius, 0.0 ) && innerRadius > 0 )
289  {
290  std::unique_ptr< QgsCompoundCurve > innerCc = qgis::make_unique< QgsCompoundCurve >();
291 
292  QgsCircle innerCircle = QgsCircle( center, innerRadius );
293  innerCc->addCurve( innerCircle.toCircularString() );
294 
295  cp->setInteriorRings( { innerCc.release() } );
296  }
297 
298  return QgsGeometry( std::move( cp ) );
299  }
300 
301  std::unique_ptr< QgsCompoundCurve > wedge = qgis::make_unique< QgsCompoundCurve >();
302 
303  const double startAngle = azimuth - angularWidth * 0.5;
304  const double endAngle = azimuth + angularWidth * 0.5;
305 
306  const QgsPoint outerP1 = center.project( outerRadius, startAngle );
307  const QgsPoint outerP2 = center.project( outerRadius, endAngle );
308 
309  const bool useShortestArc = angularWidth <= 180.0;
310 
311  wedge->addCurve( new QgsCircularString( QgsCircularString::fromTwoPointsAndCenter( outerP1, outerP2, center, useShortestArc ) ) );
312 
313  if ( !qgsDoubleNear( innerRadius, 0.0 ) && innerRadius > 0 )
314  {
315  const QgsPoint innerP1 = center.project( innerRadius, startAngle );
316  const QgsPoint innerP2 = center.project( innerRadius, endAngle );
317  wedge->addCurve( new QgsLineString( outerP2, innerP2 ) );
318  wedge->addCurve( new QgsCircularString( QgsCircularString::fromTwoPointsAndCenter( innerP2, innerP1, center, useShortestArc ) ) );
319  wedge->addCurve( new QgsLineString( innerP1, outerP1 ) );
320  }
321  else
322  {
323  wedge->addCurve( new QgsLineString( outerP2, center ) );
324  wedge->addCurve( new QgsLineString( center, outerP1 ) );
325  }
326 
327  std::unique_ptr< QgsCurvePolygon > cp = qgis::make_unique< QgsCurvePolygon >();
328  cp->setExteriorRing( wedge.release() );
329  return QgsGeometry( std::move( cp ) );
330 }
331 
332 void QgsGeometry::fromWkb( unsigned char *wkb, int length )
333 {
334  QgsConstWkbPtr ptr( wkb, length );
335  reset( QgsGeometryFactory::geomFromWkb( ptr ) );
336  delete [] wkb;
337 }
338 
339 void QgsGeometry::fromWkb( const QByteArray &wkb )
340 {
341  QgsConstWkbPtr ptr( wkb );
342  reset( QgsGeometryFactory::geomFromWkb( ptr ) );
343 }
344 
346 {
347  if ( !d->geometry )
348  {
349  return QgsWkbTypes::Unknown;
350  }
351  else
352  {
353  return d->geometry->wkbType();
354  }
355 }
356 
357 
359 {
360  if ( !d->geometry )
361  {
363  }
364  return static_cast< QgsWkbTypes::GeometryType >( QgsWkbTypes::geometryType( d->geometry->wkbType() ) );
365 }
366 
368 {
369  if ( !d->geometry )
370  {
371  return true;
372  }
373 
374  return d->geometry->isEmpty();
375 }
376 
378 {
379  if ( !d->geometry )
380  {
381  return false;
382  }
383  return QgsWkbTypes::isMultiType( d->geometry->wkbType() );
384 }
385 
386 QgsPointXY QgsGeometry::closestVertex( const QgsPointXY &point, int &atVertex, int &beforeVertex, int &afterVertex, double &sqrDist ) const
387 {
388  if ( !d->geometry )
389  {
390  sqrDist = -1;
391  return QgsPointXY();
392  }
393 
394  QgsPoint pt( point );
395  QgsVertexId id;
396 
397  QgsPoint vp = QgsGeometryUtils::closestVertex( *( d->geometry ), pt, id );
398  if ( !id.isValid() )
399  {
400  sqrDist = -1;
401  return QgsPointXY();
402  }
403  sqrDist = QgsGeometryUtils::sqrDistance2D( pt, vp );
404 
405  QgsVertexId prevVertex;
406  QgsVertexId nextVertex;
407  d->geometry->adjacentVertices( id, prevVertex, nextVertex );
408  atVertex = vertexNrFromVertexId( id );
409  beforeVertex = vertexNrFromVertexId( prevVertex );
410  afterVertex = vertexNrFromVertexId( nextVertex );
411  return QgsPointXY( vp.x(), vp.y() );
412 }
413 
414 double QgsGeometry::distanceToVertex( int vertex ) const
415 {
416  if ( !d->geometry )
417  {
418  return -1;
419  }
420 
421  QgsVertexId id;
422  if ( !vertexIdFromVertexNr( vertex, id ) )
423  {
424  return -1;
425  }
426 
427  return QgsGeometryUtils::distanceToVertex( *( d->geometry ), id );
428 }
429 
430 double QgsGeometry::angleAtVertex( int vertex ) const
431 {
432  if ( !d->geometry )
433  {
434  return 0;
435  }
436 
437  QgsVertexId v2;
438  if ( !vertexIdFromVertexNr( vertex, v2 ) )
439  {
440  return 0;
441  }
442 
443  return d->geometry->vertexAngle( v2 );
444 }
445 
446 void QgsGeometry::adjacentVertices( int atVertex, int &beforeVertex, int &afterVertex ) const
447 {
448  if ( !d->geometry )
449  {
450  return;
451  }
452 
453  QgsVertexId id;
454  if ( !vertexIdFromVertexNr( atVertex, id ) )
455  {
456  beforeVertex = -1;
457  afterVertex = -1;
458  return;
459  }
460 
461  QgsVertexId beforeVertexId, afterVertexId;
462  d->geometry->adjacentVertices( id, beforeVertexId, afterVertexId );
463  beforeVertex = vertexNrFromVertexId( beforeVertexId );
464  afterVertex = vertexNrFromVertexId( afterVertexId );
465 }
466 
467 bool QgsGeometry::moveVertex( double x, double y, int atVertex )
468 {
469  if ( !d->geometry )
470  {
471  return false;
472  }
473 
474  QgsVertexId id;
475  if ( !vertexIdFromVertexNr( atVertex, id ) )
476  {
477  return false;
478  }
479 
480  detach();
481 
482  return d->geometry->moveVertex( id, QgsPoint( x, y ) );
483 }
484 
485 bool QgsGeometry::moveVertex( const QgsPoint &p, int atVertex )
486 {
487  if ( !d->geometry )
488  {
489  return false;
490  }
491 
492  QgsVertexId id;
493  if ( !vertexIdFromVertexNr( atVertex, id ) )
494  {
495  return false;
496  }
497 
498  detach();
499 
500  return d->geometry->moveVertex( id, p );
501 }
502 
503 bool QgsGeometry::deleteVertex( int atVertex )
504 {
505  if ( !d->geometry )
506  {
507  return false;
508  }
509 
510  //maintain compatibility with < 2.10 API
511  if ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::MultiPoint )
512  {
513  detach();
514  //delete geometry instead of point
515  return static_cast< QgsGeometryCollection * >( d->geometry.get() )->removeGeometry( atVertex );
516  }
517 
518  //if it is a point, set the geometry to nullptr
519  if ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::Point )
520  {
521  reset( nullptr );
522  return true;
523  }
524 
525  QgsVertexId id;
526  if ( !vertexIdFromVertexNr( atVertex, id ) )
527  {
528  return false;
529  }
530 
531  detach();
532 
533  return d->geometry->deleteVertex( id );
534 }
535 
536 bool QgsGeometry::insertVertex( double x, double y, int beforeVertex )
537 {
538  if ( !d->geometry )
539  {
540  return false;
541  }
542 
543  //maintain compatibility with < 2.10 API
544  if ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::MultiPoint )
545  {
546  detach();
547  //insert geometry instead of point
548  return static_cast< QgsGeometryCollection * >( d->geometry.get() )->insertGeometry( new QgsPoint( x, y ), beforeVertex );
549  }
550 
551  QgsVertexId id;
552  if ( !vertexIdFromVertexNr( beforeVertex, id ) )
553  {
554  return false;
555  }
556 
557  detach();
558 
559  return d->geometry->insertVertex( id, QgsPoint( x, y ) );
560 }
561 
562 bool QgsGeometry::insertVertex( const QgsPoint &point, int beforeVertex )
563 {
564  if ( !d->geometry )
565  {
566  return false;
567  }
568 
569  //maintain compatibility with < 2.10 API
570  if ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::MultiPoint )
571  {
572  detach();
573  //insert geometry instead of point
574  return static_cast< QgsGeometryCollection * >( d->geometry.get() )->insertGeometry( new QgsPoint( point ), beforeVertex );
575  }
576 
577  QgsVertexId id;
578  if ( !vertexIdFromVertexNr( beforeVertex, id ) )
579  {
580  return false;
581  }
582 
583  detach();
584 
585  return d->geometry->insertVertex( id, point );
586 }
587 
588 QgsPoint QgsGeometry::vertexAt( int atVertex ) const
589 {
590  if ( !d->geometry )
591  {
592  return QgsPoint();
593  }
594 
595  QgsVertexId vId;
596  ( void )vertexIdFromVertexNr( atVertex, vId );
597  if ( vId.vertex < 0 )
598  {
599  return QgsPoint();
600  }
601  return d->geometry->vertexAt( vId );
602 }
603 
604 double QgsGeometry::sqrDistToVertexAt( QgsPointXY &point, int atVertex ) const
605 {
606  QgsPointXY vertexPoint = vertexAt( atVertex );
607  return QgsGeometryUtils::sqrDistance2D( QgsPoint( vertexPoint ), QgsPoint( point ) );
608 }
609 
611 {
612  // avoid calling geos for trivial point calculations
613  if ( d->geometry && QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::Point )
614  {
615  return QgsGeometry( qgsgeometry_cast< const QgsPoint * >( d->geometry.get() )->clone() );
616  }
617 
618  QgsGeos geos( d->geometry.get() );
619  mLastError.clear();
620  QgsGeometry result = geos.closestPoint( other );
621  result.mLastError = mLastError;
622  return result;
623 }
624 
626 {
627  // avoid calling geos for trivial point-to-point line calculations
629  {
630  return QgsGeometry( qgis::make_unique< QgsLineString >( *qgsgeometry_cast< const QgsPoint * >( d->geometry.get() ), *qgsgeometry_cast< const QgsPoint * >( other.constGet() ) ) );
631  }
632 
633  QgsGeos geos( d->geometry.get() );
634  mLastError.clear();
635  QgsGeometry result = geos.shortestLine( other, &mLastError );
636  result.mLastError = mLastError;
637  return result;
638 }
639 
640 double QgsGeometry::closestVertexWithContext( const QgsPointXY &point, int &atVertex ) const
641 {
642  if ( !d->geometry )
643  {
644  return -1;
645  }
646 
647  QgsVertexId vId;
648  QgsPoint pt( point );
649  QgsPoint closestPoint = QgsGeometryUtils::closestVertex( *( d->geometry ), pt, vId );
650  if ( !vId.isValid() )
651  return -1;
652  atVertex = vertexNrFromVertexId( vId );
653  return QgsGeometryUtils::sqrDistance2D( closestPoint, pt );
654 }
655 
657  QgsPointXY &minDistPoint,
658  int &afterVertex,
659  int *leftOf,
660  double epsilon ) const
661 {
662  if ( !d->geometry )
663  {
664  return -1;
665  }
666 
667  QgsPoint segmentPt;
668  QgsVertexId vertexAfter;
669 
670  double sqrDist = d->geometry->closestSegment( QgsPoint( point ), segmentPt, vertexAfter, leftOf, epsilon );
671  if ( sqrDist < 0 )
672  return -1;
673 
674  minDistPoint.setX( segmentPt.x() );
675  minDistPoint.setY( segmentPt.y() );
676  afterVertex = vertexNrFromVertexId( vertexAfter );
677  return sqrDist;
678 }
679 
680 QgsGeometry::OperationResult QgsGeometry::addRing( const QVector<QgsPointXY> &ring )
681 {
682  std::unique_ptr< QgsLineString > ringLine = qgis::make_unique< QgsLineString >( ring );
683  return addRing( ringLine.release() );
684 }
685 
687 {
688  std::unique_ptr< QgsCurve > r( ring );
689  if ( !d->geometry )
690  {
692  }
693 
694  detach();
695 
696  return QgsGeometryEditUtils::addRing( d->geometry.get(), std::move( r ) );
697 }
698 
700 {
702  convertPointList( points, l );
703  return addPart( l, geomType );
704 }
705 
707 {
708  std::unique_ptr< QgsAbstractGeometry > partGeom;
709  if ( points.size() == 1 )
710  {
711  partGeom = qgis::make_unique< QgsPoint >( points[0] );
712  }
713  else if ( points.size() > 1 )
714  {
715  std::unique_ptr< QgsLineString > ringLine = qgis::make_unique< QgsLineString >();
716  ringLine->setPoints( points );
717  partGeom = std::move( ringLine );
718  }
719  return addPart( partGeom.release(), geomType );
720 }
721 
723 {
724  std::unique_ptr< QgsAbstractGeometry > p( part );
725  if ( !d->geometry )
726  {
727  switch ( geomType )
728  {
730  reset( qgis::make_unique< QgsMultiPoint >() );
731  break;
733  reset( qgis::make_unique< QgsMultiLineString >() );
734  break;
736  reset( qgis::make_unique< QgsMultiPolygon >() );
737  break;
738  default:
739  reset( nullptr );
740  return QgsGeometry::OperationResult::AddPartNotMultiGeometry;
741  }
742  }
743  else
744  {
745  detach();
746  }
747 
749  return QgsGeometryEditUtils::addPart( d->geometry.get(), std::move( p ) );
750 }
751 
753 {
754  if ( !d->geometry )
755  {
757  }
758  if ( newPart.isNull() || !newPart.d->geometry )
759  {
761  }
762 
763  return addPart( newPart.d->geometry->clone() );
764 }
765 
766 QgsGeometry QgsGeometry::removeInteriorRings( double minimumRingArea ) const
767 {
768  if ( !d->geometry || type() != QgsWkbTypes::PolygonGeometry )
769  {
770  return QgsGeometry();
771  }
772 
773  if ( QgsWkbTypes::isMultiType( d->geometry->wkbType() ) )
774  {
775  const QVector<QgsGeometry> parts = asGeometryCollection();
776  QVector<QgsGeometry> results;
777  results.reserve( parts.count() );
778  for ( const QgsGeometry &part : parts )
779  {
780  QgsGeometry result = part.removeInteriorRings( minimumRingArea );
781  if ( !result.isNull() )
782  results << result;
783  }
784  if ( results.isEmpty() )
785  return QgsGeometry();
786 
787  QgsGeometry first = results.takeAt( 0 );
788  for ( const QgsGeometry &result : qgis::as_const( results ) )
789  {
790  first.addPart( result );
791  }
792  return first;
793  }
794  else
795  {
796  std::unique_ptr< QgsCurvePolygon > newPoly( static_cast< QgsCurvePolygon * >( d->geometry->clone() ) );
797  newPoly->removeInteriorRings( minimumRingArea );
798  return QgsGeometry( std::move( newPoly ) );
799  }
800 }
801 
802 QgsGeometry::OperationResult QgsGeometry::translate( double dx, double dy, double dz, double dm )
803 {
804  if ( !d->geometry )
805  {
807  }
808 
809  detach();
810 
811  d->geometry->transform( QTransform::fromTranslate( dx, dy ), dz, 1.0, dm );
812  return QgsGeometry::Success;
813 }
814 
816 {
817  if ( !d->geometry )
818  {
820  }
821 
822  detach();
823 
824  QTransform t = QTransform::fromTranslate( center.x(), center.y() );
825  t.rotate( -rotation );
826  t.translate( -center.x(), -center.y() );
827  d->geometry->transform( t );
828  return QgsGeometry::Success;
829 }
830 
831 QgsGeometry::OperationResult QgsGeometry::splitGeometry( const QVector<QgsPointXY> &splitLine, QVector<QgsGeometry> &newGeometries, bool topological, QVector<QgsPointXY> &topologyTestPoints, bool splitFeature )
832 {
833  QgsPointSequence split, topology;
834  convertPointList( splitLine, split );
835  convertPointList( topologyTestPoints, topology );
836  QgsGeometry::OperationResult result = splitGeometry( split, newGeometries, topological, topology, splitFeature );
837  convertPointList( topology, topologyTestPoints );
838  return result;
839 }
840 QgsGeometry::OperationResult QgsGeometry::splitGeometry( const QgsPointSequence &splitLine, QVector<QgsGeometry> &newGeometries, bool topological, QgsPointSequence &topologyTestPoints, bool splitFeature, bool skipIntersectionTest )
841 {
842  if ( !d->geometry )
843  {
844  return QgsGeometry::OperationResult::InvalidBaseGeometry;
845  }
846 
847  QVector<QgsGeometry > newGeoms;
848  QgsLineString splitLineString( splitLine );
849 
858  splitLineString.dropZValue();
859  splitLineString.dropMValue();
860 
861  QgsGeos geos( d->geometry.get() );
862  mLastError.clear();
863  QgsGeometryEngine::EngineOperationResult result = geos.splitGeometry( splitLineString, newGeoms, topological, topologyTestPoints, &mLastError, skipIntersectionTest );
864 
865  if ( result == QgsGeometryEngine::Success )
866  {
867  if ( splitFeature )
868  *this = newGeoms.takeAt( 0 );
869  newGeometries = newGeoms;
870  }
871 
872  switch ( result )
873  {
875  return QgsGeometry::OperationResult::Success;
879  return QgsGeometry::OperationResult::GeometryEngineError;
881  return QgsGeometry::OperationResult::InvalidBaseGeometry;
883  return QgsGeometry::OperationResult::InvalidInputGeometryType;
885  return QgsGeometry::OperationResult::SplitCannotSplitPoint;
887  return QgsGeometry::OperationResult::NothingHappened;
888  //default: do not implement default to handle properly all cases
889  }
890 
891  // this should never be reached
892  Q_ASSERT( false );
894 }
895 
896 QgsGeometry::OperationResult QgsGeometry::splitGeometry( const QgsCurve *curve, QVector<QgsGeometry> &newGeometries, bool preserveCircular, bool topological, QgsPointSequence &topologyTestPoints, bool splitFeature )
897 {
898  std::unique_ptr<QgsLineString> segmentizedLine( curve->curveToLine() );
899  QgsPointSequence points;
900  segmentizedLine->points( points );
901  QgsGeometry::OperationResult result = splitGeometry( points, newGeometries, topological, topologyTestPoints, splitFeature );
902 
903  if ( result == QgsGeometry::Success )
904  {
905  if ( preserveCircular )
906  {
907  for ( int i = 0; i < newGeometries.count(); ++i )
908  newGeometries[i] = newGeometries[i].convertToCurves();
909  *this = convertToCurves();
910  }
911  }
912 
913  return result;
914 }
915 
917 {
918  if ( !d->geometry )
919  {
920  return InvalidBaseGeometry;
921  }
922 
923  QgsGeos geos( d->geometry.get() );
925  mLastError.clear();
926  std::unique_ptr< QgsAbstractGeometry > geom( geos.reshapeGeometry( reshapeLineString, &errorCode, &mLastError ) );
927  if ( errorCode == QgsGeometryEngine::Success && geom )
928  {
929  reset( std::move( geom ) );
930  return Success;
931  }
932 
933  switch ( errorCode )
934  {
936  return Success;
940  return GeometryEngineError;
942  return InvalidBaseGeometry;
945  case QgsGeometryEngine::SplitCannotSplitPoint: // should not happen
946  return GeometryEngineError;
948  return NothingHappened;
949  }
950 
951  // should not be reached
952  return GeometryEngineError;
953 }
954 
956 {
957  if ( !d->geometry || !other.d->geometry )
958  {
959  return 0;
960  }
961 
962  QgsGeos geos( d->geometry.get() );
963 
964  mLastError.clear();
965  std::unique_ptr< QgsAbstractGeometry > diffGeom( geos.intersection( other.constGet(), &mLastError ) );
966  if ( !diffGeom )
967  {
968  return 1;
969  }
970 
971  reset( std::move( diffGeom ) );
972  return 0;
973 }
974 
976 {
977  if ( !d->geometry || other.isNull() )
978  {
979  return QgsGeometry();
980  }
981 
982  QgsGeos geos( d->geometry.get() );
983 
984  mLastError.clear();
985  std::unique_ptr< QgsAbstractGeometry > diffGeom( geos.intersection( other.constGet(), &mLastError ) );
986  if ( !diffGeom )
987  {
988  QgsGeometry result;
989  result.mLastError = mLastError;
990  return result;
991  }
992 
993  return QgsGeometry( diffGeom.release() );
994 }
995 
997 {
998  if ( d->geometry )
999  {
1000  return d->geometry->boundingBox();
1001  }
1002  return QgsRectangle();
1003 }
1004 
1005 QgsGeometry QgsGeometry::orientedMinimumBoundingBox( double &area, double &angle, double &width, double &height ) const
1006 {
1007  mLastError.clear();
1008  QgsInternalGeometryEngine engine( *this );
1009  const QgsGeometry res = engine.orientedMinimumBoundingBox( area, angle, width, height );
1010  if ( res.isNull() )
1011  mLastError = engine.lastError();
1012  return res;
1013 }
1014 
1016 {
1017  double area, angle, width, height;
1018  return orientedMinimumBoundingBox( area, angle, width, height );
1019 }
1020 
1021 static QgsCircle __recMinimalEnclosingCircle( QgsMultiPointXY points, QgsMultiPointXY boundary )
1022 {
1023  auto l_boundary = boundary.length();
1024  QgsCircle circ_mec;
1025  if ( ( points.length() == 0 ) || ( l_boundary == 3 ) )
1026  {
1027  switch ( l_boundary )
1028  {
1029  case 0:
1030  circ_mec = QgsCircle();
1031  break;
1032  case 1:
1033  circ_mec = QgsCircle( QgsPoint( boundary.last() ), 0 );
1034  boundary.pop_back();
1035  break;
1036  case 2:
1037  {
1038  QgsPointXY p1 = boundary.last();
1039  boundary.pop_back();
1040  QgsPointXY p2 = boundary.last();
1041  boundary.pop_back();
1042  circ_mec = QgsCircle().from2Points( QgsPoint( p1 ), QgsPoint( p2 ) );
1043  }
1044  break;
1045  default:
1046  QgsPoint p1( boundary.at( 0 ) );
1047  QgsPoint p2( boundary.at( 1 ) );
1048  QgsPoint p3( boundary.at( 2 ) );
1049  circ_mec = QgsCircle().minimalCircleFrom3Points( p1, p2, p3 );
1050  break;
1051  }
1052  return circ_mec;
1053  }
1054  else
1055  {
1056  QgsPointXY pxy = points.last();
1057  points.pop_back();
1058  circ_mec = __recMinimalEnclosingCircle( points, boundary );
1059  QgsPoint p( pxy );
1060  if ( !circ_mec.contains( p ) )
1061  {
1062  boundary.append( pxy );
1063  circ_mec = __recMinimalEnclosingCircle( points, boundary );
1064  }
1065  }
1066  return circ_mec;
1067 }
1068 
1069 QgsGeometry QgsGeometry::minimalEnclosingCircle( QgsPointXY &center, double &radius, unsigned int segments ) const
1070 {
1071  center = QgsPointXY();
1072  radius = 0;
1073 
1074  if ( isEmpty() )
1075  {
1076  return QgsGeometry();
1077  }
1078 
1079  /* optimization */
1080  QgsGeometry hull = convexHull();
1081  if ( hull.isNull() )
1082  return QgsGeometry();
1083 
1084  QgsMultiPointXY P = hull.convertToPoint( true ).asMultiPoint();
1085  QgsMultiPointXY R;
1086 
1087  QgsCircle circ = __recMinimalEnclosingCircle( P, R );
1088  center = QgsPointXY( circ.center() );
1089  radius = circ.radius();
1090  QgsGeometry geom;
1091  geom.set( circ.toPolygon( segments ) );
1092  return geom;
1093 
1094 }
1095 
1096 QgsGeometry QgsGeometry::minimalEnclosingCircle( unsigned int segments ) const
1097 {
1098  QgsPointXY center;
1099  double radius;
1100  return minimalEnclosingCircle( center, radius, segments );
1101 
1102 }
1103 
1104 QgsGeometry QgsGeometry::orthogonalize( double tolerance, int maxIterations, double angleThreshold ) const
1105 {
1106  QgsInternalGeometryEngine engine( *this );
1107 
1108  return engine.orthogonalize( tolerance, maxIterations, angleThreshold );
1109 }
1110 
1111 QgsGeometry QgsGeometry::snappedToGrid( double hSpacing, double vSpacing, double dSpacing, double mSpacing ) const
1112 {
1113  if ( !d->geometry )
1114  {
1115  return QgsGeometry();
1116  }
1117  return QgsGeometry( d->geometry->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) );
1118 }
1119 
1120 bool QgsGeometry::removeDuplicateNodes( double epsilon, bool useZValues )
1121 {
1122  if ( !d->geometry )
1123  return false;
1124 
1125  detach();
1126  return d->geometry->removeDuplicateNodes( epsilon, useZValues );
1127 }
1128 
1130 {
1131  // fast case, check bounding boxes
1132  if ( !boundingBoxIntersects( r ) )
1133  return false;
1134 
1135  // optimise trivial case for point intersections -- the bounding box test has already given us the answer
1136  if ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::Point )
1137  {
1138  return true;
1139  }
1140 
1141  QgsGeometry g = fromRect( r );
1142  return intersects( g );
1143 }
1144 
1145 bool QgsGeometry::intersects( const QgsGeometry &geometry ) const
1146 {
1147  if ( !d->geometry || geometry.isNull() )
1148  {
1149  return false;
1150  }
1151 
1152  QgsGeos geos( d->geometry.get() );
1153  mLastError.clear();
1154  return geos.intersects( geometry.d->geometry.get(), &mLastError );
1155 }
1156 
1157 bool QgsGeometry::boundingBoxIntersects( const QgsRectangle &rectangle ) const
1158 {
1159  if ( !d->geometry )
1160  {
1161  return false;
1162  }
1163 
1164  // optimise trivial case for point intersections
1165  if ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::Point )
1166  {
1167  const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( d->geometry.get() );
1168  return rectangle.contains( QgsPointXY( point->x(), point->y() ) );
1169  }
1170 
1171  return d->geometry->boundingBox().intersects( rectangle );
1172 }
1173 
1175 {
1176  if ( !d->geometry || geometry.isNull() )
1177  {
1178  return false;
1179  }
1180 
1181  return d->geometry->boundingBox().intersects( geometry.constGet()->boundingBox() );
1182 }
1183 
1184 bool QgsGeometry::contains( const QgsPointXY *p ) const
1185 {
1186  if ( !d->geometry || !p )
1187  {
1188  return false;
1189  }
1190 
1191  QgsPoint pt( p->x(), p->y() );
1192  QgsGeos geos( d->geometry.get() );
1193  mLastError.clear();
1194  return geos.contains( &pt, &mLastError );
1195 }
1196 
1197 bool QgsGeometry::contains( const QgsGeometry &geometry ) const
1198 {
1199  if ( !d->geometry || geometry.isNull() )
1200  {
1201  return false;
1202  }
1203 
1204  QgsGeos geos( d->geometry.get() );
1205  mLastError.clear();
1206  return geos.contains( geometry.d->geometry.get(), &mLastError );
1207 }
1208 
1209 bool QgsGeometry::disjoint( const QgsGeometry &geometry ) const
1210 {
1211  if ( !d->geometry || geometry.isNull() )
1212  {
1213  return false;
1214  }
1215 
1216  QgsGeos geos( d->geometry.get() );
1217  mLastError.clear();
1218  return geos.disjoint( geometry.d->geometry.get(), &mLastError );
1219 }
1220 
1221 bool QgsGeometry::equals( const QgsGeometry &geometry ) const
1222 {
1223  if ( !d->geometry || geometry.isNull() )
1224  {
1225  return false;
1226  }
1227 
1228  // fast check - are they shared copies of the same underlying geometry?
1229  if ( d == geometry.d )
1230  return true;
1231 
1232  // fast check - distinct geometry types?
1233  if ( type() != geometry.type() )
1234  return false;
1235 
1236  // slower check - actually test the geometries
1237  return *d->geometry == *geometry.d->geometry;
1238 }
1239 
1240 bool QgsGeometry::touches( const QgsGeometry &geometry ) const
1241 {
1242  if ( !d->geometry || geometry.isNull() )
1243  {
1244  return false;
1245  }
1246 
1247  QgsGeos geos( d->geometry.get() );
1248  mLastError.clear();
1249  return geos.touches( geometry.d->geometry.get(), &mLastError );
1250 }
1251 
1252 bool QgsGeometry::overlaps( const QgsGeometry &geometry ) const
1253 {
1254  if ( !d->geometry || geometry.isNull() )
1255  {
1256  return false;
1257  }
1258 
1259  QgsGeos geos( d->geometry.get() );
1260  mLastError.clear();
1261  return geos.overlaps( geometry.d->geometry.get(), &mLastError );
1262 }
1263 
1264 bool QgsGeometry::within( const QgsGeometry &geometry ) const
1265 {
1266  if ( !d->geometry || geometry.isNull() )
1267  {
1268  return false;
1269  }
1270 
1271  QgsGeos geos( d->geometry.get() );
1272  mLastError.clear();
1273  return geos.within( geometry.d->geometry.get(), &mLastError );
1274 }
1275 
1276 bool QgsGeometry::crosses( const QgsGeometry &geometry ) const
1277 {
1278  if ( !d->geometry || geometry.isNull() )
1279  {
1280  return false;
1281  }
1282 
1283  QgsGeos geos( d->geometry.get() );
1284  mLastError.clear();
1285  return geos.crosses( geometry.d->geometry.get(), &mLastError );
1286 }
1287 
1288 QString QgsGeometry::asWkt( int precision ) const
1289 {
1290  if ( !d->geometry )
1291  {
1292  return QString();
1293  }
1294  return d->geometry->asWkt( precision );
1295 }
1296 
1297 QString QgsGeometry::asJson( int precision ) const
1298 {
1299  return QString::fromStdString( asJsonObject( precision ).dump() );
1300 }
1301 
1303 {
1304  if ( !d->geometry )
1305  {
1306  return nullptr;
1307  }
1308  return d->geometry->asJsonObject( precision );
1309 
1310 }
1311 
1312 QVector<QgsGeometry> QgsGeometry::coerceToType( const QgsWkbTypes::Type type ) const
1313 {
1314  QVector< QgsGeometry > res;
1315  if ( isNull() )
1316  return res;
1317 
1318  if ( wkbType() == type || type == QgsWkbTypes::Unknown )
1319  {
1320  res << *this;
1321  return res;
1322  }
1323 
1324  if ( type == QgsWkbTypes::NoGeometry )
1325  {
1326  return res;
1327  }
1328 
1329  QgsGeometry newGeom = *this;
1330 
1331  // Curved -> straight
1333  {
1334  newGeom = QgsGeometry( d->geometry.get()->segmentize() );
1335  }
1336 
1337  // polygon -> line
1339  newGeom.type() == QgsWkbTypes::PolygonGeometry )
1340  {
1341  // boundary gives us a (multi)line string of exterior + interior rings
1342  newGeom = QgsGeometry( newGeom.constGet()->boundary() );
1343  }
1344  // line -> polygon
1346  newGeom.type() == QgsWkbTypes::LineGeometry )
1347  {
1348  std::unique_ptr< QgsGeometryCollection > gc( QgsGeometryFactory::createCollectionOfType( type ) );
1349  const QgsGeometry source = newGeom;
1350  for ( auto part = source.const_parts_begin(); part != source.const_parts_end(); ++part )
1351  {
1352  std::unique_ptr< QgsAbstractGeometry > exterior( ( *part )->clone() );
1353  if ( QgsCurve *curve = qgsgeometry_cast< QgsCurve * >( exterior.get() ) )
1354  {
1356  {
1357  std::unique_ptr< QgsCurvePolygon > cp = qgis::make_unique< QgsCurvePolygon >();
1358  cp->setExteriorRing( curve );
1359  exterior.release();
1360  gc->addGeometry( cp.release() );
1361  }
1362  else
1363  {
1364  std::unique_ptr< QgsPolygon > p = qgis::make_unique< QgsPolygon >();
1365  p->setExteriorRing( qgsgeometry_cast< QgsLineString * >( curve ) );
1366  exterior.release();
1367  gc->addGeometry( p.release() );
1368  }
1369  }
1370  }
1371  newGeom = QgsGeometry( std::move( gc ) );
1372  }
1373 
1374  // line/polygon -> points
1376  ( newGeom.type() == QgsWkbTypes::LineGeometry ||
1377  newGeom.type() == QgsWkbTypes::PolygonGeometry ) )
1378  {
1379  // lines/polygons to a point layer, extract all vertices
1380  std::unique_ptr< QgsMultiPoint > mp = qgis::make_unique< QgsMultiPoint >();
1381  const QgsGeometry source = newGeom;
1382  QSet< QgsPoint > added;
1383  for ( auto vertex = source.vertices_begin(); vertex != source.vertices_end(); ++vertex )
1384  {
1385  if ( added.contains( *vertex ) )
1386  continue; // avoid duplicate points, e.g. start/end of rings
1387  mp->addGeometry( ( *vertex ).clone() );
1388  added.insert( *vertex );
1389  }
1390  newGeom = QgsGeometry( std::move( mp ) );
1391  }
1392 
1393  // Single -> multi
1394  if ( QgsWkbTypes::isMultiType( type ) && ! newGeom.isMultipart( ) )
1395  {
1396  newGeom.convertToMultiType();
1397  }
1398  // Drop Z/M
1399  if ( newGeom.constGet()->is3D() && ! QgsWkbTypes::hasZ( type ) )
1400  {
1401  newGeom.get()->dropZValue();
1402  }
1403  if ( newGeom.constGet()->isMeasure() && ! QgsWkbTypes::hasM( type ) )
1404  {
1405  newGeom.get()->dropMValue();
1406  }
1407  // Add Z/M back, set to 0
1408  if ( ! newGeom.constGet()->is3D() && QgsWkbTypes::hasZ( type ) )
1409  {
1410  newGeom.get()->addZValue( 0.0 );
1411  }
1412  if ( ! newGeom.constGet()->isMeasure() && QgsWkbTypes::hasM( type ) )
1413  {
1414  newGeom.get()->addMValue( 0.0 );
1415  }
1416 
1417  // Multi -> single
1418  if ( ! QgsWkbTypes::isMultiType( type ) && newGeom.isMultipart( ) )
1419  {
1420  const QgsGeometryCollection *parts( static_cast< const QgsGeometryCollection * >( newGeom.constGet() ) );
1421  QgsAttributeMap attrMap;
1422  res.reserve( parts->partCount() );
1423  for ( int i = 0; i < parts->partCount( ); i++ )
1424  {
1425  res << QgsGeometry( parts->geometryN( i )->clone() );
1426  }
1427  }
1428  else
1429  {
1430  res << newGeom;
1431  }
1432  return res;
1433 }
1434 
1436 {
1437  switch ( destType )
1438  {
1440  return convertToPoint( destMultipart );
1441 
1443  return convertToLine( destMultipart );
1444 
1446  return convertToPolygon( destMultipart );
1447 
1448  default:
1449  return QgsGeometry();
1450  }
1451 }
1452 
1454 {
1455  if ( !d->geometry )
1456  {
1457  return false;
1458  }
1459 
1460  if ( isMultipart() ) //already multitype, no need to convert
1461  {
1462  return true;
1463  }
1464 
1465  std::unique_ptr< QgsAbstractGeometry >geom = QgsGeometryFactory::geomFromWkbType( QgsWkbTypes::multiType( d->geometry->wkbType() ) );
1466  QgsGeometryCollection *multiGeom = qgsgeometry_cast<QgsGeometryCollection *>( geom.get() );
1467  if ( !multiGeom )
1468  {
1469  return false;
1470  }
1471 
1472  //try to avoid cloning existing geometry whenever we can
1473 
1474  //want to see a magic trick?... gather round kiddies...
1475  detach(); // maybe a clone, hopefully not if we're the only ref to the private data
1476  // now we cheat a bit and steal the private geometry and add it direct to the multigeom
1477  // we can do this because we're the only ref to this geometry, guaranteed by the detach call above
1478  multiGeom->addGeometry( d->geometry.release() );
1479  // and replace it with the multi geometry.
1480  // TADA! a clone free conversion in some cases
1481  d->geometry = std::move( geom );
1482  return true;
1483 }
1484 
1486 {
1487  if ( !d->geometry )
1488  {
1489  return false;
1490  }
1491 
1492  if ( !isMultipart() ) //already single part, no need to convert
1493  {
1494  return true;
1495  }
1496 
1497  QgsGeometryCollection *multiGeom = qgsgeometry_cast<QgsGeometryCollection *>( d->geometry.get() );
1498  if ( !multiGeom || multiGeom->partCount() < 1 )
1499  return false;
1500 
1501  std::unique_ptr< QgsAbstractGeometry > firstPart( multiGeom->geometryN( 0 )->clone() );
1502  reset( std::move( firstPart ) );
1503  return true;
1504 }
1505 
1506 
1508 {
1509  const QgsGeometryCollection *origGeom = qgsgeometry_cast<const QgsGeometryCollection *>( constGet() );
1510  if ( !origGeom )
1511  return false;
1512 
1513  std::unique_ptr<QgsGeometryCollection> resGeom;
1514  switch ( geomType )
1515  {
1517  resGeom = qgis::make_unique<QgsMultiPoint>();
1518  break;
1520  resGeom = qgis::make_unique<QgsMultiLineString>();
1521  break;
1523  resGeom = qgis::make_unique<QgsMultiPolygon>();
1524  break;
1525  default:
1526  break;
1527  }
1528  if ( !resGeom )
1529  return false;
1530 
1531  resGeom->reserve( origGeom->numGeometries() );
1532  for ( int i = 0; i < origGeom->numGeometries(); ++i )
1533  {
1534  const QgsAbstractGeometry *g = origGeom->geometryN( i );
1535  if ( QgsWkbTypes::geometryType( g->wkbType() ) == geomType )
1536  resGeom->addGeometry( g->clone() );
1537  }
1538 
1539  set( resGeom.release() );
1540  return true;
1541 }
1542 
1543 
1545 {
1546  if ( !d->geometry || QgsWkbTypes::flatType( d->geometry->wkbType() ) != QgsWkbTypes::Point )
1547  {
1548  return QgsPointXY();
1549  }
1550  QgsPoint *pt = qgsgeometry_cast<QgsPoint *>( d->geometry.get() );
1551  if ( !pt )
1552  {
1553  return QgsPointXY();
1554  }
1555 
1556  return QgsPointXY( pt->x(), pt->y() );
1557 }
1558 
1560 {
1561  QgsPolylineXY polyLine;
1562  if ( !d->geometry )
1563  {
1564  return polyLine;
1565  }
1566 
1567  bool doSegmentation = ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::CompoundCurve
1569  std::unique_ptr< QgsLineString > segmentizedLine;
1570  QgsLineString *line = nullptr;
1571  if ( doSegmentation )
1572  {
1573  QgsCurve *curve = qgsgeometry_cast<QgsCurve *>( d->geometry.get() );
1574  if ( !curve )
1575  {
1576  return polyLine;
1577  }
1578  segmentizedLine.reset( curve->curveToLine() );
1579  line = segmentizedLine.get();
1580  }
1581  else
1582  {
1583  line = qgsgeometry_cast<QgsLineString *>( d->geometry.get() );
1584  if ( !line )
1585  {
1586  return polyLine;
1587  }
1588  }
1589 
1590  int nVertices = line->numPoints();
1591  polyLine.resize( nVertices );
1592  QgsPointXY *data = polyLine.data();
1593  const double *xData = line->xData();
1594  const double *yData = line->yData();
1595  for ( int i = 0; i < nVertices; ++i )
1596  {
1597  data->setX( *xData++ );
1598  data->setY( *yData++ );
1599  data++;
1600  }
1601 
1602  return polyLine;
1603 }
1604 
1606 {
1607  if ( !d->geometry )
1608  return QgsPolygonXY();
1609 
1610  bool doSegmentation = ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::CurvePolygon );
1611 
1612  QgsPolygon *p = nullptr;
1613  std::unique_ptr< QgsPolygon > segmentized;
1614  if ( doSegmentation )
1615  {
1616  QgsCurvePolygon *curvePoly = qgsgeometry_cast<QgsCurvePolygon *>( d->geometry.get() );
1617  if ( !curvePoly )
1618  {
1619  return QgsPolygonXY();
1620  }
1621  segmentized.reset( curvePoly->toPolygon() );
1622  p = segmentized.get();
1623  }
1624  else
1625  {
1626  p = qgsgeometry_cast<QgsPolygon *>( d->geometry.get() );
1627  }
1628 
1629  if ( !p )
1630  {
1631  return QgsPolygonXY();
1632  }
1633 
1634  QgsPolygonXY polygon;
1635  convertPolygon( *p, polygon );
1636 
1637  return polygon;
1638 }
1639 
1641 {
1642  if ( !d->geometry || QgsWkbTypes::flatType( d->geometry->wkbType() ) != QgsWkbTypes::MultiPoint )
1643  {
1644  return QgsMultiPointXY();
1645  }
1646 
1647  const QgsMultiPoint *mp = qgsgeometry_cast<QgsMultiPoint *>( d->geometry.get() );
1648  if ( !mp )
1649  {
1650  return QgsMultiPointXY();
1651  }
1652 
1653  int nPoints = mp->numGeometries();
1654  QgsMultiPointXY multiPoint( nPoints );
1655  for ( int i = 0; i < nPoints; ++i )
1656  {
1657  const QgsPoint *pt = mp->pointN( i );
1658  multiPoint[i].setX( pt->x() );
1659  multiPoint[i].setY( pt->y() );
1660  }
1661  return multiPoint;
1662 }
1663 
1665 {
1666  if ( !d->geometry )
1667  {
1668  return QgsMultiPolylineXY();
1669  }
1670 
1671  QgsGeometryCollection *geomCollection = qgsgeometry_cast<QgsGeometryCollection *>( d->geometry.get() );
1672  if ( !geomCollection )
1673  {
1674  return QgsMultiPolylineXY();
1675  }
1676 
1677  int nLines = geomCollection->numGeometries();
1678  if ( nLines < 1 )
1679  {
1680  return QgsMultiPolylineXY();
1681  }
1682 
1683  QgsMultiPolylineXY mpl;
1684  mpl.reserve( nLines );
1685  for ( int i = 0; i < nLines; ++i )
1686  {
1687  const QgsLineString *line = qgsgeometry_cast<const QgsLineString *>( geomCollection->geometryN( i ) );
1688  std::unique_ptr< QgsLineString > segmentized;
1689  if ( !line )
1690  {
1691  const QgsCurve *curve = qgsgeometry_cast<const QgsCurve *>( geomCollection->geometryN( i ) );
1692  if ( !curve )
1693  {
1694  continue;
1695  }
1696  segmentized.reset( curve->curveToLine() );
1697  line = segmentized.get();
1698  }
1699 
1700  QgsPolylineXY polyLine;
1701  int nVertices = line->numPoints();
1702  polyLine.resize( nVertices );
1703  QgsPointXY *data = polyLine.data();
1704  const double *xData = line->xData();
1705  const double *yData = line->yData();
1706  for ( int i = 0; i < nVertices; ++i )
1707  {
1708  data->setX( *xData++ );
1709  data->setY( *yData++ );
1710  data++;
1711  }
1712  mpl.append( polyLine );
1713  }
1714  return mpl;
1715 }
1716 
1718 {
1719  if ( !d->geometry )
1720  {
1721  return QgsMultiPolygonXY();
1722  }
1723 
1724  QgsGeometryCollection *geomCollection = qgsgeometry_cast<QgsGeometryCollection *>( d->geometry.get() );
1725  if ( !geomCollection )
1726  {
1727  return QgsMultiPolygonXY();
1728  }
1729 
1730  int nPolygons = geomCollection->numGeometries();
1731  if ( nPolygons < 1 )
1732  {
1733  return QgsMultiPolygonXY();
1734  }
1735 
1736  QgsMultiPolygonXY mp;
1737  for ( int i = 0; i < nPolygons; ++i )
1738  {
1739  const QgsPolygon *polygon = qgsgeometry_cast<const QgsPolygon *>( geomCollection->geometryN( i ) );
1740  if ( !polygon )
1741  {
1742  const QgsCurvePolygon *cPolygon = qgsgeometry_cast<const QgsCurvePolygon *>( geomCollection->geometryN( i ) );
1743  if ( cPolygon )
1744  {
1745  polygon = cPolygon->toPolygon();
1746  }
1747  else
1748  {
1749  continue;
1750  }
1751  }
1752 
1753  QgsPolygonXY poly;
1754  convertPolygon( *polygon, poly );
1755  mp.append( poly );
1756  }
1757  return mp;
1758 }
1759 
1760 double QgsGeometry::area() const
1761 {
1762  if ( !d->geometry )
1763  {
1764  return -1.0;
1765  }
1766  QgsGeos g( d->geometry.get() );
1767 
1768 #if 0
1769  //debug: compare geos area with calculation in QGIS
1770  double geosArea = g.area();
1771  double qgisArea = 0;
1772  QgsSurface *surface = qgsgeometry_cast<QgsSurface *>( d->geometry );
1773  if ( surface )
1774  {
1775  qgisArea = surface->area();
1776  }
1777 #endif
1778 
1779  mLastError.clear();
1780  return g.area( &mLastError );
1781 }
1782 
1783 double QgsGeometry::length() const
1784 {
1785  if ( !d->geometry )
1786  {
1787  return -1.0;
1788  }
1789  QgsGeos g( d->geometry.get() );
1790  mLastError.clear();
1791  return g.length( &mLastError );
1792 }
1793 
1794 double QgsGeometry::distance( const QgsGeometry &geom ) const
1795 {
1796  if ( !d->geometry || !geom.d->geometry )
1797  {
1798  return -1.0;
1799  }
1800 
1801  // avoid calling geos for trivial point-to-point distance calculations
1803  {
1804  return qgsgeometry_cast< const QgsPoint * >( d->geometry.get() )->distance( *qgsgeometry_cast< const QgsPoint * >( geom.constGet() ) );
1805  }
1806 
1807  QgsGeos g( d->geometry.get() );
1808  mLastError.clear();
1809  return g.distance( geom.d->geometry.get(), &mLastError );
1810 }
1811 
1812 double QgsGeometry::hausdorffDistance( const QgsGeometry &geom ) const
1813 {
1814  if ( !d->geometry || !geom.d->geometry )
1815  {
1816  return -1.0;
1817  }
1818 
1819  QgsGeos g( d->geometry.get() );
1820  mLastError.clear();
1821  return g.hausdorffDistance( geom.d->geometry.get(), &mLastError );
1822 }
1823 
1824 double QgsGeometry::hausdorffDistanceDensify( const QgsGeometry &geom, double densifyFraction ) const
1825 {
1826  if ( !d->geometry || !geom.d->geometry )
1827  {
1828  return -1.0;
1829  }
1830 
1831  QgsGeos g( d->geometry.get() );
1832  mLastError.clear();
1833  return g.hausdorffDistanceDensify( geom.d->geometry.get(), densifyFraction, &mLastError );
1834 }
1835 
1837 {
1838  if ( !d->geometry || d->geometry.get()->isEmpty() )
1840  return d->geometry->vertices_begin();
1841 }
1842 
1844 {
1845  if ( !d->geometry || d->geometry.get()->isEmpty() )
1847  return d->geometry->vertices_end();
1848 }
1849 
1851 {
1852  if ( !d->geometry || d->geometry.get()->isEmpty() )
1853  return QgsVertexIterator();
1854  return QgsVertexIterator( d->geometry.get() );
1855 }
1856 
1858 {
1859  if ( !d->geometry )
1861 
1862  detach();
1863  return d->geometry->parts_begin();
1864 }
1865 
1867 {
1868  if ( !d->geometry )
1870  return d->geometry->parts_end();
1871 }
1872 
1874 {
1875  if ( !d->geometry )
1877  return d->geometry->const_parts_begin();
1878 }
1879 
1881 {
1882  if ( !d->geometry )
1884  return d->geometry->const_parts_end();
1885 }
1886 
1888 {
1889  if ( !d->geometry )
1890  return QgsGeometryPartIterator();
1891 
1892  detach();
1893  return QgsGeometryPartIterator( d->geometry.get() );
1894 }
1895 
1897 {
1898  if ( !d->geometry )
1900 
1901  return QgsGeometryConstPartIterator( d->geometry.get() );
1902 }
1903 
1904 QgsGeometry QgsGeometry::buffer( double distance, int segments ) const
1905 {
1906  if ( !d->geometry )
1907  {
1908  return QgsGeometry();
1909  }
1910 
1911  QgsGeos g( d->geometry.get() );
1912  mLastError.clear();
1913  std::unique_ptr<QgsAbstractGeometry> geom( g.buffer( distance, segments, &mLastError ) );
1914  if ( !geom )
1915  {
1916  QgsGeometry result;
1917  result.mLastError = mLastError;
1918  return result;
1919  }
1920  return QgsGeometry( std::move( geom ) );
1921 }
1922 
1923 QgsGeometry QgsGeometry::buffer( double distance, int segments, EndCapStyle endCapStyle, JoinStyle joinStyle, double miterLimit ) const
1924 {
1925  if ( !d->geometry )
1926  {
1927  return QgsGeometry();
1928  }
1929 
1930  QgsGeos g( d->geometry.get() );
1931  mLastError.clear();
1932  QgsAbstractGeometry *geom = g.buffer( distance, segments, endCapStyle, joinStyle, miterLimit, &mLastError );
1933  if ( !geom )
1934  {
1935  QgsGeometry result;
1936  result.mLastError = mLastError;
1937  return result;
1938  }
1939  return QgsGeometry( geom );
1940 }
1941 
1942 QgsGeometry QgsGeometry::offsetCurve( double distance, int segments, JoinStyle joinStyle, double miterLimit ) const
1943 {
1944  if ( !d->geometry || type() != QgsWkbTypes::LineGeometry )
1945  {
1946  return QgsGeometry();
1947  }
1948 
1949  if ( QgsWkbTypes::isMultiType( d->geometry->wkbType() ) )
1950  {
1951  const QVector<QgsGeometry> parts = asGeometryCollection();
1952  QVector<QgsGeometry> results;
1953  results.reserve( parts.count() );
1954  for ( const QgsGeometry &part : parts )
1955  {
1956  QgsGeometry result = part.offsetCurve( distance, segments, joinStyle, miterLimit );
1957  if ( !result.isNull() )
1958  results << result;
1959  }
1960  if ( results.isEmpty() )
1961  return QgsGeometry();
1962 
1963  QgsGeometry first = results.takeAt( 0 );
1964  for ( const QgsGeometry &result : qgis::as_const( results ) )
1965  {
1966  first.addPart( result );
1967  }
1968  return first;
1969  }
1970  else
1971  {
1972  QgsGeos geos( d->geometry.get() );
1973  mLastError.clear();
1974 
1975  // GEOS can flip the curve orientation in some circumstances. So record previous orientation and correct if required
1976  const QgsCurve::Orientation prevOrientation = qgsgeometry_cast< const QgsCurve * >( d->geometry.get() )->orientation();
1977 
1978  std::unique_ptr< QgsAbstractGeometry > offsetGeom( geos.offsetCurve( distance, segments, joinStyle, miterLimit, &mLastError ) );
1979  if ( !offsetGeom )
1980  {
1981  QgsGeometry result;
1982  result.mLastError = mLastError;
1983  return result;
1984  }
1985 
1986  if ( const QgsCurve *offsetCurve = qgsgeometry_cast< const QgsCurve * >( offsetGeom.get() ) )
1987  {
1988  const QgsCurve::Orientation newOrientation = offsetCurve->orientation();
1989  if ( newOrientation != prevOrientation )
1990  {
1991  // GEOS has flipped line orientation, flip it back
1992  std::unique_ptr< QgsAbstractGeometry > flipped( offsetCurve->reversed() );
1993  offsetGeom = std::move( flipped );
1994  }
1995  }
1996  return QgsGeometry( std::move( offsetGeom ) );
1997  }
1998 }
1999 
2000 QgsGeometry QgsGeometry::singleSidedBuffer( double distance, int segments, BufferSide side, JoinStyle joinStyle, double miterLimit ) const
2001 {
2002  if ( !d->geometry || type() != QgsWkbTypes::LineGeometry )
2003  {
2004  return QgsGeometry();
2005  }
2006 
2007  if ( QgsWkbTypes::isMultiType( d->geometry->wkbType() ) )
2008  {
2009  const QVector<QgsGeometry> parts = asGeometryCollection();
2010  QVector<QgsGeometry> results;
2011  results.reserve( parts.count() );
2012  for ( const QgsGeometry &part : parts )
2013  {
2014  QgsGeometry result = part.singleSidedBuffer( distance, segments, side, joinStyle, miterLimit );
2015  if ( !result.isNull() )
2016  results << result;
2017  }
2018  if ( results.isEmpty() )
2019  return QgsGeometry();
2020 
2021  QgsGeometry first = results.takeAt( 0 );
2022  for ( const QgsGeometry &result : qgis::as_const( results ) )
2023  {
2024  first.addPart( result );
2025  }
2026  return first;
2027  }
2028  else
2029  {
2030  QgsGeos geos( d->geometry.get() );
2031  mLastError.clear();
2032  std::unique_ptr< QgsAbstractGeometry > bufferGeom = geos.singleSidedBuffer( distance, segments, side,
2033  joinStyle, miterLimit, &mLastError );
2034  if ( !bufferGeom )
2035  {
2036  QgsGeometry result;
2037  result.mLastError = mLastError;
2038  return result;
2039  }
2040  return QgsGeometry( std::move( bufferGeom ) );
2041  }
2042 }
2043 
2044 QgsGeometry QgsGeometry::taperedBuffer( double startWidth, double endWidth, int segments ) const
2045 {
2046  QgsInternalGeometryEngine engine( *this );
2047 
2048  return engine.taperedBuffer( startWidth, endWidth, segments );
2049 }
2050 
2052 {
2053  QgsInternalGeometryEngine engine( *this );
2054 
2055  return engine.variableWidthBufferByM( segments );
2056 }
2057 
2058 QgsGeometry QgsGeometry::extendLine( double startDistance, double endDistance ) const
2059 {
2060  if ( !d->geometry || type() != QgsWkbTypes::LineGeometry )
2061  {
2062  return QgsGeometry();
2063  }
2064 
2065  if ( QgsWkbTypes::isMultiType( d->geometry->wkbType() ) )
2066  {
2067  const QVector<QgsGeometry> parts = asGeometryCollection();
2068  QVector<QgsGeometry> results;
2069  results.reserve( parts.count() );
2070  for ( const QgsGeometry &part : parts )
2071  {
2072  QgsGeometry result = part.extendLine( startDistance, endDistance );
2073  if ( !result.isNull() )
2074  results << result;
2075  }
2076  if ( results.isEmpty() )
2077  return QgsGeometry();
2078 
2079  QgsGeometry first = results.takeAt( 0 );
2080  for ( const QgsGeometry &result : qgis::as_const( results ) )
2081  {
2082  first.addPart( result );
2083  }
2084  return first;
2085  }
2086  else
2087  {
2088  QgsLineString *line = qgsgeometry_cast< QgsLineString * >( d->geometry.get() );
2089  if ( !line )
2090  return QgsGeometry();
2091 
2092  std::unique_ptr< QgsLineString > newLine( line->clone() );
2093  newLine->extend( startDistance, endDistance );
2094  return QgsGeometry( std::move( newLine ) );
2095  }
2096 }
2097 
2098 QgsGeometry QgsGeometry::simplify( double tolerance ) const
2099 {
2100  if ( !d->geometry )
2101  {
2102  return QgsGeometry();
2103  }
2104 
2105  QgsGeos geos( d->geometry.get() );
2106  mLastError.clear();
2107  std::unique_ptr< QgsAbstractGeometry > simplifiedGeom( geos.simplify( tolerance, &mLastError ) );
2108  if ( !simplifiedGeom )
2109  {
2110  QgsGeometry result;
2111  result.mLastError = mLastError;
2112  return result;
2113  }
2114  return QgsGeometry( std::move( simplifiedGeom ) );
2115 }
2116 
2117 QgsGeometry QgsGeometry::densifyByCount( int extraNodesPerSegment ) const
2118 {
2119  QgsInternalGeometryEngine engine( *this );
2120 
2121  return engine.densifyByCount( extraNodesPerSegment );
2122 }
2123 
2125 {
2126  QgsInternalGeometryEngine engine( *this );
2127 
2128  return engine.densifyByDistance( distance );
2129 }
2130 
2131 QgsGeometry QgsGeometry::convertToCurves( double distanceTolerance, double angleTolerance ) const
2132 {
2133  QgsInternalGeometryEngine engine( *this );
2134 
2135  return engine.convertToCurves( distanceTolerance, angleTolerance );
2136 }
2137 
2139 {
2140  if ( !d->geometry )
2141  {
2142  return QgsGeometry();
2143  }
2144 
2145  // avoid calling geos for trivial point centroids
2146  if ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::Point )
2147  {
2148  QgsGeometry c = *this;
2149  c.get()->dropZValue();
2150  c.get()->dropMValue();
2151  return c;
2152  }
2153 
2154  QgsGeos geos( d->geometry.get() );
2155 
2156  mLastError.clear();
2157  QgsGeometry result( geos.centroid( &mLastError ) );
2158  result.mLastError = mLastError;
2159  return result;
2160 }
2161 
2163 {
2164  if ( !d->geometry )
2165  {
2166  return QgsGeometry();
2167  }
2168 
2169  QgsGeos geos( d->geometry.get() );
2170 
2171  mLastError.clear();
2172  QgsGeometry result( geos.pointOnSurface( &mLastError ) );
2173  result.mLastError = mLastError;
2174  return result;
2175 }
2176 
2177 QgsGeometry QgsGeometry::poleOfInaccessibility( double precision, double *distanceToBoundary ) const
2178 {
2179  QgsInternalGeometryEngine engine( *this );
2180 
2181  return engine.poleOfInaccessibility( precision, distanceToBoundary );
2182 }
2183 
2185 {
2186  if ( !d->geometry )
2187  {
2188  return QgsGeometry();
2189  }
2190  QgsGeos geos( d->geometry.get() );
2191  mLastError.clear();
2192  std::unique_ptr< QgsAbstractGeometry > cHull( geos.convexHull( &mLastError ) );
2193  if ( !cHull )
2194  {
2195  QgsGeometry geom;
2196  geom.mLastError = mLastError;
2197  return geom;
2198  }
2199  return QgsGeometry( std::move( cHull ) );
2200 }
2201 
2202 QgsGeometry QgsGeometry::voronoiDiagram( const QgsGeometry &extent, double tolerance, bool edgesOnly ) const
2203 {
2204  if ( !d->geometry )
2205  {
2206  return QgsGeometry();
2207  }
2208 
2209  QgsGeos geos( d->geometry.get() );
2210  mLastError.clear();
2211  QgsGeometry result = geos.voronoiDiagram( extent.constGet(), tolerance, edgesOnly, &mLastError );
2212  result.mLastError = mLastError;
2213  return result;
2214 }
2215 
2216 QgsGeometry QgsGeometry::delaunayTriangulation( double tolerance, bool edgesOnly ) const
2217 {
2218  if ( !d->geometry )
2219  {
2220  return QgsGeometry();
2221  }
2222 
2223  QgsGeos geos( d->geometry.get() );
2224  mLastError.clear();
2225  QgsGeometry result = geos.delaunayTriangulation( tolerance, edgesOnly );
2226  result.mLastError = mLastError;
2227  return result;
2228 }
2229 
2231 {
2232  if ( !d->geometry )
2233  {
2234  return QgsGeometry();
2235  }
2236 
2237  const QgsAbstractGeometry *geom = d->geometry.get();
2238  std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2239  if ( QgsWkbTypes::isCurvedType( d->geometry->wkbType() ) )
2240  {
2241  segmentizedCopy.reset( d->geometry->segmentize() );
2242  geom = segmentizedCopy.get();
2243  }
2244 
2245  QgsGeos geos( geom );
2246  mLastError.clear();
2247  std::unique_ptr< QgsAbstractGeometry > result( geos.subdivide( maxNodes, &mLastError ) );
2248  if ( !result )
2249  {
2250  QgsGeometry geom;
2251  geom.mLastError = mLastError;
2252  return geom;
2253  }
2254  return QgsGeometry( std::move( result ) );
2255 }
2256 
2257 QgsGeometry QgsGeometry::interpolate( double distance ) const
2258 {
2259  if ( !d->geometry )
2260  {
2261  return QgsGeometry();
2262  }
2263 
2264  QgsGeometry line = *this;
2265  if ( type() == QgsWkbTypes::PointGeometry )
2266  return QgsGeometry();
2267  else if ( type() == QgsWkbTypes::PolygonGeometry )
2268  {
2269  line = QgsGeometry( d->geometry->boundary() );
2270  }
2271 
2272  const QgsCurve *curve = nullptr;
2273  if ( line.isMultipart() )
2274  {
2275  // if multi part, iterate through parts to find target part
2276  const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( line.constGet() );
2277  for ( int part = 0; part < collection->numGeometries(); ++part )
2278  {
2279  const QgsCurve *candidate = qgsgeometry_cast< const QgsCurve * >( collection->geometryN( part ) );
2280  if ( !candidate )
2281  continue;
2282  const double candidateLength = candidate->length();
2283  if ( candidateLength >= distance )
2284  {
2285  curve = candidate;
2286  break;
2287  }
2288 
2289  distance -= candidateLength;
2290  }
2291  }
2292  else
2293  {
2294  curve = qgsgeometry_cast< const QgsCurve * >( line.constGet() );
2295  }
2296  if ( !curve )
2297  return QgsGeometry();
2298 
2299  std::unique_ptr< QgsPoint > result( curve->interpolatePoint( distance ) );
2300  if ( !result )
2301  {
2302  return QgsGeometry();
2303  }
2304  return QgsGeometry( std::move( result ) );
2305 }
2306 
2307 double QgsGeometry::lineLocatePoint( const QgsGeometry &point ) const
2308 {
2309  if ( type() != QgsWkbTypes::LineGeometry )
2310  return -1;
2311 
2312  if ( QgsWkbTypes::flatType( point.wkbType() ) != QgsWkbTypes::Point )
2313  return -1;
2314 
2315  QgsGeometry segmentized = *this;
2317  {
2318  segmentized = QgsGeometry( static_cast< QgsCurve * >( d->geometry.get() )->segmentize() );
2319  }
2320 
2321  QgsGeos geos( d->geometry.get() );
2322  mLastError.clear();
2323  return geos.lineLocatePoint( *( static_cast< QgsPoint * >( point.d->geometry.get() ) ), &mLastError );
2324 }
2325 
2326 double QgsGeometry::interpolateAngle( double distance ) const
2327 {
2328  if ( !d->geometry )
2329  return 0.0;
2330 
2331  // always operate on segmentized geometries
2332  QgsGeometry segmentized = *this;
2334  {
2335  segmentized = QgsGeometry( static_cast< QgsCurve * >( d->geometry.get() )->segmentize() );
2336  }
2337 
2338  QgsVertexId previous;
2339  QgsVertexId next;
2340  if ( !QgsGeometryUtils::verticesAtDistance( *segmentized.constGet(), distance, previous, next ) )
2341  return 0.0;
2342 
2343  if ( previous == next )
2344  {
2345  // distance coincided exactly with a vertex
2346  QgsVertexId v2 = previous;
2347  QgsVertexId v1;
2348  QgsVertexId v3;
2349  segmentized.constGet()->adjacentVertices( v2, v1, v3 );
2350  if ( v1.isValid() && v3.isValid() )
2351  {
2352  QgsPoint p1 = segmentized.constGet()->vertexAt( v1 );
2353  QgsPoint p2 = segmentized.constGet()->vertexAt( v2 );
2354  QgsPoint p3 = segmentized.constGet()->vertexAt( v3 );
2355  double angle1 = QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
2356  double angle2 = QgsGeometryUtils::lineAngle( p2.x(), p2.y(), p3.x(), p3.y() );
2357  return QgsGeometryUtils::averageAngle( angle1, angle2 );
2358  }
2359  else if ( v3.isValid() )
2360  {
2361  QgsPoint p1 = segmentized.constGet()->vertexAt( v2 );
2362  QgsPoint p2 = segmentized.constGet()->vertexAt( v3 );
2363  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
2364  }
2365  else
2366  {
2367  QgsPoint p1 = segmentized.constGet()->vertexAt( v1 );
2368  QgsPoint p2 = segmentized.constGet()->vertexAt( v2 );
2369  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
2370  }
2371  }
2372  else
2373  {
2374  QgsPoint p1 = segmentized.constGet()->vertexAt( previous );
2375  QgsPoint p2 = segmentized.constGet()->vertexAt( next );
2376  return QgsGeometryUtils::lineAngle( p1.x(), p1.y(), p2.x(), p2.y() );
2377  }
2378 }
2379 
2381 {
2382  if ( !d->geometry || geometry.isNull() )
2383  {
2384  return QgsGeometry();
2385  }
2386 
2387  QgsGeos geos( d->geometry.get() );
2388 
2389  mLastError.clear();
2390  std::unique_ptr< QgsAbstractGeometry > resultGeom( geos.intersection( geometry.d->geometry.get(), &mLastError ) );
2391 
2392  if ( !resultGeom )
2393  {
2394  QgsGeometry geom;
2395  geom.mLastError = mLastError;
2396  return geom;
2397  }
2398 
2399  return QgsGeometry( std::move( resultGeom ) );
2400 }
2401 
2403 {
2404  if ( !d->geometry || geometry.isNull() )
2405  {
2406  return QgsGeometry();
2407  }
2408 
2409  QgsGeos geos( d->geometry.get() );
2410  mLastError.clear();
2411  std::unique_ptr< QgsAbstractGeometry > resultGeom( geos.combine( geometry.d->geometry.get(), &mLastError ) );
2412  if ( !resultGeom )
2413  {
2414  QgsGeometry geom;
2415  geom.mLastError = mLastError;
2416  return geom;
2417  }
2418  return QgsGeometry( std::move( resultGeom ) );
2419 }
2420 
2422 {
2423  if ( !d->geometry )
2424  {
2425  return QgsGeometry();
2426  }
2427 
2428  if ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::LineString )
2429  {
2430  // special case - a single linestring was passed
2431  return QgsGeometry( *this );
2432  }
2433 
2434  QgsGeos geos( d->geometry.get() );
2435  mLastError.clear();
2436  QgsGeometry result = geos.mergeLines( &mLastError );
2437  result.mLastError = mLastError;
2438  return result;
2439 }
2440 
2442 {
2443  if ( !d->geometry || geometry.isNull() )
2444  {
2445  return QgsGeometry();
2446  }
2447 
2448  QgsGeos geos( d->geometry.get() );
2449 
2450  mLastError.clear();
2451  std::unique_ptr< QgsAbstractGeometry > resultGeom( geos.difference( geometry.d->geometry.get(), &mLastError ) );
2452  if ( !resultGeom )
2453  {
2454  QgsGeometry geom;
2455  geom.mLastError = mLastError;
2456  return geom;
2457  }
2458  return QgsGeometry( std::move( resultGeom ) );
2459 }
2460 
2462 {
2463  if ( !d->geometry || geometry.isNull() )
2464  {
2465  return QgsGeometry();
2466  }
2467 
2468  QgsGeos geos( d->geometry.get() );
2469 
2470  mLastError.clear();
2471  std::unique_ptr< QgsAbstractGeometry > resultGeom( geos.symDifference( geometry.d->geometry.get(), &mLastError ) );
2472  if ( !resultGeom )
2473  {
2474  QgsGeometry geom;
2475  geom.mLastError = mLastError;
2476  return geom;
2477  }
2478  return QgsGeometry( std::move( resultGeom ) );
2479 }
2480 
2481 QgsGeometry QgsGeometry::extrude( double x, double y )
2482 {
2483  QgsInternalGeometryEngine engine( *this );
2484 
2485  return engine.extrude( x, y );
2486 }
2487 
2489 
2490 QVector<QgsPointXY> QgsGeometry::randomPointsInPolygon( int count, const std::function< bool( const QgsPointXY & ) > &acceptPoint, unsigned long seed, QgsFeedback *feedback, int maxTriesPerPoint ) const
2491 {
2493  return QVector< QgsPointXY >();
2494 
2495  return QgsInternalGeometryEngine::randomPointsInPolygon( *this, count, acceptPoint, seed, feedback, maxTriesPerPoint );
2496 }
2497 
2498 QVector<QgsPointXY> QgsGeometry::randomPointsInPolygon( int count, unsigned long seed, QgsFeedback *feedback ) const
2499 {
2501  return QVector< QgsPointXY >();
2502 
2503  return QgsInternalGeometryEngine::randomPointsInPolygon( *this, count, []( const QgsPointXY & ) { return true; }, seed, feedback, 0 );
2504 }
2506 
2507 int QgsGeometry::wkbSize( QgsAbstractGeometry::WkbFlags flags ) const
2508 {
2509  return d->geometry ? d->geometry->wkbSize( flags ) : 0;
2510 }
2511 
2512 QByteArray QgsGeometry::asWkb( QgsAbstractGeometry::WkbFlags flags ) const
2513 {
2514  return d->geometry ? d->geometry->asWkb( flags ) : QByteArray();
2515 }
2516 
2517 QVector<QgsGeometry> QgsGeometry::asGeometryCollection() const
2518 {
2519  QVector<QgsGeometry> geometryList;
2520  if ( !d->geometry )
2521  {
2522  return geometryList;
2523  }
2524 
2525  QgsGeometryCollection *gc = qgsgeometry_cast<QgsGeometryCollection *>( d->geometry.get() );
2526  if ( gc )
2527  {
2528  int numGeom = gc->numGeometries();
2529  geometryList.reserve( numGeom );
2530  for ( int i = 0; i < numGeom; ++i )
2531  {
2532  geometryList.append( QgsGeometry( gc->geometryN( i )->clone() ) );
2533  }
2534  }
2535  else //a singlepart geometry
2536  {
2537  geometryList.append( *this );
2538  }
2539 
2540  return geometryList;
2541 }
2542 
2543 QPointF QgsGeometry::asQPointF() const
2544 {
2545  QgsPointXY point = asPoint();
2546  return point.toQPointF();
2547 }
2548 
2549 QPolygonF QgsGeometry::asQPolygonF() const
2550 {
2551  const QgsAbstractGeometry *part = constGet();
2552 
2553  // if a geometry collection, get first part only
2554  if ( const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection *>( part ) )
2555  {
2556  if ( collection->numGeometries() > 0 )
2557  part = collection->geometryN( 0 );
2558  else
2559  return QPolygonF();
2560  }
2561 
2562  if ( const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( part ) )
2563  return curve->asQPolygonF();
2564  else if ( const QgsCurvePolygon *polygon = qgsgeometry_cast< const QgsCurvePolygon * >( part ) )
2565  return polygon->exteriorRing() ? polygon->exteriorRing()->asQPolygonF() : QPolygonF();
2566  return QPolygonF();
2567 }
2568 
2569 bool QgsGeometry::deleteRing( int ringNum, int partNum )
2570 {
2571  if ( !d->geometry )
2572  {
2573  return false;
2574  }
2575 
2576  detach();
2577  bool ok = QgsGeometryEditUtils::deleteRing( d->geometry.get(), ringNum, partNum );
2578  return ok;
2579 }
2580 
2581 bool QgsGeometry::deletePart( int partNum )
2582 {
2583  if ( !d->geometry )
2584  {
2585  return false;
2586  }
2587 
2588  if ( !isMultipart() && partNum < 1 )
2589  {
2590  set( nullptr );
2591  return true;
2592  }
2593 
2594  detach();
2595  bool ok = QgsGeometryEditUtils::deletePart( d->geometry.get(), partNum );
2596  return ok;
2597 }
2598 
2599 int QgsGeometry::avoidIntersections( const QList<QgsVectorLayer *> &avoidIntersectionsLayers, const QHash<QgsVectorLayer *, QSet<QgsFeatureId> > &ignoreFeatures )
2600 {
2601  if ( !d->geometry )
2602  {
2603  return 1;
2604  }
2605 
2606  std::unique_ptr< QgsAbstractGeometry > diffGeom = QgsGeometryEditUtils::avoidIntersections( *( d->geometry ), avoidIntersectionsLayers, ignoreFeatures );
2607  if ( diffGeom )
2608  {
2609  reset( std::move( diffGeom ) );
2610  }
2611  return 0;
2612 }
2613 
2614 
2616 {
2617  if ( !d->geometry )
2618  return QgsGeometry();
2619 
2620  mLastError.clear();
2621  std::unique_ptr< QgsAbstractGeometry > g( _qgis_lwgeom_make_valid( d->geometry.get(), mLastError ) );
2622 
2623  QgsGeometry result = QgsGeometry( std::move( g ) );
2624  result.mLastError = mLastError;
2625  return result;
2626 }
2627 
2629 {
2630  if ( !d->geometry )
2631  return QgsGeometry();
2632 
2633  if ( isMultipart() )
2634  {
2635  const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( d->geometry.get() );
2636  std::unique_ptr< QgsGeometryCollection > newCollection( collection->createEmptyWithSameType() );
2637  newCollection->reserve( collection->numGeometries() );
2638  for ( int i = 0; i < collection->numGeometries(); ++i )
2639  {
2640  const QgsAbstractGeometry *g = collection->geometryN( i );
2641  if ( const QgsCurvePolygon *cp = qgsgeometry_cast< const QgsCurvePolygon * >( g ) )
2642  {
2643  std::unique_ptr< QgsCurvePolygon > corrected( cp->clone() );
2644  corrected->forceRHR();
2645  newCollection->addGeometry( corrected.release() );
2646  }
2647  else
2648  {
2649  newCollection->addGeometry( g->clone() );
2650  }
2651  }
2652  return QgsGeometry( std::move( newCollection ) );
2653  }
2654  else
2655  {
2656  if ( const QgsCurvePolygon *cp = qgsgeometry_cast< const QgsCurvePolygon * >( d->geometry.get() ) )
2657  {
2658  std::unique_ptr< QgsCurvePolygon > corrected( cp->clone() );
2659  corrected->forceRHR();
2660  return QgsGeometry( std::move( corrected ) );
2661  }
2662  else
2663  {
2664  // not a curve polygon, so return unchanged
2665  return *this;
2666  }
2667  }
2668 }
2669 
2670 
2671 void QgsGeometry::validateGeometry( QVector<QgsGeometry::Error> &errors, const ValidationMethod method, const QgsGeometry::ValidityFlags flags ) const
2672 {
2673  errors.clear();
2674  if ( !d->geometry )
2675  return;
2676 
2677  // avoid expensive calcs for trivial point geometries
2679  {
2680  return;
2681  }
2682 
2683  switch ( method )
2684  {
2685  case ValidatorQgisInternal:
2686  QgsGeometryValidator::validateGeometry( *this, errors, method );
2687  return;
2688 
2689  case ValidatorGeos:
2690  {
2691  QgsGeos geos( d->geometry.get() );
2692  QString error;
2693  QgsGeometry errorLoc;
2694  if ( !geos.isValid( &error, flags & FlagAllowSelfTouchingHoles, &errorLoc ) )
2695  {
2696  if ( errorLoc.isNull() )
2697  {
2698  errors.append( QgsGeometry::Error( error ) );
2699  }
2700  else
2701  {
2702  const QgsPointXY point = errorLoc.asPoint();
2703  errors.append( QgsGeometry::Error( error, point ) );
2704  }
2705  return;
2706  }
2707  }
2708  }
2709 }
2710 
2711 bool QgsGeometry::isGeosValid( const QgsGeometry::ValidityFlags flags ) const
2712 {
2713  if ( !d->geometry )
2714  {
2715  return false;
2716  }
2717 
2718  return d->geometry->isValid( mLastError, static_cast< int >( flags ) );
2719 }
2720 
2722 {
2723  if ( !d->geometry )
2724  return false;
2725 
2726  QgsGeos geos( d->geometry.get() );
2727  mLastError.clear();
2728  return geos.isSimple( &mLastError );
2729 }
2730 
2732 {
2733  if ( !d->geometry || !g.d->geometry )
2734  {
2735  return false;
2736  }
2737 
2738  // fast check - are they shared copies of the same underlying geometry?
2739  if ( d == g.d )
2740  return true;
2741 
2742  // fast check - distinct geometry types?
2743  if ( type() != g.type() )
2744  return false;
2745 
2746  // avoid calling geos for trivial point case
2747  if ( QgsWkbTypes::flatType( d->geometry->wkbType() ) == QgsWkbTypes::Point
2748  && QgsWkbTypes::flatType( g.d->geometry->wkbType() ) == QgsWkbTypes::Point )
2749  {
2750  return equals( g );
2751  }
2752 
2753  // another nice fast check upfront -- if the bounding boxes aren't equal, the geometries themselves can't be equal!
2754  if ( d->geometry->boundingBox() != g.d->geometry->boundingBox() )
2755  return false;
2756 
2757  QgsGeos geos( d->geometry.get() );
2758  mLastError.clear();
2759  return geos.isEqual( g.d->geometry.get(), &mLastError );
2760 }
2761 
2762 QgsGeometry QgsGeometry::unaryUnion( const QVector<QgsGeometry> &geometries )
2763 {
2764  QgsGeos geos( nullptr );
2765 
2766  QString error;
2767  std::unique_ptr< QgsAbstractGeometry > geom( geos.combine( geometries, &error ) );
2768  QgsGeometry result( std::move( geom ) );
2769  result.mLastError = error;
2770  return result;
2771 }
2772 
2773 QgsGeometry QgsGeometry::polygonize( const QVector<QgsGeometry> &geometryList )
2774 {
2775  QgsGeos geos( nullptr );
2776 
2777  QVector<const QgsAbstractGeometry *> geomV2List;
2778  for ( const QgsGeometry &g : geometryList )
2779  {
2780  if ( !( g.isNull() ) )
2781  {
2782  geomV2List.append( g.constGet() );
2783  }
2784  }
2785 
2786  QString error;
2787  QgsGeometry result = geos.polygonize( geomV2List, &error );
2788  result.mLastError = error;
2789  return result;
2790 }
2791 
2793 {
2795  {
2796  return;
2797  }
2798 
2799  std::unique_ptr< QgsAbstractGeometry > straightGeom( d->geometry->segmentize( tolerance, toleranceType ) );
2800  reset( std::move( straightGeom ) );
2801 }
2802 
2804 {
2805  if ( !d->geometry )
2806  {
2807  return false;
2808  }
2809 
2810  return d->geometry->hasCurvedSegments();
2811 }
2812 
2814 {
2815  if ( !d->geometry )
2816  {
2818  }
2819 
2820  detach();
2821  d->geometry->transform( ct, direction, transformZ );
2822  return QgsGeometry::Success;
2823 }
2824 
2825 QgsGeometry::OperationResult QgsGeometry::transform( const QTransform &ct, double zTranslate, double zScale, double mTranslate, double mScale )
2826 {
2827  if ( !d->geometry )
2828  {
2830  }
2831 
2832  detach();
2833  d->geometry->transform( ct, zTranslate, zScale, mTranslate, mScale );
2834  return QgsGeometry::Success;
2835 }
2836 
2838 {
2839  if ( d->geometry )
2840  {
2841  detach();
2842  d->geometry->transform( mtp.transform() );
2843  }
2844 }
2845 
2847 {
2848  if ( !d->geometry || rectangle.isNull() || rectangle.isEmpty() )
2849  {
2850  return QgsGeometry();
2851  }
2852 
2853  QgsGeos geos( d->geometry.get() );
2854  mLastError.clear();
2855  std::unique_ptr< QgsAbstractGeometry > resultGeom = geos.clip( rectangle, &mLastError );
2856  if ( !resultGeom )
2857  {
2858  QgsGeometry result;
2859  result.mLastError = mLastError;
2860  return result;
2861  }
2862  return QgsGeometry( std::move( resultGeom ) );
2863 }
2864 
2865 void QgsGeometry::draw( QPainter &p ) const
2866 {
2867  if ( d->geometry )
2868  {
2869  d->geometry->draw( p );
2870  }
2871 }
2872 
2873 static bool vertexIndexInfo( const QgsAbstractGeometry *g, int vertexIndex, int &partIndex, int &ringIndex, int &vertex )
2874 {
2875  if ( vertexIndex < 0 )
2876  return false; // clearly something wrong
2877 
2878  if ( const QgsGeometryCollection *geomCollection = qgsgeometry_cast<const QgsGeometryCollection *>( g ) )
2879  {
2880  partIndex = 0;
2881  int offset = 0;
2882  for ( int i = 0; i < geomCollection->numGeometries(); ++i )
2883  {
2884  const QgsAbstractGeometry *part = geomCollection->geometryN( i );
2885 
2886  // count total number of vertices in the part
2887  int numPoints = 0;
2888  for ( int k = 0; k < part->ringCount(); ++k )
2889  numPoints += part->vertexCount( 0, k );
2890 
2891  if ( vertexIndex < numPoints )
2892  {
2893  int nothing;
2894  return vertexIndexInfo( part, vertexIndex, nothing, ringIndex, vertex ); // set ring_index + index
2895  }
2896  vertexIndex -= numPoints;
2897  offset += numPoints;
2898  partIndex++;
2899  }
2900  }
2901  else if ( const QgsCurvePolygon *curvePolygon = qgsgeometry_cast<const QgsCurvePolygon *>( g ) )
2902  {
2903  const QgsCurve *ring = curvePolygon->exteriorRing();
2904  if ( vertexIndex < ring->numPoints() )
2905  {
2906  partIndex = 0;
2907  ringIndex = 0;
2908  vertex = vertexIndex;
2909  return true;
2910  }
2911  vertexIndex -= ring->numPoints();
2912  ringIndex = 1;
2913  for ( int i = 0; i < curvePolygon->numInteriorRings(); ++i )
2914  {
2915  const QgsCurve *ring = curvePolygon->interiorRing( i );
2916  if ( vertexIndex < ring->numPoints() )
2917  {
2918  partIndex = 0;
2919  vertex = vertexIndex;
2920  return true;
2921  }
2922  vertexIndex -= ring->numPoints();
2923  ringIndex += 1;
2924  }
2925  }
2926  else if ( const QgsCurve *curve = qgsgeometry_cast<const QgsCurve *>( g ) )
2927  {
2928  if ( vertexIndex < curve->numPoints() )
2929  {
2930  partIndex = 0;
2931  ringIndex = 0;
2932  vertex = vertexIndex;
2933  return true;
2934  }
2935  }
2936  else if ( qgsgeometry_cast<const QgsPoint *>( g ) )
2937  {
2938  if ( vertexIndex == 0 )
2939  {
2940  partIndex = 0;
2941  ringIndex = 0;
2942  vertex = 0;
2943  return true;
2944  }
2945  }
2946 
2947  return false;
2948 }
2949 
2951 {
2952  if ( !d->geometry )
2953  {
2954  return false;
2955  }
2956 
2957  id.type = QgsVertexId::SegmentVertex;
2958 
2959  bool res = vertexIndexInfo( d->geometry.get(), nr, id.part, id.ring, id.vertex );
2960  if ( !res )
2961  return false;
2962 
2963  // now let's find out if it is a straight or circular segment
2964  const QgsAbstractGeometry *g = d->geometry.get();
2965  if ( const QgsGeometryCollection *geomCollection = qgsgeometry_cast<const QgsGeometryCollection *>( g ) )
2966  {
2967  g = geomCollection->geometryN( id.part );
2968  }
2969 
2970  if ( const QgsCurvePolygon *curvePolygon = qgsgeometry_cast<const QgsCurvePolygon *>( g ) )
2971  {
2972  g = id.ring == 0 ? curvePolygon->exteriorRing() : curvePolygon->interiorRing( id.ring - 1 );
2973  }
2974 
2975  if ( const QgsCurve *curve = qgsgeometry_cast<const QgsCurve *>( g ) )
2976  {
2977  QgsPoint p;
2978  res = curve->pointAt( id.vertex, p, id.type );
2979  if ( !res )
2980  return false;
2981  }
2982 
2983  return true;
2984 }
2985 
2987 {
2988  if ( !d->geometry )
2989  {
2990  return -1;
2991  }
2992  return d->geometry->vertexNumberFromVertexId( id );
2993 }
2994 
2995 QString QgsGeometry::lastError() const
2996 {
2997  return mLastError;
2998 }
2999 
3000 void QgsGeometry::filterVertices( const std::function<bool ( const QgsPoint & )> &filter )
3001 {
3002  if ( !d->geometry )
3003  return;
3004 
3005  detach();
3006 
3007  d->geometry->filterVertices( filter );
3008 }
3009 
3010 void QgsGeometry::transformVertices( const std::function<QgsPoint( const QgsPoint & )> &transform )
3011 {
3012  if ( !d->geometry )
3013  return;
3014 
3015  detach();
3016 
3017  d->geometry->transformVertices( transform );
3018 }
3019 
3020 void QgsGeometry::convertPointList( const QVector<QgsPointXY> &input, QgsPointSequence &output )
3021 {
3022  output.clear();
3023  for ( const QgsPointXY &p : input )
3024  {
3025  output.append( QgsPoint( p ) );
3026  }
3027 }
3028 
3029 void QgsGeometry::convertPointList( const QgsPointSequence &input, QVector<QgsPointXY> &output )
3030 {
3031  output.clear();
3032  for ( const QgsPoint &p : input )
3033  {
3034  output.append( QgsPointXY( p.x(), p.y() ) );
3035  }
3036 }
3037 
3038 void QgsGeometry::convertToPolyline( const QgsPointSequence &input, QgsPolylineXY &output )
3039 {
3040  output.clear();
3041  output.resize( input.size() );
3042 
3043  for ( int i = 0; i < input.size(); ++i )
3044  {
3045  const QgsPoint &pt = input.at( i );
3046  output[i].setX( pt.x() );
3047  output[i].setY( pt.y() );
3048  }
3049 }
3050 
3051 void QgsGeometry::convertPolygon( const QgsPolygon &input, QgsPolygonXY &output )
3052 {
3053  output.clear();
3054  QgsCoordinateSequence coords = input.coordinateSequence();
3055  if ( coords.empty() )
3056  {
3057  return;
3058  }
3059  const QgsRingSequence &rings = coords[0];
3060  output.resize( rings.size() );
3061  for ( int i = 0; i < rings.size(); ++i )
3062  {
3063  convertToPolyline( rings[i], output[i] );
3064  }
3065 }
3066 
3068 {
3069  return QgsGeometry( qgis::make_unique< QgsPoint >( point.x(), point.y() ) );
3070 }
3071 
3072 QgsGeometry QgsGeometry::fromQPolygonF( const QPolygonF &polygon )
3073 {
3074  std::unique_ptr < QgsLineString > ring( QgsLineString::fromQPolygonF( polygon ) );
3075 
3076  if ( polygon.isClosed() )
3077  {
3078  std::unique_ptr< QgsPolygon > poly = qgis::make_unique< QgsPolygon >();
3079  poly->setExteriorRing( ring.release() );
3080  return QgsGeometry( std::move( poly ) );
3081  }
3082  else
3083  {
3084  return QgsGeometry( std::move( ring ) );
3085  }
3086 }
3087 
3089 {
3091  QgsPolygonXY result;
3092  result << createPolylineFromQPolygonF( polygon );
3093  return result;
3095 }
3096 
3098 {
3099  QgsPolylineXY result;
3100  result.reserve( polygon.count() );
3101  for ( const QPointF &p : polygon )
3102  {
3103  result.append( QgsPointXY( p ) );
3104  }
3105  return result;
3106 }
3107 
3108 bool QgsGeometry::compare( const QgsPolylineXY &p1, const QgsPolylineXY &p2, double epsilon )
3109 {
3110  if ( p1.count() != p2.count() )
3111  return false;
3112 
3113  for ( int i = 0; i < p1.count(); ++i )
3114  {
3115  if ( !p1.at( i ).compare( p2.at( i ), epsilon ) )
3116  return false;
3117  }
3118  return true;
3119 }
3120 
3121 bool QgsGeometry::compare( const QgsPolygonXY &p1, const QgsPolygonXY &p2, double epsilon )
3122 {
3123  if ( p1.count() != p2.count() )
3124  return false;
3125 
3126  for ( int i = 0; i < p1.count(); ++i )
3127  {
3128  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
3129  return false;
3130  }
3131  return true;
3132 }
3133 
3134 
3135 bool QgsGeometry::compare( const QgsMultiPolygonXY &p1, const QgsMultiPolygonXY &p2, double epsilon )
3136 {
3137  if ( p1.count() != p2.count() )
3138  return false;
3139 
3140  for ( int i = 0; i < p1.count(); ++i )
3141  {
3142  if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
3143  return false;
3144  }
3145  return true;
3146 }
3147 
3148 QgsGeometry QgsGeometry::smooth( const unsigned int iterations, const double offset, double minimumDistance, double maxAngle ) const
3149 {
3150  if ( !d->geometry || d->geometry->isEmpty() )
3151  return QgsGeometry();
3152 
3153  QgsGeometry geom = *this;
3155  geom = QgsGeometry( d->geometry->segmentize() );
3156 
3157  switch ( QgsWkbTypes::flatType( geom.wkbType() ) )
3158  {
3159  case QgsWkbTypes::Point:
3161  //can't smooth a point based geometry
3162  return geom;
3163 
3165  {
3166  const QgsLineString *lineString = qgsgeometry_cast< const QgsLineString * >( geom.constGet() );
3167  return QgsGeometry( smoothLine( *lineString, iterations, offset, minimumDistance, maxAngle ) );
3168  }
3169 
3171  {
3172  const QgsMultiLineString *multiLine = qgsgeometry_cast< const QgsMultiLineString * >( geom.constGet() );
3173 
3174  std::unique_ptr< QgsMultiLineString > resultMultiline = qgis::make_unique< QgsMultiLineString> ();
3175  resultMultiline->reserve( multiLine->numGeometries() );
3176  for ( int i = 0; i < multiLine->numGeometries(); ++i )
3177  {
3178  resultMultiline->addGeometry( smoothLine( *( multiLine->lineStringN( i ) ), iterations, offset, minimumDistance, maxAngle ).release() );
3179  }
3180  return QgsGeometry( std::move( resultMultiline ) );
3181  }
3182 
3183  case QgsWkbTypes::Polygon:
3184  {
3185  const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon * >( geom.constGet() );
3186  return QgsGeometry( smoothPolygon( *poly, iterations, offset, minimumDistance, maxAngle ) );
3187  }
3188 
3190  {
3191  const QgsMultiPolygon *multiPoly = qgsgeometry_cast< const QgsMultiPolygon * >( geom.constGet() );
3192 
3193  std::unique_ptr< QgsMultiPolygon > resultMultiPoly = qgis::make_unique< QgsMultiPolygon >();
3194  resultMultiPoly->reserve( multiPoly->numGeometries() );
3195  for ( int i = 0; i < multiPoly->numGeometries(); ++i )
3196  {
3197  resultMultiPoly->addGeometry( smoothPolygon( *( multiPoly->polygonN( i ) ), iterations, offset, minimumDistance, maxAngle ).release() );
3198  }
3199  return QgsGeometry( std::move( resultMultiPoly ) );
3200  }
3201 
3202  case QgsWkbTypes::Unknown:
3203  default:
3204  return QgsGeometry( *this );
3205  }
3206 }
3207 
3208 std::unique_ptr< QgsLineString > smoothCurve( const QgsLineString &line, const unsigned int iterations,
3209  const double offset, double squareDistThreshold, double maxAngleRads,
3210  bool isRing )
3211 {
3212  std::unique_ptr< QgsLineString > result = qgis::make_unique< QgsLineString >( line );
3213  QgsPointSequence outputLine;
3214  for ( unsigned int iteration = 0; iteration < iterations; ++iteration )
3215  {
3216  outputLine.resize( 0 );
3217  outputLine.reserve( 2 * ( result->numPoints() - 1 ) );
3218  bool skipFirst = false;
3219  bool skipLast = false;
3220  if ( isRing )
3221  {
3222  QgsPoint p1 = result->pointN( result->numPoints() - 2 );
3223  QgsPoint p2 = result->pointN( 0 );
3224  QgsPoint p3 = result->pointN( 1 );
3225  double angle = QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(),
3226  p3.x(), p3.y() );
3227  angle = std::fabs( M_PI - angle );
3228  skipFirst = angle > maxAngleRads;
3229  }
3230  for ( int i = 0; i < result->numPoints() - 1; i++ )
3231  {
3232  QgsPoint p1 = result->pointN( i );
3233  QgsPoint p2 = result->pointN( i + 1 );
3234 
3235  double angle = M_PI;
3236  if ( i == 0 && isRing )
3237  {
3238  QgsPoint p3 = result->pointN( result->numPoints() - 2 );
3239  angle = QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(),
3240  p3.x(), p3.y() );
3241  }
3242  else if ( i < result->numPoints() - 2 )
3243  {
3244  QgsPoint p3 = result->pointN( i + 2 );
3245  angle = QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(),
3246  p3.x(), p3.y() );
3247  }
3248  else if ( i == result->numPoints() - 2 && isRing )
3249  {
3250  QgsPoint p3 = result->pointN( 1 );
3251  angle = QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(),
3252  p3.x(), p3.y() );
3253  }
3254 
3255  skipLast = angle < M_PI - maxAngleRads || angle > M_PI + maxAngleRads;
3256 
3257  // don't apply distance threshold to first or last segment
3258  if ( i == 0 || i >= result->numPoints() - 2
3259  || QgsGeometryUtils::sqrDistance2D( p1, p2 ) > squareDistThreshold )
3260  {
3261  if ( !isRing )
3262  {
3263  if ( !skipFirst )
3264  outputLine << ( i == 0 ? result->pointN( i ) : QgsGeometryUtils::interpolatePointOnLine( p1, p2, offset ) );
3265  if ( !skipLast )
3266  outputLine << ( i == result->numPoints() - 2 ? result->pointN( i + 1 ) : QgsGeometryUtils::interpolatePointOnLine( p1, p2, 1.0 - offset ) );
3267  else
3268  outputLine << p2;
3269  }
3270  else
3271  {
3272  // ring
3273  if ( !skipFirst )
3274  outputLine << QgsGeometryUtils::interpolatePointOnLine( p1, p2, offset );
3275  else if ( i == 0 )
3276  outputLine << p1;
3277  if ( !skipLast )
3278  outputLine << QgsGeometryUtils::interpolatePointOnLine( p1, p2, 1.0 - offset );
3279  else
3280  outputLine << p2;
3281  }
3282  }
3283  skipFirst = skipLast;
3284  }
3285 
3286  if ( isRing && outputLine.at( 0 ) != outputLine.at( outputLine.count() - 1 ) )
3287  outputLine << outputLine.at( 0 );
3288 
3289  result->setPoints( outputLine );
3290  }
3291  return result;
3292 }
3293 
3294 std::unique_ptr<QgsLineString> QgsGeometry::smoothLine( const QgsLineString &line, const unsigned int iterations, const double offset, double minimumDistance, double maxAngle ) const
3295 {
3296  double maxAngleRads = maxAngle * M_PI / 180.0;
3297  double squareDistThreshold = minimumDistance > 0 ? minimumDistance * minimumDistance : -1;
3298  return smoothCurve( line, iterations, offset, squareDistThreshold, maxAngleRads, false );
3299 }
3300 
3301 std::unique_ptr<QgsPolygon> QgsGeometry::smoothPolygon( const QgsPolygon &polygon, const unsigned int iterations, const double offset, double minimumDistance, double maxAngle ) const
3302 {
3303  double maxAngleRads = maxAngle * M_PI / 180.0;
3304  double squareDistThreshold = minimumDistance > 0 ? minimumDistance * minimumDistance : -1;
3305  std::unique_ptr< QgsPolygon > resultPoly = qgis::make_unique< QgsPolygon >();
3306 
3307  resultPoly->setExteriorRing( smoothCurve( *( static_cast< const QgsLineString *>( polygon.exteriorRing() ) ), iterations, offset,
3308  squareDistThreshold, maxAngleRads, true ).release() );
3309 
3310  for ( int i = 0; i < polygon.numInteriorRings(); ++i )
3311  {
3312  resultPoly->addInteriorRing( smoothCurve( *( static_cast< const QgsLineString *>( polygon.interiorRing( i ) ) ), iterations, offset,
3313  squareDistThreshold, maxAngleRads, true ).release() );
3314  }
3315  return resultPoly;
3316 }
3317 
3318 QgsGeometry QgsGeometry::convertToPoint( bool destMultipart ) const
3319 {
3320  switch ( type() )
3321  {
3323  {
3324  bool srcIsMultipart = isMultipart();
3325 
3326  if ( ( destMultipart && srcIsMultipart ) ||
3327  ( !destMultipart && !srcIsMultipart ) )
3328  {
3329  // return a copy of the same geom
3330  return QgsGeometry( *this );
3331  }
3332  if ( destMultipart )
3333  {
3334  // layer is multipart => make a multipoint with a single point
3335  return fromMultiPointXY( QgsMultiPointXY() << asPoint() );
3336  }
3337  else
3338  {
3339  // destination is singlepart => make a single part if possible
3340  QgsMultiPointXY multiPoint = asMultiPoint();
3341  if ( multiPoint.count() == 1 )
3342  {
3343  return fromPointXY( multiPoint[0] );
3344  }
3345  }
3346  return QgsGeometry();
3347  }
3348 
3350  {
3351  // only possible if destination is multipart
3352  if ( !destMultipart )
3353  return QgsGeometry();
3354 
3355  // input geometry is multipart
3356  if ( isMultipart() )
3357  {
3358  const QgsMultiPolylineXY multiLine = asMultiPolyline();
3359  QgsMultiPointXY multiPoint;
3360  for ( const QgsPolylineXY &l : multiLine )
3361  for ( const QgsPointXY &p : l )
3362  multiPoint << p;
3363  return fromMultiPointXY( multiPoint );
3364  }
3365  // input geometry is not multipart: copy directly the line into a multipoint
3366  else
3367  {
3368  QgsPolylineXY line = asPolyline();
3369  if ( !line.isEmpty() )
3370  return fromMultiPointXY( line );
3371  }
3372  return QgsGeometry();
3373  }
3374 
3376  {
3377  // can only transform if destination is multipoint
3378  if ( !destMultipart )
3379  return QgsGeometry();
3380 
3381  // input geometry is multipart: make a multipoint from multipolygon
3382  if ( isMultipart() )
3383  {
3384  const QgsMultiPolygonXY multiPolygon = asMultiPolygon();
3385  QgsMultiPointXY multiPoint;
3386  for ( const QgsPolygonXY &poly : multiPolygon )
3387  for ( const QgsPolylineXY &line : poly )
3388  for ( const QgsPointXY &pt : line )
3389  multiPoint << pt;
3390  return fromMultiPointXY( multiPoint );
3391  }
3392  // input geometry is not multipart: make a multipoint from polygon
3393  else
3394  {
3395  const QgsPolygonXY polygon = asPolygon();
3396  QgsMultiPointXY multiPoint;
3397  for ( const QgsPolylineXY &line : polygon )
3398  for ( const QgsPointXY &pt : line )
3399  multiPoint << pt;
3400  return fromMultiPointXY( multiPoint );
3401  }
3402  }
3403 
3404  default:
3405  return QgsGeometry();
3406  }
3407 }
3408 
3409 QgsGeometry QgsGeometry::convertToLine( bool destMultipart ) const
3410 {
3411  switch ( type() )
3412  {
3414  {
3415  if ( !isMultipart() )
3416  return QgsGeometry();
3417 
3418  QgsMultiPointXY multiPoint = asMultiPoint();
3419  if ( multiPoint.count() < 2 )
3420  return QgsGeometry();
3421 
3422  if ( destMultipart )
3423  return fromMultiPolylineXY( QgsMultiPolylineXY() << multiPoint );
3424  else
3425  return fromPolylineXY( multiPoint );
3426  }
3427 
3429  {
3430  bool srcIsMultipart = isMultipart();
3431 
3432  if ( ( destMultipart && srcIsMultipart ) ||
3433  ( !destMultipart && ! srcIsMultipart ) )
3434  {
3435  // return a copy of the same geom
3436  return QgsGeometry( *this );
3437  }
3438  if ( destMultipart )
3439  {
3440  // destination is multipart => makes a multipoint with a single line
3441  QgsPolylineXY line = asPolyline();
3442  if ( !line.isEmpty() )
3443  return fromMultiPolylineXY( QgsMultiPolylineXY() << line );
3444  }
3445  else
3446  {
3447  // destination is singlepart => make a single part if possible
3448  QgsMultiPolylineXY multiLine = asMultiPolyline();
3449  if ( multiLine.count() == 1 )
3450  return fromPolylineXY( multiLine[0] );
3451  }
3452  return QgsGeometry();
3453  }
3454 
3456  {
3457  // input geometry is multipolygon
3458  if ( isMultipart() )
3459  {
3460  const QgsMultiPolygonXY multiPolygon = asMultiPolygon();
3461  QgsMultiPolylineXY multiLine;
3462  for ( const QgsPolygonXY &poly : multiPolygon )
3463  for ( const QgsPolylineXY &line : poly )
3464  multiLine << line;
3465 
3466  if ( destMultipart )
3467  {
3468  // destination is multipart
3469  return fromMultiPolylineXY( multiLine );
3470  }
3471  else if ( multiLine.count() == 1 )
3472  {
3473  // destination is singlepart => make a single part if possible
3474  return fromPolylineXY( multiLine[0] );
3475  }
3476  }
3477  // input geometry is single polygon
3478  else
3479  {
3480  QgsPolygonXY polygon = asPolygon();
3481  // if polygon has rings
3482  if ( polygon.count() > 1 )
3483  {
3484  // cannot fit a polygon with rings in a single line layer
3485  // TODO: would it be better to remove rings?
3486  if ( destMultipart )
3487  {
3488  const QgsPolygonXY polygon = asPolygon();
3489  QgsMultiPolylineXY multiLine;
3490  multiLine.reserve( polygon.count() );
3491  for ( const QgsPolylineXY &line : polygon )
3492  multiLine << line;
3493  return fromMultiPolylineXY( multiLine );
3494  }
3495  }
3496  // no rings
3497  else if ( polygon.count() == 1 )
3498  {
3499  if ( destMultipart )
3500  {
3501  return fromMultiPolylineXY( polygon );
3502  }
3503  else
3504  {
3505  return fromPolylineXY( polygon[0] );
3506  }
3507  }
3508  }
3509  return QgsGeometry();
3510  }
3511 
3512  default:
3513  return QgsGeometry();
3514  }
3515 }
3516 
3517 QgsGeometry QgsGeometry::convertToPolygon( bool destMultipart ) const
3518 {
3519  switch ( type() )
3520  {
3522  {
3523  if ( !isMultipart() )
3524  return QgsGeometry();
3525 
3526  QgsMultiPointXY multiPoint = asMultiPoint();
3527  if ( multiPoint.count() < 3 )
3528  return QgsGeometry();
3529 
3530  if ( multiPoint.last() != multiPoint.first() )
3531  multiPoint << multiPoint.first();
3532 
3533  QgsPolygonXY polygon = QgsPolygonXY() << multiPoint;
3534  if ( destMultipart )
3535  return fromMultiPolygonXY( QgsMultiPolygonXY() << polygon );
3536  else
3537  return fromPolygonXY( polygon );
3538  }
3539 
3541  {
3542  // input geometry is multiline
3543  if ( isMultipart() )
3544  {
3545  QgsMultiPolylineXY multiLine = asMultiPolyline();
3546  QgsMultiPolygonXY multiPolygon;
3547  for ( QgsMultiPolylineXY::iterator multiLineIt = multiLine.begin(); multiLineIt != multiLine.end(); ++multiLineIt )
3548  {
3549  // do not create polygon for a 1 segment line
3550  if ( ( *multiLineIt ).count() < 3 )
3551  return QgsGeometry();
3552  if ( ( *multiLineIt ).count() == 3 && ( *multiLineIt ).first() == ( *multiLineIt ).last() )
3553  return QgsGeometry();
3554 
3555  // add closing node
3556  if ( ( *multiLineIt ).first() != ( *multiLineIt ).last() )
3557  *multiLineIt << ( *multiLineIt ).first();
3558  multiPolygon << ( QgsPolygonXY() << *multiLineIt );
3559  }
3560  // check that polygons were inserted
3561  if ( !multiPolygon.isEmpty() )
3562  {
3563  if ( destMultipart )
3564  {
3565  return fromMultiPolygonXY( multiPolygon );
3566  }
3567  else if ( multiPolygon.count() == 1 )
3568  {
3569  // destination is singlepart => make a single part if possible
3570  return fromPolygonXY( multiPolygon[0] );
3571  }
3572  }
3573  }
3574  // input geometry is single line
3575  else
3576  {
3577  QgsPolylineXY line = asPolyline();
3578 
3579  // do not create polygon for a 1 segment line
3580  if ( line.count() < 3 )
3581  return QgsGeometry();
3582  if ( line.count() == 3 && line.first() == line.last() )
3583  return QgsGeometry();
3584 
3585  // add closing node
3586  if ( line.first() != line.last() )
3587  line << line.first();
3588 
3589  // destination is multipart
3590  if ( destMultipart )
3591  {
3592  return fromMultiPolygonXY( QgsMultiPolygonXY() << ( QgsPolygonXY() << line ) );
3593  }
3594  else
3595  {
3596  return fromPolygonXY( QgsPolygonXY() << line );
3597  }
3598  }
3599  return QgsGeometry();
3600  }
3601 
3603  {
3604  bool srcIsMultipart = isMultipart();
3605 
3606  if ( ( destMultipart && srcIsMultipart ) ||
3607  ( !destMultipart && ! srcIsMultipart ) )
3608  {
3609  // return a copy of the same geom
3610  return QgsGeometry( *this );
3611  }
3612  if ( destMultipart )
3613  {
3614  // destination is multipart => makes a multipoint with a single polygon
3615  QgsPolygonXY polygon = asPolygon();
3616  if ( !polygon.isEmpty() )
3617  return fromMultiPolygonXY( QgsMultiPolygonXY() << polygon );
3618  }
3619  else
3620  {
3621  QgsMultiPolygonXY multiPolygon = asMultiPolygon();
3622  if ( multiPolygon.count() == 1 )
3623  {
3624  // destination is singlepart => make a single part if possible
3625  return fromPolygonXY( multiPolygon[0] );
3626  }
3627  }
3628  return QgsGeometry();
3629  }
3630 
3631  default:
3632  return QgsGeometry();
3633  }
3634 }
3635 
3637 {
3638  return new QgsGeos( geometry );
3639 }
3640 
3641 QDataStream &operator<<( QDataStream &out, const QgsGeometry &geometry )
3642 {
3643  out << geometry.asWkb();
3644  return out;
3645 }
3646 
3647 QDataStream &operator>>( QDataStream &in, QgsGeometry &geometry )
3648 {
3649  QByteArray byteArray;
3650  in >> byteArray;
3651  if ( byteArray.isEmpty() )
3652  {
3653  geometry.set( nullptr );
3654  return in;
3655  }
3656 
3657  geometry.fromWkb( byteArray );
3658  return in;
3659 }
3660 
3661 
3663 {
3664  return mMessage;
3665 }
3666 
3668 {
3669  return mLocation;
3670 }
3671 
3673 {
3674  return mHasLocation;
3675 }
QgsCurve
Abstract base class for curved geometry type.
Definition: qgscurve.h:36
QgsGeometry::combine
QgsGeometry combine(const QgsGeometry &geometry) const
Returns a geometry representing all the points in this geometry and other (a union geometry operation...
Definition: qgsgeometry.cpp:2402
QgsGeometry::Success
@ Success
Operation succeeded.
Definition: qgsgeometry.h:137
qgspolygon.h
QgsGeometry::AddPartNotMultiGeometry
@ AddPartNotMultiGeometry
The source geometry is not multi.
Definition: qgsgeometry.h:147
QgsInternalGeometryEngine::orthogonalize
QgsGeometry orthogonalize(double tolerance=1.0E-8, int maxIterations=1000, double angleThreshold=15.0) const
Attempts to orthogonalize a line or polygon geometry by shifting vertices to make the geometries angl...
Definition: qgsinternalgeometryengine.cpp:502
QgsInternalGeometryEngine::extrude
QgsGeometry extrude(double x, double y) const
Will extrude a line or (segmentized) curve by a given offset and return a polygon representation of i...
Definition: qgsinternalgeometryengine.cpp:55
QgsCircle::contains
bool contains(const QgsPoint &point, double epsilon=1E-8) const
Returns true if the circle contains the point.
Definition: qgscircle.cpp:350
QgsGeometry::lastError
QString lastError() const SIP_HOLDGIL
Returns an error string referring to the last error encountered either when this geometry was created...
Definition: qgsgeometry.cpp:2995
QgsGeometry::ValidatorGeos
@ ValidatorGeos
Use GEOS validation methods.
Definition: qgsgeometry.h:2115
QgsGeos::hausdorffDistanceDensify
double hausdorffDistanceDensify(const QgsAbstractGeometry *geom, double densifyFraction, QString *errorMsg=nullptr) const
Returns the Hausdorff distance between this geometry and geom.
Definition: qgsgeos.cpp:463
QgsCoordinateSequence
QVector< QgsRingSequence > QgsCoordinateSequence
Definition: qgsabstractgeometry.h:51
QgsGeometry::hausdorffDistanceDensify
double hausdorffDistanceDensify(const QgsGeometry &geom, double densifyFraction) const
Returns the Hausdorff distance between this geometry and geom.
Definition: qgsgeometry.cpp:1824
smoothCurve
std::unique_ptr< QgsLineString > smoothCurve(const QgsLineString &line, const unsigned int iterations, const double offset, double squareDistThreshold, double maxAngleRads, bool isRing)
Definition: qgsgeometry.cpp:3208
operator>>
QDataStream & operator>>(QDataStream &in, QgsGeometry &geometry)
Reads a geometry from stream in into geometry. QGIS version compatibility is not guaranteed.
Definition: qgsgeometry.cpp:3647
QgsGeometry::makeDifferenceInPlace
int makeDifferenceInPlace(const QgsGeometry &other)
Changes this geometry such that it does not intersect the other geometry.
Definition: qgsgeometry.cpp:955
QgsGeos::distance
double distance(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Calculates the distance between this and geom.
Definition: qgsgeos.cpp:417
QgsGeometry::avoidIntersections
int avoidIntersections(const QList< QgsVectorLayer * > &avoidIntersectionsLayers, const QHash< QgsVectorLayer *, QSet< QgsFeatureId > > &ignoreFeatures=(QHash< QgsVectorLayer *, QSet< QgsFeatureId > >()))
Modifies geometry to avoid intersections with the layers specified in project properties.
Definition: qgsgeometry.cpp:2599
QgsGeometryPrivate::ref
QAtomicInt ref
Definition: qgsgeometry.cpp:54
QgsAbstractGeometry::dropMValue
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
QgsInternalGeometryEngine::densifyByCount
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Densifies the geometry by adding the specified number of extra nodes within each segment of the geome...
Definition: qgsinternalgeometryengine.cpp:660
QgsVertexId::vertex
int vertex
Vertex number.
Definition: qgsabstractgeometry.h:1137
QgsPointXY::y
double y
Definition: qgspointxy.h:48
QgsGeometry::asWkb
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const
Export the geometry to WKB.
Definition: qgsgeometry.cpp:2512
QgsGeometry::addPart
OperationResult addPart(const QVector< QgsPointXY > &points, QgsWkbTypes::GeometryType geomType=QgsWkbTypes::UnknownGeometry)
Adds a new part to a the geometry.
Definition: qgsgeometry.cpp:699
QgsGeometry::transform
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
Definition: qgsgeometry.cpp:2813
QgsCurvePolygon::toPolygon
virtual QgsPolygon * toPolygon(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a new polygon geometry corresponding to a segmentized approximation of the curve.
Definition: qgscurvepolygon.cpp:614
QgsGeometryEngine::InvalidInput
@ InvalidInput
The input is not valid.
Definition: qgsgeometryengine.h:50
QgsAbstractGeometry::adjacentVertices
virtual void adjacentVertices(QgsVertexId vertex, QgsVertexId &previousVertex, QgsVertexId &nextVertex) const =0
Returns the vertices adjacent to a specified vertex within a geometry.
QgsGeometry::distance
double distance(const QgsGeometry &geom) const
Returns the minimum distance between this geometry and another geometry.
Definition: qgsgeometry.cpp:1794
QgsGeometry::convertGeometryCollectionToSubclass
bool convertGeometryCollectionToSubclass(QgsWkbTypes::GeometryType geomType)
Converts geometry collection to a the desired geometry type subclass (multi-point,...
Definition: qgsgeometry.cpp:1507
QgsAbstractGeometry::dropZValue
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
QgsGeometry::within
bool within(const QgsGeometry &geometry) const
Returns true if the geometry is completely within another geometry.
Definition: qgsgeometry.cpp:1264
QgsGeometry::createPolygonFromQPolygonF
static Q_DECL_DEPRECATED QgsPolygonXY createPolygonFromQPolygonF(const QPolygonF &polygon)
Creates a QgsPolygonXYfrom a QPolygonF.
Definition: qgsgeometry.cpp:3088
QgsGeometry::validateGeometry
void validateGeometry(QVector< QgsGeometry::Error > &errors, ValidationMethod method=ValidatorQgisInternal, QgsGeometry::ValidityFlags flags=QgsGeometry::ValidityFlags()) const
Validates geometry and produces a list of geometry errors.
Definition: qgsgeometry.cpp:2671
QgsCircle
Circle geometry type.
Definition: qgscircle.h:44
QgsWkbTypes::Point
@ Point
Definition: qgswkbtypes.h:72
QgsCircle::minimalCircleFrom3Points
static QgsCircle minimalCircleFrom3Points(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon=1E-8) SIP_HOLDGIL
Constructs the smallest circle from 3 points.
Definition: qgscircle.cpp:223
QgsVertexId::SegmentVertex
@ SegmentVertex
The actual start or end point of a segment.
Definition: qgsabstractgeometry.h:1066
QgsGeometry::angleAtVertex
double angleAtVertex(int vertex) const
Returns the bisector angle for this geometry at the specified vertex.
Definition: qgsgeometry.cpp:430
QgsPolygon
Polygon geometry type.
Definition: qgspolygon.h:34
qgslinestring.h
QgsGeometry::filterVertices
void filterVertices(const std::function< bool(const QgsPoint &) > &filter)
Filters the vertices from the geometry in place, removing any which do not return true for the filter...
Definition: qgsgeometry.cpp:3000
QgsCurve::interpolatePoint
virtual QgsPoint * interpolatePoint(double distance) const =0
Returns an interpolated point on the curve at the specified distance.
qgsrectangle.h
QgsPolygonXY
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
Definition: qgsgeometry.h:75
QgsAbstractGeometry::addZValue
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
QgsWkbTypes::MultiPolygon
@ MultiPolygon
Definition: qgswkbtypes.h:78
QgsGeometry::subdivide
QgsGeometry subdivide(int maxNodes=256) const
Subdivides the geometry.
Definition: qgsgeometry.cpp:2230
QgsGeometry::fromPolylineXY
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
Definition: qgsgeometry.cpp:174
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:38
QgsGeometry::const_parts_end
QgsAbstractGeometry::const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
Definition: qgsgeometry.cpp:1880
QgsGeometry::asJson
QString asJson(int precision=17) const
Exports the geometry to a GeoJSON string.
Definition: qgsgeometry.cpp:1297
QgsGeometry::fromMultiPolylineXY
static QgsGeometry fromMultiPolylineXY(const QgsMultiPolylineXY &multiline)
Creates a new geometry from a QgsMultiPolylineXY object.
Definition: qgsgeometry.cpp:209
QgsGeometry::fromPolyline
static QgsGeometry fromPolyline(const QgsPolyline &polyline)
Creates a new LineString geometry from a list of QgsPoint points.
Definition: qgsgeometry.cpp:184
qgsgeometryfactory.h
QgsInternalGeometryEngine::variableWidthBufferByM
QgsGeometry variableWidthBufferByM(int segments) const
Calculates a variable width buffer using the m-values from a (multi)line geometry.
Definition: qgsinternalgeometryengine.cpp:1042
qgsmaptopixel.h
QgsGeometry::removeInteriorRings
QgsGeometry removeInteriorRings(double minimumAllowedArea=-1) const
Removes the interior rings from a (multi)polygon geometry.
Definition: qgsgeometry.cpp:766
QgsGeometryFactory::fromPolygonXY
static std::unique_ptr< QgsPolygon > fromPolygonXY(const QgsPolygonXY &polygon)
Construct geometry from a polygon.
Definition: qgsgeometryfactory.cpp:173
QgsGeometry::parts
QgsGeometryPartIterator parts()
Returns Java-style iterator for traversal of parts of the geometry.
Definition: qgsgeometry.cpp:1887
QgsCurvePolygon::exteriorRing
const QgsCurve * exteriorRing() const SIP_HOLDGIL
Returns the curve polygon's exterior ring.
Definition: qgscurvepolygon.h:87
operator<<
QDataStream & operator<<(QDataStream &out, const QgsGeometry &geometry)
Writes the geometry to stream out. QGIS version compatibility is not guaranteed.
Definition: qgsgeometry.cpp:3641
QgsGeometry::isNull
Q_GADGET bool isNull
Definition: qgsgeometry.h:126
QgsPointXY::x
Q_GADGET double x
Definition: qgspointxy.h:47
QgsGeometry::NothingHappened
@ NothingHappened
Nothing happened, without any error.
Definition: qgsgeometry.h:138
qgsinternalgeometryengine.h
QgsAbstractGeometry::addMValue
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
QgsGeometry::removeDuplicateNodes
bool removeDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false)
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
Definition: qgsgeometry.cpp:1120
QgsWkbTypes::flatType
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:702
QgsGeometryFactory::geomFromWkb
static std::unique_ptr< QgsAbstractGeometry > geomFromWkb(QgsConstWkbPtr &wkb)
Construct geometry from a WKB string.
Definition: qgsgeometryfactory.cpp:34
QgsCurvePolygon
Curve polygon geometry type.
Definition: qgscurvepolygon.h:35
QgsGeometry::interpolate
QgsGeometry interpolate(double distance) const
Returns an interpolated point on the geometry at the specified distance.
Definition: qgsgeometry.cpp:2257
QgsPolylineXY
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
Definition: qgsgeometry.h:51
QgsCoordinateTransform::TransformDirection
TransformDirection
Enum used to indicate the direction (forward or inverse) of the transform.
Definition: qgscoordinatetransform.h:59
QgsWkbTypes::LineString
@ LineString
Definition: qgswkbtypes.h:73
QgsGeometryEditUtils::addRing
static QgsGeometry::OperationResult addRing(QgsAbstractGeometry *geometry, std::unique_ptr< QgsCurve > ring)
Add an interior ring to a geometry.
Definition: qgsgeometryeditutils.cpp:29
QgsRectangle::yMinimum
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
QgsGeometry::fromWkb
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
Definition: qgsgeometry.cpp:332
geos
Contains geos related utilities and functions.
Definition: qgsgeos.h:42
QgsGeometry::fromPointXY
static QgsGeometry fromPointXY(const QgsPointXY &point) SIP_HOLDGIL
Creates a new geometry from a QgsPointXY object.
Definition: qgsgeometry.cpp:164
QgsGeometryEngine::EngineError
@ EngineError
Error occurred in the geometry engine.
Definition: qgsgeometryengine.h:47
QgsMultiLineString
Multi line string geometry collection.
Definition: qgsmultilinestring.h:32
QgsInternalGeometryEngine::poleOfInaccessibility
QgsGeometry poleOfInaccessibility(double precision, double *distanceFromBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...
Definition: qgsinternalgeometryengine.cpp:246
QgsGeometryFactory::fromMultiPolygonXY
static std::unique_ptr< QgsMultiPolygon > fromMultiPolygonXY(const QgsMultiPolygonXY &multipoly)
Construct geometry from a multipolygon.
Definition: qgsgeometryfactory.cpp:197
QgsGeometry::centroid
QgsGeometry centroid() const
Returns the center of mass of a geometry.
Definition: qgsgeometry.cpp:2138
QgsInternalGeometryEngine::randomPointsInPolygon
static QVector< QgsPointXY > randomPointsInPolygon(const QgsGeometry &polygon, int count, const std::function< bool(const QgsPointXY &) > &acceptPoint, unsigned long seed=0, QgsFeedback *feedback=nullptr, int maxTriesPerPoint=0)
Returns a list of count random points generated inside a polygon geometry (if acceptPoint is specifie...
Definition: qgsinternalgeometryengine.cpp:1058
qgsmultipoint.h
QgsGeometryConstPartIterator
Java-style iterator for const traversal of parts of a geometry.
Definition: qgsabstractgeometry.h:1269
QgsGeometry::fromQPointF
static QgsGeometry fromQPointF(QPointF point) SIP_HOLDGIL
Construct geometry from a QPointF.
Definition: qgsgeometry.cpp:3067
QgsGeometry::Error
Definition: qgsgeometry.h:2059
QgsGeometry::addRing
OperationResult addRing(const QVector< QgsPointXY > &ring)
Adds a new ring to this geometry.
Definition: qgsgeometry.cpp:680
QgsPointXY::setY
void setY(double y) SIP_HOLDGIL
Sets the y value of the point.
Definition: qgspointxy.h:117
QgsGeometryEngine::MethodNotImplemented
@ MethodNotImplemented
Method not implemented in geometry engine.
Definition: qgsgeometryengine.h:46
QgsGeometryUtils::lineAngle
static double lineAngle(double x1, double y1, double x2, double y2) SIP_HOLDGIL
Calculates the direction of line joining two points in radians, clockwise from the north direction.
Definition: qgsgeometryutils.cpp:1500
QgsGeometry::reshapeGeometry
OperationResult reshapeGeometry(const QgsLineString &reshapeLineString)
Replaces a part of this geometry with another line.
Definition: qgsgeometry.cpp:916
qgis.h
QgsGeos::area
double area(QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:586
QgsSurface
Definition: qgssurface.h:33
QgsLineString::yData
const double * yData() const
Returns a const pointer to the y vertex data.
Definition: qgslinestring.h:232
QgsAbstractGeometry::length
virtual double length() const
Returns the planar, 2-dimensional length of the geometry.
Definition: qgsabstractgeometry.cpp:132
QgsPointXY::toQPointF
QPointF toQPointF() const
Converts a point to a QPointF.
Definition: qgspointxy.h:154
QgsMultiPolygonXY
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
Definition: qgsgeometry.h:92
QgsGeometry::EndCapStyle
EndCapStyle
End cap styles for buffers.
Definition: qgsgeometry.h:1141
QgsGeometry::orthogonalize
QgsGeometry orthogonalize(double tolerance=1.0E-8, int maxIterations=1000, double angleThreshold=15.0) const
Attempts to orthogonalize a line or polygon geometry by shifting vertices to make the geometries angl...
Definition: qgsgeometry.cpp:1104
QgsGeometry::rotate
OperationResult rotate(double rotation, const QgsPointXY &center)
Rotate this geometry around the Z axis.
Definition: qgsgeometry.cpp:815
QgsGeometry::minimalEnclosingCircle
QgsGeometry minimalEnclosingCircle(QgsPointXY &center, double &radius, unsigned int segments=36) const
Returns the minimal enclosing circle for the geometry.
Definition: qgsgeometry.cpp:1069
QgsGeometry::const_parts_begin
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
Definition: qgsgeometry.cpp:1873
QgsWkbTypes::Type
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
QgsGeometry::operator=
QgsGeometry & operator=(QgsGeometry const &rhs)
Creates a deep copy of the object.
Definition: qgsgeometry.cpp:90
QgsGeometry::OperationResult
OperationResult
Success or failure of a geometry operation.
Definition: qgsgeometry.h:136
QgsAbstractGeometry::SegmentationToleranceType
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle.
Definition: qgsabstractgeometry.h:115
qgspoint.h
QgsGeos::buffer
QgsAbstractGeometry * buffer(double distance, int segments, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1545
QgsGeometry::moveVertex
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...
Definition: qgsgeometry.cpp:467
QgsInternalGeometryEngine::lastError
QString lastError() const
Returns an error string referring to the last error encountered.
Definition: qgsinternalgeometryengine.cpp:44
QgsWkbTypes::multiType
static Type multiType(Type type) SIP_HOLDGIL
Returns the multi type for a WKB type.
Definition: qgswkbtypes.h:302
QgsGeometryUtils::sqrDistance2D
static double sqrDistance2D(const QgsPoint &pt1, const QgsPoint &pt2) SIP_HOLDGIL
Returns the squared 2D distance between two points.
Definition: qgsgeometryutils.cpp:198
QgsLineString
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:44
QgsGeometry::overlaps
bool overlaps(const QgsGeometry &geometry) const
Returns true if the geometry overlaps another geometry.
Definition: qgsgeometry.cpp:1252
QgsGeometry::coerceToType
QVector< QgsGeometry > coerceToType(QgsWkbTypes::Type type) const
Attempts to coerce this geometry into the specified destination type.
Definition: qgsgeometry.cpp:1312
QgsPointXY::setX
void setX(double x) SIP_HOLDGIL
Sets the x value of the point.
Definition: qgspointxy.h:107
QgsGeometry::buffer
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...
Definition: qgsgeometry.cpp:1904
QgsGeometry::closestVertex
QgsPointXY closestVertex(const QgsPointXY &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 ...
Definition: qgsgeometry.cpp:386
QgsGeometry::deletePart
bool deletePart(int partNum)
Deletes part identified by the part number.
Definition: qgsgeometry.cpp:2581
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QgsGeometryPrivate
Definition: qgsgeometry.cpp:52
QgsGeometry::asMultiPolyline
QgsMultiPolylineXY asMultiPolyline() const
Returns the contents of the geometry as a multi-linestring.
Definition: qgsgeometry.cpp:1664
QgsMultiPointXY
QVector< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
Definition: qgsgeometry.h:81
QgsWkbTypes::PolygonGeometry
@ PolygonGeometry
Definition: qgswkbtypes.h:144
QgsGeometry::asGeometryCollection
QVector< QgsGeometry > asGeometryCollection() const
Returns contents of the geometry as a list of geometries.
Definition: qgsgeometry.cpp:2517
QgsGeos::hausdorffDistance
double hausdorffDistance(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const
Returns the Hausdorff distance between this geometry and geom.
Definition: qgsgeos.cpp:440
QgsPoint::project
QgsPoint project(double distance, double azimuth, double inclination=90.0) const SIP_HOLDGIL
Returns a new point which correspond to this point projected by a specified distance with specified a...
Definition: qgspoint.cpp:715
QgsLineString::xData
const double * xData() const
Returns a const pointer to the x vertex data.
Definition: qgslinestring.h:221
QgsGeometry::mergeLines
QgsGeometry mergeLines() const
Merges any connected lines in a LineString/MultiLineString geometry and converts them to single line ...
Definition: qgsgeometry.cpp:2421
QgsGeometryCollection::numGeometries
int numGeometries() const SIP_HOLDGIL
Returns the number of geometries within the collection.
Definition: qgsgeometrycollection.h:57
QgsGeometry::distanceToVertex
double distanceToVertex(int vertex) const
Returns the distance along this geometry from its first vertex to the specified vertex.
Definition: qgsgeometry.cpp:414
QgsGeometry::intersection
QgsGeometry intersection(const QgsGeometry &geometry) const
Returns a geometry representing the points shared by this geometry and other.
Definition: qgsgeometry.cpp:2380
QgsAbstractGeometry::vertexCount
virtual int vertexCount(int part=0, int ring=0) const =0
Returns the number of vertices of which this geometry is built.
QgsGeometry::insertVertex
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...
Definition: qgsgeometry.cpp:536
QgsGeometryEditUtils::deleteRing
static bool deleteRing(QgsAbstractGeometry *geom, int ringNum, int partNum=0)
Deletes a ring from a geometry.
Definition: qgsgeometryeditutils.cpp:176
QgsGeometry::isMultipart
bool isMultipart() const SIP_HOLDGIL
Returns true if WKB of the geometry is of WKBMulti* type.
Definition: qgsgeometry.cpp:377
QgsGeometry::nearestPoint
QgsGeometry nearestPoint(const QgsGeometry &other) const
Returns the nearest point on this geometry to another geometry.
Definition: qgsgeometry.cpp:610
QgsAbstractGeometry::vertexAt
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
qgsapplication.h
QgsAbstractGeometry::isMeasure
bool isMeasure() const SIP_HOLDGIL
Returns true if the geometry contains m values.
Definition: qgsabstractgeometry.h:215
QgsGeometry::createPolylineFromQPolygonF
static Q_DECL_DEPRECATED QgsPolylineXY createPolylineFromQPolygonF(const QPolygonF &polygon)
Creates a QgsPolylineXY from a QPolygonF.
Definition: qgsgeometry.cpp:3097
QgsCircle::from2Points
static QgsCircle from2Points(const QgsPoint &pt1, const QgsPoint &pt2) SIP_HOLDGIL
Constructs a circle by 2 points on the circle.
Definition: qgscircle.cpp:37
QgsGeometry::convertToStraightSegment
void convertToStraightSegment(double tolerance=M_PI/180., QgsAbstractGeometry::SegmentationToleranceType toleranceType=QgsAbstractGeometry::MaximumAngle)
Converts the geometry to straight line segments, if it is a curved geometry type.
Definition: qgsgeometry.cpp:2792
QgsGeometry::isGeosEqual
bool isGeosEqual(const QgsGeometry &) const
Compares the geometry with another geometry using GEOS.
Definition: qgsgeometry.cpp:2731
QgsGeometry::deleteRing
bool deleteRing(int ringNum, int partNum=0)
Deletes a ring in polygon or multipolygon.
Definition: qgsgeometry.cpp:2569
QgsCurvePolygon::numInteriorRings
int numInteriorRings() const SIP_HOLDGIL
Returns the number of interior rings contained with the curve polygon.
Definition: qgscurvepolygon.h:77
QgsAbstractGeometry::part_iterator
The part_iterator class provides STL-style iterator for geometry parts.
Definition: qgsabstractgeometry.h:726
MathUtils::leftOf
double ANALYSIS_EXPORT leftOf(const QgsPoint &thepoint, const QgsPoint *p1, const QgsPoint *p2)
Returns whether 'thepoint' is left or right of the line from 'p1' to 'p2'. Negative values mean left ...
Definition: MathUtils.cpp:292
Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:797
QgsGeometryCollection::createEmptyWithSameType
QgsGeometryCollection * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
Definition: qgsgeometrycollection.cpp:111
QgsRectangle::xMaximum
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:162
QgsAbstractGeometry::area
virtual double area() const
Returns the planar, 2-dimensional area of the geometry.
Definition: qgsabstractgeometry.cpp:142
QgsPoint::y
double y
Definition: qgspoint.h:42
QgsGeometry::Error::hasWhere
bool hasWhere() const
true if the location available from
Definition: qgsgeometry.cpp:3672
precision
int precision
Definition: qgswfsgetfeature.cpp:49
QgsWkbTypes::MultiLineString
@ MultiLineString
Definition: qgswkbtypes.h:77
QgsGeometryCollection
Geometry collection.
Definition: qgsgeometrycollection.h:36
QgsGeometry::asQPolygonF
QPolygonF asQPolygonF() const SIP_HOLDGIL
Returns contents of the geometry as a QPolygonF.
Definition: qgsgeometry.cpp:2549
QgsGeometry::poleOfInaccessibility
QgsGeometry poleOfInaccessibility(double precision, double *distanceToBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...
Definition: qgsgeometry.cpp:2177
QgsGeometry::asPolygon
QgsPolygonXY asPolygon() const
Returns the contents of the geometry as a polygon.
Definition: qgsgeometry.cpp:1605
QgsGeometry::intersects
bool intersects(const QgsRectangle &rectangle) const
Returns true if this geometry exactly intersects with a rectangle.
Definition: qgsgeometry.cpp:1129
QgsLineString::clone
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
Definition: qgslinestring.cpp:293
QgsGeometryCollection::partCount
int partCount() const override
Returns count of parts contained in the geometry.
Definition: qgsgeometrycollection.cpp:852
QgsGeometryEngine::NodedGeometryError
@ NodedGeometryError
Error occurred while creating a noded geometry.
Definition: qgsgeometryengine.h:48
QgsCircularString
Circular string geometry type.
Definition: qgscircularstring.h:35
QgsGeometry::densifyByCount
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Returns a copy of the geometry which has been densified by adding the specified number of extra nodes...
Definition: qgsgeometry.cpp:2117
QgsGeometryEngine::InvalidBaseGeometry
@ InvalidBaseGeometry
The geometry on which the operation occurs is not valid.
Definition: qgsgeometryengine.h:49
QgsAbstractGeometry::wkbType
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
Definition: qgsabstractgeometry.h:193
QgsGeometryFactory::fromMultiPolylineXY
static std::unique_ptr< QgsMultiLineString > fromMultiPolylineXY(const QgsMultiPolylineXY &multiline)
Construct geometry from a multipolyline.
Definition: qgsgeometryfactory.cpp:162
QgsGeometryFactory::createCollectionOfType
static std::unique_ptr< QgsGeometryCollection > createCollectionOfType(QgsWkbTypes::Type type)
Returns a new geometry collection matching a specified WKB type.
Definition: qgsgeometryfactory.cpp:264
qgsmultipolygon.h
QgsGeometry::randomPointsInPolygon
QVector< QgsPointXY > randomPointsInPolygon(int count, const std::function< bool(const QgsPointXY &) > &acceptPoint, unsigned long seed=0, QgsFeedback *feedback=nullptr, int maxTriesPerPoint=0) const
Returns a list of count random points generated inside a (multi)polygon geometry (if acceptPoint is s...
QgsWkbTypes::Unknown
@ Unknown
Definition: qgswkbtypes.h:71
QgsGeometry::wkbSize
int wkbSize(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const
Returns the length of the QByteArray returned by asWkb()
Definition: qgsgeometry.cpp:2507
QgsGeometry::fromMultiPointXY
static QgsGeometry fromMultiPointXY(const QgsMultiPointXY &multipoint)
Creates a new geometry from a QgsMultiPointXY object.
Definition: qgsgeometry.cpp:199
QgsGeometry::extendLine
QgsGeometry extendLine(double startDistance, double endDistance) const
Extends a (multi)line geometry by extrapolating out the start or end of the line by a specified dista...
Definition: qgsgeometry.cpp:2058
QgsGeometryEditUtils::avoidIntersections
static std::unique_ptr< QgsAbstractGeometry > avoidIntersections(const QgsAbstractGeometry &geom, const QList< QgsVectorLayer * > &avoidIntersectionsLayers, const QHash< QgsVectorLayer *, QSet< QgsFeatureId > > &ignoreFeatures=(QHash< QgsVectorLayer *, QSet< QgsFeatureId > >()))
Alters a geometry so that it avoids intersections with features from all open vector layers.
Definition: qgsgeometryeditutils.cpp:225
QgsGeometryUtils::verticesAtDistance
static bool verticesAtDistance(const QgsAbstractGeometry &geometry, double distance, QgsVertexId &previousVertex, QgsVertexId &nextVertex)
Retrieves the vertices which are before and after the interpolated point at a specified distance alon...
Definition: qgsgeometryutils.cpp:153
QgsInternalGeometryEngine::convertToCurves
QgsGeometry convertToCurves(double distanceTolerance, double angleTolerance) const
Attempts to convert a non-curved geometry into a curved geometry type (e.g.
Definition: qgsinternalgeometryengine.cpp:1409
QgsGeometry::Error::what
QString what() const
A human readable error message containing details about the error.
Definition: qgsgeometry.cpp:3662
QgsGeometry::sqrDistToVertexAt
double sqrDistToVertexAt(QgsPointXY &point SIP_IN, int atVertex) const
Returns the squared Cartesian distance between the given point to the given vertex index (vertex at t...
Definition: qgsgeometry.cpp:604
QgsGeometry::offsetCurve
QgsGeometry offsetCurve(double distance, int segments, JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
Definition: qgsgeometry.cpp:1942
QgsRectangle::contains
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
Definition: qgsrectangle.h:342
QgsGeometry::smooth
QgsGeometry smooth(unsigned int iterations=1, double offset=0.25, double minimumDistance=-1.0, double maxAngle=180.0) const
Smooths a geometry by rounding off corners using the Chaikin algorithm.
Definition: qgsgeometry.cpp:3148
QgsInternalGeometryEngine
This class offers geometry processing methods.
Definition: qgsinternalgeometryengine.h:42
QgsAbstractGeometry::const_part_iterator
The part_iterator class provides STL-style iterator for const references to geometry parts.
Definition: qgsabstractgeometry.h:796
QgsGeometry::Error::where
QgsPointXY where() const
The coordinates at which the error is located and should be visualized.
Definition: qgsgeometry.cpp:3667
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:315
QgsConstWkbPtr
Definition: qgswkbptr.h:128
QgsFeedback
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:44
QgsGeometry::convertToSingleType
bool convertToSingleType()
Converts multi type geometry into single type geometry e.g.
Definition: qgsgeometry.cpp:1485
QgsGeometry::equals
bool equals(const QgsGeometry &geometry) const
Test if this geometry is exactly equal to another geometry.
Definition: qgsgeometry.cpp:1221
QgsGeometry::FlagAllowSelfTouchingHoles
@ FlagAllowSelfTouchingHoles
Indicates that self-touching holes are permitted. OGC validity states that self-touching holes are NO...
Definition: qgsgeometry.h:369
QgsGeometryCollection::addGeometry
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
Definition: qgsgeometrycollection.cpp:226
QgsGeometry::variableWidthBufferByM
QgsGeometry variableWidthBufferByM(int segments) const
Calculates a variable width buffer for a (multi)linestring geometry, where the width at each node is ...
Definition: qgsgeometry.cpp:2051
qgscircle.h
QgsGeometry::taperedBuffer
QgsGeometry taperedBuffer(double startWidth, double endWidth, int segments) const
Calculates a variable width buffer ("tapered buffer") for a (multi)curve geometry.
Definition: qgsgeometry.cpp:2044
QgsAbstractGeometry::clone
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
QgsGeos
Does vector analysis using the geos library and handles import, export, exception handling*.
Definition: qgsgeos.h:104
QgsGeometryUtils::averageAngle
static double averageAngle(double x1, double y1, double x2, double y2, double x3, double y3) SIP_HOLDGIL
Calculates the average angle (in radians) between the two linear segments from (x1,...
Definition: qgsgeometryutils.cpp:1521
QgsGeometryFactory::fromMultiPointXY
static std::unique_ptr< QgsMultiPoint > fromMultiPointXY(const QgsMultiPointXY &multipoint)
Construct geometry from a multipoint.
Definition: qgsgeometryfactory.cpp:144
QgsGeometry::ValidatorQgisInternal
@ ValidatorQgisInternal
Use internal QgsGeometryValidator method.
Definition: qgsgeometry.h:2114
QgsLineString::fromQPolygonF
static QgsLineString * fromQPolygonF(const QPolygonF &polygon)
Returns a new linestring from a QPolygonF polygon input.
Definition: qgslinestring.cpp:245
QgsWkbTypes::CurvePolygon
@ CurvePolygon
Definition: qgswkbtypes.h:82
QgsCircle::radius
double radius() const SIP_HOLDGIL
Returns the radius of the circle.
Definition: qgscircle.h:247
QgsGeometry::convexHull
QgsGeometry convexHull() const
Returns the smallest convex polygon that contains all the points in the geometry.
Definition: qgsgeometry.cpp:2184
QgsGeometry::deleteVertex
bool deleteVertex(int atVertex)
Deletes the vertex at the given position number and item (first number is index 0)
Definition: qgsgeometry.cpp:503
QgsPoint::setX
void setX(double x) SIP_HOLDGIL
Sets the point's x-coordinate.
Definition: qgspoint.h:269
QgsAttributeMap
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:38
QgsWkbTypes::hasM
static bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1093
QgsGeometry::densifyByDistance
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
Definition: qgsgeometry.cpp:2124
QgsPoint::x
Q_GADGET double x
Definition: qgspoint.h:41
QgsCircle::toCircularString
QgsCircularString * toCircularString(bool oriented=false) const
Returns a circular string from the circle.
Definition: qgscircle.cpp:327
QgsGeometryFactory::geomFromWkt
static std::unique_ptr< QgsAbstractGeometry > geomFromWkt(const QString &text)
Construct geometry from a WKT string.
Definition: qgsgeometryfactory.cpp:72
QgsGeometry::length
double length() const
Returns the planar, 2-dimensional length of geometry.
Definition: qgsgeometry.cpp:1783
QgsMultiPolylineXY
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
Definition: qgsgeometry.h:85
QgsGeometry::isEmpty
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
Definition: qgsgeometry.cpp:367
QgsGeometry::extrude
QgsGeometry extrude(double x, double y)
Returns an extruded version of this geometry.
Definition: qgsgeometry.cpp:2481
QgsGeometry::crosses
bool crosses(const QgsGeometry &geometry) const
Returns true if the geometry crosses another geometry.
Definition: qgsgeometry.cpp:1276
QgsMultiPolygon
Multi polygon geometry collection.
Definition: qgsmultipolygon.h:32
QgsGeometry::draw
void draw(QPainter &p) const
Draws the geometry onto a QPainter.
Definition: qgsgeometry.cpp:2865
QgsGeometry::transformVertices
void transformVertices(const std::function< QgsPoint(const QgsPoint &) > &transform)
Transforms the vertices from the geometry in place, applying the transform function to every vertex.
Definition: qgsgeometry.cpp:3010
QgsGeometry::asQPointF
QPointF asQPointF() const SIP_HOLDGIL
Returns contents of the geometry as a QPointF if wkbType is WKBPoint, otherwise returns a null QPoint...
Definition: qgsgeometry.cpp:2543
QgsGeometry::clipped
QgsGeometry clipped(const QgsRectangle &rectangle)
Clips the geometry using the specified rectangle.
Definition: qgsgeometry.cpp:2846
QgsInternalGeometryEngine::orientedMinimumBoundingBox
QgsGeometry orientedMinimumBoundingBox(double &area, double &angle, double &width, double &height) const
Returns the oriented minimum bounding box for the geometry, which is the smallest (by area) rotated r...
Definition: qgsinternalgeometryengine.cpp:1452
QgsRectangle::xMinimum
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
QgsGeometryPrivate::geometry
std::unique_ptr< QgsAbstractGeometry > geometry
Definition: qgsgeometry.cpp:55
QgsCurvePolygon::interiorRing
const QgsCurve * interiorRing(int i) const SIP_HOLDGIL
Retrieves an interior ring from the curve polygon.
Definition: qgscurvepolygon.h:100
QgsGeometry::splitGeometry
Q_DECL_DEPRECATED OperationResult splitGeometry(const QVector< QgsPointXY > &splitLine, QVector< QgsGeometry > &newGeometries, bool topological, QVector< QgsPointXY > &topologyTestPoints, bool splitFeature=true)
Splits this geometry according to a given line.
Definition: qgsgeometry.cpp:831
QgsEllipse::center
QgsPoint center() const SIP_HOLDGIL
Returns the center point.
Definition: qgsellipse.h:121
QgsRingSequence
QVector< QgsPointSequence > QgsRingSequence
Definition: qgsabstractgeometry.h:50
QgsGeometry::pointOnSurface
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
Definition: qgsgeometry.cpp:2162
QgsGeometry::constGet
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Definition: qgsgeometry.cpp:128
QgsGeometry::InvalidInputGeometryType
@ InvalidInputGeometryType
The input geometry (ring, part, split line, etc.) has not the correct geometry type.
Definition: qgsgeometry.h:140
QgsGeometry::touches
bool touches(const QgsGeometry &geometry) const
Returns true if the geometry touches another geometry.
Definition: qgsgeometry.cpp:1240
QgsGeometry::fromWkt
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
Definition: qgsgeometry.cpp:154
QgsMultiPoint
Multi point geometry collection.
Definition: qgsmultipoint.h:30
QgsMapToPixel::transform
QgsPointXY transform(const QgsPointXY &p) const
Transform the point from map (world) coordinates to device coordinates.
Definition: qgsmaptopixel.cpp:217
QgsGeometryUtils::closestVertex
static QgsPoint closestVertex(const QgsAbstractGeometry &geom, const QgsPoint &pt, QgsVertexId &id)
Returns the closest vertex to a geometry for a specified point.
Definition: qgsgeometryutils.cpp:67
QgsAbstractGeometry
Abstract base class for all geometries.
Definition: qgsabstractgeometry.h:74
QgsGeometryPrivate::QgsGeometryPrivate
QgsGeometryPrivate()
Definition: qgsgeometry.cpp:53
QgsGeometry::simplify
QgsGeometry simplify(double tolerance) const
Returns a simplified version of this geometry using a specified tolerance value.
Definition: qgsgeometry.cpp:2098
QgsCurvePolygon::coordinateSequence
QgsCoordinateSequence coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
Definition: qgscurvepolygon.cpp:846
qgsgeometryutils.h
_qgis_lwgeom_make_valid
std::unique_ptr< QgsAbstractGeometry > _qgis_lwgeom_make_valid(const QgsAbstractGeometry *lwgeom_in, QString &errorMessage)
Implementation of QgsGeometry::makeValid(). Not a public API.
Definition: qgsgeometrymakevalid.cpp:903
QgsGeometryEditUtils::deletePart
static bool deletePart(QgsAbstractGeometry *geom, int partNum)
Deletes a part from a geometry.
Definition: qgsgeometryeditutils.cpp:209
QgsAbstractGeometry::is3D
bool is3D() const SIP_HOLDGIL
Returns true if the geometry is 3D and contains a z-value.
Definition: qgsabstractgeometry.h:206
QgsGeometry::vertexAt
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
Definition: qgsgeometry.cpp:588
QgsMultiPoint::pointN
QgsPoint * pointN(int index)
Returns the point with the specified index.
Definition: qgsmultipoint.cpp:31
qgsvectorlayer.h
QgsPolyline
QgsPointSequence QgsPolyline
Polyline as represented as a vector of points.
Definition: qgsgeometry.h:71
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:44
QgsGeometry::QgsGeometry
QgsGeometry() SIP_HOLDGIL
Constructor.
Definition: qgsgeometry.cpp:58
QgsLineString::dropMValue
bool dropMValue() override
Drops any measure values which exist in the geometry.
Definition: qgslinestring.cpp:1675
QgsGeometry::hausdorffDistance
double hausdorffDistance(const QgsGeometry &geom) const
Returns the Hausdorff distance between this geometry and geom.
Definition: qgsgeometry.cpp:1812
QgsAbstractGeometry::boundingBox
virtual QgsRectangle boundingBox() const =0
Returns the minimal bounding box for the geometry.
QgsGeometry::asPoint
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Definition: qgsgeometry.cpp:1544
QgsInternalGeometryEngine::densifyByDistance
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
Definition: qgsinternalgeometryengine.cpp:696
QgsGeometryUtils::distanceToVertex
static double distanceToVertex(const QgsAbstractGeometry &geom, QgsVertexId id)
Returns the distance along a geometry from its first vertex to the specified vertex.
Definition: qgsgeometryutils.cpp:134
QgsGeometry::convertToCurves
QgsGeometry convertToCurves(double distanceTolerance=1e-8, double angleTolerance=1e-8) const
Attempts to convert a non-curved geometry into a curved geometry type (e.g.
Definition: qgsgeometry.cpp:2131
QgsGeometry::asJsonObject
virtual json asJsonObject(int precision=17) const
Exports the geometry to a json object.
Definition: qgsgeometry.cpp:1302
QgsVertexId::isValid
bool isValid() const SIP_HOLDGIL
Returns true if the vertex id is valid.
Definition: qgsabstractgeometry.h:1083
QgsGeometry::polygonize
static QgsGeometry polygonize(const QVector< QgsGeometry > &geometries)
Creates a GeometryCollection geometry containing possible polygons formed from the constituent linewo...
Definition: qgsgeometry.cpp:2773
QgsGeometry::requiresConversionToStraightSegments
bool requiresConversionToStraightSegments() const
Returns true if the geometry is a curved geometry type which requires conversion to display as straig...
Definition: qgsgeometry.cpp:2803
QgsGeometryEngine::NothingHappened
@ NothingHappened
Nothing happened, without any error.
Definition: qgsgeometryengine.h:45
QgsGeometry::get
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
Definition: qgsgeometry.cpp:133
QgsGeometry::createGeometryEngine
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine.
Definition: qgsgeometry.cpp:3636
QgsWkbTypes::isCurvedType
static bool isCurvedType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a curved type or can contain curved geometries.
Definition: qgswkbtypes.h:881
QgsWkbTypes::LineGeometry
@ LineGeometry
Definition: qgswkbtypes.h:143
QgsGeometry::asWkt
QString asWkt(int precision=17) const
Exports the geometry to WKT.
Definition: qgsgeometry.cpp:1288
QgsWkbTypes::CircularString
@ CircularString
Definition: qgswkbtypes.h:80
QgsWkbTypes::PointGeometry
@ PointGeometry
Definition: qgswkbtypes.h:142
QgsGeometry::interpolateAngle
double interpolateAngle(double distance) const
Returns the angle parallel to the linestring or polygon boundary at the specified distance along the ...
Definition: qgsgeometry.cpp:2326
QgsGeometryEngine::SplitCannotSplitPoint
@ SplitCannotSplitPoint
Points cannot be split.
Definition: qgsgeometryengine.h:52
QgsGeometry::fromPolygonXY
static QgsGeometry fromPolygonXY(const QgsPolygonXY &polygon)
Creates a new geometry from a QgsPolygon.
Definition: qgsgeometry.cpp:189
QgsRectangle::yMaximum
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:172
QgsGeometryCollection::geometryN
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
Definition: qgsgeometrycollection.h:85
QgsWkbTypes::NoGeometry
@ NoGeometry
Definition: qgswkbtypes.h:85
QgsGeometry::makeValid
QgsGeometry makeValid() const
Attempts to make an invalid geometry valid without losing vertices.
Definition: qgsgeometry.cpp:2615
QgsGeometry::BufferSide
BufferSide
Side of line to buffer.
Definition: qgsgeometry.h:1133
qgsgeometry.h
QgsGeometry::convertPointList
static void convertPointList(const QVector< QgsPointXY > &input, QgsPointSequence &output)
Upgrades a point list from QgsPointXY to QgsPoint.
Definition: qgsgeometry.cpp:3020
QgsWkbTypes::GeometryType
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:141
QgsAbstractGeometry::vertex_iterator
The vertex_iterator class provides STL-style iterator for vertices.
Definition: qgsabstractgeometry.h:856
QgsGeometry::shortestLine
QgsGeometry shortestLine(const QgsGeometry &other) const
Returns the shortest line joining this geometry to another geometry.
Definition: qgsgeometry.cpp:625
QgsPointSequence
QVector< QgsPoint > QgsPointSequence
Definition: qgsabstractgeometry.h:46
QgsGeos::length
double length(QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:603
qgscurve.h
c
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Definition: porting_processing.dox:1
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsMapToPixel
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:38
QgsGeometryPartIterator
Java-style iterator for traversal of parts of a geometry.
Definition: qgsabstractgeometry.h:1219
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
QgsGeometry::InvalidBaseGeometry
@ InvalidBaseGeometry
The base geometry on which the operation is done is invalid or empty.
Definition: qgsgeometry.h:139
QgsGeometry::snappedToGrid
QgsGeometry snappedToGrid(double hSpacing, double vSpacing, double dSpacing=0, double mSpacing=0) const
Returns a new geometry with all points or vertices snapped to the closest point of the grid.
Definition: qgsgeometry.cpp:1111
QgsMultiLineString::lineStringN
QgsLineString * lineStringN(int index)
Returns the line string with the specified index.
Definition: qgsmultilinestring.cpp:33
QgsGeometryEditUtils::addPart
static QgsGeometry::OperationResult addPart(QgsAbstractGeometry *geometry, std::unique_ptr< QgsAbstractGeometry > part)
Add a part to multi type geometry.
Definition: qgsgeometryeditutils.cpp:98
QgsGeometry::singleSidedBuffer
QgsGeometry singleSidedBuffer(double distance, int segments, BufferSide side, JoinStyle joinStyle=JoinStyleRound, double miterLimit=2.0) const
Returns a single sided buffer for a (multi)line geometry.
Definition: qgsgeometry.cpp:2000
QgsWkbTypes::Polygon
@ Polygon
Definition: qgswkbtypes.h:74
QgsGeometry::convertToMultiType
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
Definition: qgsgeometry.cpp:1453
qgsgeometryeditutils.h
QgsWkbTypes::MultiPoint
@ MultiPoint
Definition: qgswkbtypes.h:76
QgsGeometryEngine::Success
@ Success
Operation succeeded.
Definition: qgsgeometryengine.h:44
QgsGeometry::translate
OperationResult translate(double dx, double dy, double dz=0.0, double dm=0.0)
Translates this geometry by dx, dy, dz and dm.
Definition: qgsgeometry.cpp:802
QgsGeometry::fromRect
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
Definition: qgsgeometry.cpp:229
QgsVertexId
Utility class for identifying a unique vertex within a geometry.
Definition: qgsabstractgeometry.h:1059
QgsCircularString::fromTwoPointsAndCenter
static QgsCircularString fromTwoPointsAndCenter(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &center, bool useShortestArc=true)
Creates a circular string with a single arc representing the curve from p1 to p2 with the specified c...
Definition: qgscircularstring.cpp:72
QgsGeometry::forceRHR
QgsGeometry forceRHR() const
Forces geometries to respect the Right-Hand-Rule, in which the area that is bounded by a polygon is t...
Definition: qgsgeometry.cpp:2628
QgsGeometry::convertToType
QgsGeometry convertToType(QgsWkbTypes::GeometryType destType, bool destMultipart=false) const
Try to convert the geometry to the requested type.
Definition: qgsgeometry.cpp:1435
QgsGeometry::closestVertexWithContext
double closestVertexWithContext(const QgsPointXY &point, int &atVertex) const
Searches for the closest vertex in this geometry to the given point.
Definition: qgsgeometry.cpp:640
QgsGeometry::vertexNrFromVertexId
int vertexNrFromVertexId(QgsVertexId id) const
Returns the vertex number corresponding to a vertex id.
Definition: qgsgeometry.cpp:2986
QgsGeometry::mapToPixel
void mapToPixel(const QgsMapToPixel &mtp)
Transforms the geometry from map units to pixels in place.
Definition: qgsgeometry.cpp:2837
QgsGeometry::makeDifference
QgsGeometry makeDifference(const QgsGeometry &other) const
Returns the geometry formed by modifying this geometry such that it does not intersect the other geom...
Definition: qgsgeometry.cpp:975
QgsWkbTypes::UnknownGeometry
@ UnknownGeometry
Definition: qgswkbtypes.h:145
QgsGeometry::asPolyline
QgsPolylineXY asPolyline() const
Returns the contents of the geometry as a polyline.
Definition: qgsgeometry.cpp:1559
QgsGeometry::vertices
QgsVertexIterator vertices() const
Returns a read-only, Java-style iterator for traversal of vertices of all the geometry,...
Definition: qgsgeometry.cpp:1850
QgsWkbTypes::geometryType
static GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:938
QgsGeometry::~QgsGeometry
virtual ~QgsGeometry()
Definition: qgsgeometry.cpp:63
QgsGeometry::voronoiDiagram
QgsGeometry voronoiDiagram(const QgsGeometry &extent=QgsGeometry(), double tolerance=0.0, bool edgesOnly=false) const
Creates a Voronoi diagram for the nodes contained within the geometry.
Definition: qgsgeometry.cpp:2202
QgsGeometry::asMultiPoint
QgsMultiPointXY asMultiPoint() const
Returns the contents of the geometry as a multi-point.
Definition: qgsgeometry.cpp:1640
QgsGeometry::isSimple
bool isSimple() const
Determines whether the geometry is simple (according to OGC definition), i.e.
Definition: qgsgeometry.cpp:2721
QgsAbstractGeometry::boundary
virtual QgsAbstractGeometry * boundary() const =0
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
QgsGeometry::createWedgeBuffer
static QgsGeometry createWedgeBuffer(const QgsPoint &center, double azimuth, double angularWidth, double outerRadius, double innerRadius=0)
Creates a wedge shaped buffer from a center point.
Definition: qgsgeometry.cpp:276
QgsGeometryEngine::EngineOperationResult
EngineOperationResult
Success or failure of a geometry operation.
Definition: qgsgeometryengine.h:43
QgsGeometry::ValidationMethod
ValidationMethod
Available methods for validating geometries.
Definition: qgsgeometry.h:2113
QgsVertexIterator
Java-style iterator for traversal of vertices of a geometry.
Definition: qgsabstractgeometry.h:1170
QgsGeometry::boundingBox
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Definition: qgsgeometry.cpp:996
QgsWkbTypes::hasZ
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:1043
QgsEllipse::toPolygon
virtual QgsPolygon * toPolygon(unsigned int segments=36) const
Returns a segmented polygon.
Definition: qgsellipse.cpp:224
qgsmulticurve.h
QgsGeometry::vertexIdFromVertexNr
bool vertexIdFromVertexNr(int number, QgsVertexId &id) const
Calculates the vertex ID from a vertex number.
Definition: qgsgeometry.cpp:2950
QgsGeometry::JoinStyle
JoinStyle
Join styles for buffers.
Definition: qgsgeometry.h:1150
QgsGeometry::fromQPolygonF
static QgsGeometry fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
Definition: qgsgeometry.cpp:3072
QgsGeometry::symDifference
QgsGeometry symDifference(const QgsGeometry &geometry) const
Returns a geometry representing the points making up this geometry that do not make up other.
Definition: qgsgeometry.cpp:2461
QgsGeometry::contains
bool contains(const QgsPointXY *p) const
Returns true if the geometry contains the point p.
Definition: qgsgeometry.cpp:1184
QgsCurve::numPoints
virtual int numPoints() const =0
Returns the number of points in the curve.
QgsGeometry::vertices_end
QgsAbstractGeometry::vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
Definition: qgsgeometry.cpp:1843
QgsGeometry::parts_begin
QgsAbstractGeometry::part_iterator parts_begin()
Returns STL-style iterator pointing to the first part of the geometry.
Definition: qgsgeometry.cpp:1857
QgsGeometry::isGeosValid
bool isGeosValid(QgsGeometry::ValidityFlags flags=QgsGeometry::ValidityFlags()) const
Checks validity of the geometry using GEOS.
Definition: qgsgeometry.cpp:2711
QgsGeometryUtils::angleBetweenThreePoints
static double angleBetweenThreePoints(double x1, double y1, double x2, double y2, double x3, double y3) SIP_HOLDGIL
Calculates the angle between the lines AB and BC, where AB and BC described by points a,...
Definition: qgsgeometryutils.cpp:1507
QgsGeometry::adjacentVertices
void adjacentVertices(int atVertex, int &beforeVertex, int &afterVertex) const
Returns the indexes of the vertices before and after the given vertex index.
Definition: qgsgeometry.cpp:446
qgslogger.h
QgsCurve::segmentize
QgsCurve * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
Definition: qgscurve.cpp:166
QgsGeometry::vertices_begin
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
Definition: qgsgeometry.cpp:1836
QgsLineString::numPoints
int numPoints() const override SIP_HOLDGIL
Returns the number of points in the curve.
Definition: qgslinestring.cpp:703
QgsCurve::Orientation
Orientation
Curve orientation.
Definition: qgscurve.h:239
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:53
QgsWkbTypes::isMultiType
static bool isMultiType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a multi type.
Definition: qgswkbtypes.h:832
QgsGeometry::type
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:127
qgsgeometrymakevalid.h
Q_NOWARN_DEPRECATED_PUSH
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:796
QgsGeometryValidator::validateGeometry
static void validateGeometry(const QgsGeometry &geometry, QVector< QgsGeometry::Error > &errors, QgsGeometry::ValidationMethod method=QgsGeometry::ValidatorQgisInternal)
Validate geometry and produce a list of geometry errors.
Definition: qgsgeometryvalidator.cpp:390
QgsGeometryFactory::geomFromWkbType
static std::unique_ptr< QgsAbstractGeometry > geomFromWkbType(QgsWkbTypes::Type t)
Returns empty geometry from wkb type.
Definition: qgsgeometryfactory.cpp:228
QgsGeometryEngine
Contains geometry relation and modification algorithms.
Definition: qgsgeometryengine.h:35
QgsRectangle::isEmpty
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:437
MathUtils::angle
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
QgsGeometry::area
double area() const
Returns the planar, 2-dimensional area of the geometry.
Definition: qgsgeometry.cpp:1760
QgsGeometry::compare
static bool compare(const QgsPolylineXY &p1, const QgsPolylineXY &p2, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compares two polylines for equality within a specified tolerance.
Definition: qgsgeometry.cpp:3108
QgsAbstractGeometry::ringCount
virtual int ringCount(int part=0) const =0
Returns the number of rings of which this geometry is built.
QgsCurve::curveToLine
virtual QgsLineString * 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.
QgsRectangle::isNull
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:447
QgsGeometry::set
void set(QgsAbstractGeometry *geometry)
Sets the underlying geometry store.
Definition: qgsgeometry.cpp:139
qgsmultisurface.h
QgsGeometry::difference
QgsGeometry difference(const QgsGeometry &geometry) const
Returns a geometry representing the points making up this geometry that do not make up other.
Definition: qgsgeometry.cpp:2441
QgsGeometryUtils::interpolatePointOnLine
static QgsPointXY interpolatePointOnLine(double x1, double y1, double x2, double y2, double fraction) SIP_HOLDGIL
Interpolates the position of a point a fraction of the way along the line from (x1,...
Definition: qgsgeometryutils.cpp:1411
QgsGeometry::boundingBoxIntersects
bool boundingBoxIntersects(const QgsRectangle &rectangle) const
Returns true if the bounding box of this geometry intersects with a rectangle.
Definition: qgsgeometry.cpp:1157
QgsMultiPolygon::polygonN
QgsPolygon * polygonN(int index)
Returns the polygon with the specified index.
Definition: qgsmultipolygon.cpp:33
QgsGeometryFactory::fromPolylineXY
static std::unique_ptr< QgsAbstractGeometry > fromPolylineXY(const QgsPolylineXY &polyline)
Construct geometry from a polyline.
Definition: qgsgeometryfactory.cpp:157
QgsGeometry::wkbType
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
Definition: qgsgeometry.cpp:345
qgspointxy.h
qgsmultilinestring.h
QgsGeometry::delaunayTriangulation
QgsGeometry delaunayTriangulation(double tolerance=0.0, bool edgesOnly=false) const
Returns the Delaunay triangulation for the vertices of the geometry.
Definition: qgsgeometry.cpp:2216
qgsgeometryvalidator.h
QgsGeometry::fromMultiPolygonXY
static QgsGeometry fromMultiPolygonXY(const QgsMultiPolygonXY &multipoly)
Creates a new geometry from a QgsMultiPolygon.
Definition: qgsgeometry.cpp:219
qgsgeos.h
QgsInternalGeometryEngine::taperedBuffer
QgsGeometry taperedBuffer(double startWidth, double endWidth, int segments) const
Calculates a tapered width buffer for a (multi)curve geometry.
Definition: qgsinternalgeometryengine.cpp:1009
QgsGeometry::unaryUnion
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries)
Compute the unary union on a list of geometries.
Definition: qgsgeometry.cpp:2762
QgsGeometry::closestSegmentWithContext
double closestSegmentWithContext(const QgsPointXY &point, QgsPointXY &minDistPoint, int &afterVertex, int *leftOf=nullptr, double epsilon=DEFAULT_SEGMENT_EPSILON) const
Searches for the closest segment of geometry to the given point.
Definition: qgsgeometry.cpp:656
QgsGeometry::constParts
QgsGeometryConstPartIterator constParts() const
Returns Java-style iterator for traversal of parts of the geometry.
Definition: qgsgeometry.cpp:1896
QgsGeometry::collectGeometry
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
Definition: qgsgeometry.cpp:247
QgsGeometry::orientedMinimumBoundingBox
QgsGeometry orientedMinimumBoundingBox() const
Returns the oriented minimum bounding box for the geometry, which is the smallest (by area) rotated r...
Definition: qgsgeometry.cpp:1015
QgsGeometry::asMultiPolygon
QgsMultiPolygonXY asMultiPolygon() const
Returns the contents of the geometry as a multi-polygon.
Definition: qgsgeometry.cpp:1717
QgsGeometry::GeometryEngineError
@ GeometryEngineError
Geometry engine misses a method implemented or an error occurred in the geometry engine.
Definition: qgsgeometry.h:143
QgsWkbTypes::CompoundCurve
@ CompoundCurve
Definition: qgswkbtypes.h:81
QgsGeometry::parts_end
QgsAbstractGeometry::part_iterator parts_end()
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
Definition: qgsgeometry.cpp:1866
qgsmessagelog.h
QgsGeometryFactory::fromPointXY
static std::unique_ptr< QgsAbstractGeometry > fromPointXY(const QgsPointXY &point)
Construct geometry from a point.
Definition: qgsgeometryfactory.cpp:139
QgsGeometry::lineLocatePoint
double lineLocatePoint(const QgsGeometry &point) const
Returns a distance representing the location along this linestring of the closest point on this lines...
Definition: qgsgeometry.cpp:2307
QgsGeometry::disjoint
bool disjoint(const QgsGeometry &geometry) const
Returns true if the geometry is disjoint of another geometry.
Definition: qgsgeometry.cpp:1209
QgsLineString::dropZValue
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
Definition: qgslinestring.cpp:1664