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