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