QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgscurvepolygon.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscurvepolygon.cpp
3  ---------------------
4  begin : September 2014
5  copyright : (C) 2014 by Marco Hugentobler
6  email : marco at sourcepole dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgscurvepolygon.h"
19 #include "qgsapplication.h"
20 #include "qgscircularstring.h"
21 #include "qgscompoundcurve.h"
22 #include "qgsgeometryutils.h"
23 #include "qgslinestring.h"
24 #include "qgspolygon.h"
25 #include "qgswkbptr.h"
26 #include "qgsmulticurve.h"
27 
28 #include <QJsonArray>
29 #include <QJsonObject>
30 #include <QPainter>
31 #include <QPainterPath>
32 #include <memory>
33 #include <nlohmann/json.hpp>
34 
36 {
38 }
39 
41 {
42  clear();
43 }
44 
46 {
47  auto result = qgis::make_unique< QgsCurvePolygon >();
48  result->mWkbType = mWkbType;
49  return result.release();
50 }
51 
53 {
54  return QStringLiteral( "CurvePolygon" );
55 }
56 
58 {
59  return 2;
60 }
61 
63  : QgsSurface( p )
64 
65 {
66  mWkbType = p.mWkbType;
67  if ( p.mExteriorRing )
68  {
69  mExteriorRing.reset( p.mExteriorRing->clone() );
70  }
71 
72  for ( const QgsCurve *ring : p.mInteriorRings )
73  {
74  mInteriorRings.push_back( ring->clone() );
75  }
76 }
77 
79 {
80  if ( &p != this )
81  {
82  clearCache();
84  if ( p.mExteriorRing )
85  {
86  mExteriorRing.reset( p.mExteriorRing->clone() );
87  }
88 
89  for ( const QgsCurve *ring : p.mInteriorRings )
90  {
91  mInteriorRings.push_back( ring->clone() );
92  }
93  }
94  return *this;
95 }
96 
98 {
99  const QgsCurvePolygon *otherPolygon = qgsgeometry_cast< const QgsCurvePolygon * >( &other );
100  if ( !otherPolygon )
101  return false;
102 
103  //run cheap checks first
104  if ( mWkbType != otherPolygon->mWkbType )
105  return false;
106 
107  if ( ( !mExteriorRing && otherPolygon->mExteriorRing ) || ( mExteriorRing && !otherPolygon->mExteriorRing ) )
108  return false;
109 
110  if ( mInteriorRings.count() != otherPolygon->mInteriorRings.count() )
111  return false;
112 
113  // compare rings
114  if ( mExteriorRing && otherPolygon->mExteriorRing )
115  {
116  if ( *mExteriorRing != *otherPolygon->mExteriorRing )
117  return false;
118  }
119 
120  for ( int i = 0; i < mInteriorRings.count(); ++i )
121  {
122  if ( ( !mInteriorRings.at( i ) && otherPolygon->mInteriorRings.at( i ) ) ||
123  ( mInteriorRings.at( i ) && !otherPolygon->mInteriorRings.at( i ) ) )
124  return false;
125 
126  if ( mInteriorRings.at( i ) && otherPolygon->mInteriorRings.at( i ) &&
127  *mInteriorRings.at( i ) != *otherPolygon->mInteriorRings.at( i ) )
128  return false;
129  }
130 
131  return true;
132 }
133 
135 {
136  return !operator==( other );
137 }
138 
140 {
141  return new QgsCurvePolygon( *this );
142 }
143 
145 {
147  mExteriorRing.reset();
148  qDeleteAll( mInteriorRings );
149  mInteriorRings.clear();
150  clearCache();
151 }
152 
153 
155 {
156  clear();
157  if ( !wkbPtr )
158  {
159  return false;
160  }
161 
162  QgsWkbTypes::Type type = wkbPtr.readHeader();
164  {
165  return false;
166  }
167  mWkbType = type;
168 
169  int nRings;
170  wkbPtr >> nRings;
171  std::unique_ptr< QgsCurve > currentCurve;
172  for ( int i = 0; i < nRings; ++i )
173  {
174  QgsWkbTypes::Type curveType = wkbPtr.readHeader();
175  wkbPtr -= 1 + sizeof( int );
176  QgsWkbTypes::Type flatCurveType = QgsWkbTypes::flatType( curveType );
177  if ( flatCurveType == QgsWkbTypes::LineString )
178  {
179  currentCurve.reset( new QgsLineString() );
180  }
181  else if ( flatCurveType == QgsWkbTypes::CircularString )
182  {
183  currentCurve.reset( new QgsCircularString() );
184  }
185  else if ( flatCurveType == QgsWkbTypes::CompoundCurve )
186  {
187  currentCurve.reset( new QgsCompoundCurve() );
188  }
189  else
190  {
191  return false;
192  }
193  currentCurve->fromWkb( wkbPtr ); // also updates wkbPtr
194  if ( i == 0 )
195  {
196  mExteriorRing = std::move( currentCurve );
197  }
198  else
199  {
200  mInteriorRings.append( currentCurve.release() );
201  }
202  }
203 
204  return true;
205 }
206 
207 bool QgsCurvePolygon::fromWkt( const QString &wkt )
208 {
209  clear();
210 
211  QPair<QgsWkbTypes::Type, QString> parts = QgsGeometryUtils::wktReadBlock( wkt );
212 
214  return false;
215 
216  mWkbType = parts.first;
217 
218  if ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 )
219  return true;
220 
221  QString defaultChildWkbType = QStringLiteral( "LineString%1%2" ).arg( is3D() ? QStringLiteral( "Z" ) : QString(), isMeasure() ? QStringLiteral( "M" ) : QString() );
222 
223  const QStringList blocks = QgsGeometryUtils::wktGetChildBlocks( parts.second, defaultChildWkbType );
224  for ( const QString &childWkt : blocks )
225  {
226  QPair<QgsWkbTypes::Type, QString> childParts = QgsGeometryUtils::wktReadBlock( childWkt );
227 
228  QgsWkbTypes::Type flatCurveType = QgsWkbTypes::flatType( childParts.first );
229  if ( flatCurveType == QgsWkbTypes::LineString )
230  mInteriorRings.append( new QgsLineString() );
231  else if ( flatCurveType == QgsWkbTypes::CircularString )
232  mInteriorRings.append( new QgsCircularString() );
233  else if ( flatCurveType == QgsWkbTypes::CompoundCurve )
234  mInteriorRings.append( new QgsCompoundCurve() );
235  else
236  {
237  clear();
238  return false;
239  }
240  if ( !mInteriorRings.back()->fromWkt( childWkt ) )
241  {
242  clear();
243  return false;
244  }
245  }
246 
247  if ( mInteriorRings.isEmpty() )
248  {
249  clear();
250  return false;
251  }
252 
253  mExteriorRing.reset( mInteriorRings.takeFirst() );
254 
255  //scan through rings and check if dimensionality of rings is different to CurvePolygon.
256  //if so, update the type dimensionality of the CurvePolygon to match
257  bool hasZ = false;
258  bool hasM = false;
259  if ( mExteriorRing )
260  {
261  hasZ = hasZ || mExteriorRing->is3D();
262  hasM = hasM || mExteriorRing->isMeasure();
263  }
264  for ( const QgsCurve *curve : qgis::as_const( mInteriorRings ) )
265  {
266  hasZ = hasZ || curve->is3D();
267  hasM = hasM || curve->isMeasure();
268  if ( hasZ && hasM )
269  break;
270  }
271  if ( hasZ )
272  addZValue( 0 );
273  if ( hasM )
274  addMValue( 0 );
275 
276  return true;
277 }
278 
280 {
281  if ( mExteriorRing )
282  {
283  return mExteriorRing->boundingBox();
284  }
285  return QgsRectangle();
286 }
287 
288 QByteArray QgsCurvePolygon::asWkb( WkbFlags flags ) const
289 {
290  int binarySize = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 );
291  QVector<QByteArray> wkbForRings;
292  wkbForRings.reserve( 1 + mInteriorRings.size() );
293  if ( mExteriorRing )
294  {
295  QByteArray wkb( mExteriorRing->asWkb( flags ) );
296  binarySize += wkb.length();
297  wkbForRings << wkb;
298  }
299  for ( const QgsCurve *curve : mInteriorRings )
300  {
301  QByteArray wkb( curve->asWkb( flags ) );
302  binarySize += wkb.length();
303  wkbForRings << wkb;
304  }
305 
306  QByteArray wkbArray;
307  wkbArray.resize( binarySize );
308  QgsWkbPtr wkbPtr( wkbArray );
309  wkbPtr << static_cast<char>( QgsApplication::endian() );
310  wkbPtr << static_cast<quint32>( wkbType() );
311  wkbPtr << static_cast<quint32>( wkbForRings.count() );
312  for ( const QByteArray &wkb : qgis::as_const( wkbForRings ) )
313  {
314  wkbPtr << wkb;
315  }
316  return wkbArray;
317 }
318 
319 QString QgsCurvePolygon::asWkt( int precision ) const
320 {
321  QString wkt = wktTypeStr();
322 
323  if ( isEmpty() )
324  wkt += QStringLiteral( " EMPTY" );
325  else
326  {
327  wkt += QLatin1String( " (" );
328  if ( mExteriorRing )
329  {
330  QString childWkt = mExteriorRing->asWkt( precision );
331  if ( qgsgeometry_cast<QgsLineString *>( mExteriorRing.get() ) )
332  {
333  // Type names of linear geometries are omitted
334  childWkt = childWkt.mid( childWkt.indexOf( '(' ) );
335  }
336  wkt += childWkt + ',';
337  }
338  for ( const QgsCurve *curve : mInteriorRings )
339  {
340  QString childWkt = curve->asWkt( precision );
341  if ( qgsgeometry_cast<const QgsLineString *>( curve ) )
342  {
343  // Type names of linear geometries are omitted
344  childWkt = childWkt.mid( childWkt.indexOf( '(' ) );
345  }
346  wkt += childWkt + ',';
347  }
348  if ( wkt.endsWith( ',' ) )
349  {
350  wkt.chop( 1 ); // Remove last ','
351  }
352  wkt += ')';
353  }
354  return wkt;
355 }
356 
357 QDomElement QgsCurvePolygon::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
358 {
359  // GML2 does not support curves
360  QDomElement elemPolygon = doc.createElementNS( ns, QStringLiteral( "Polygon" ) );
361 
362  if ( isEmpty() )
363  return elemPolygon;
364 
365  QDomElement elemOuterBoundaryIs = doc.createElementNS( ns, QStringLiteral( "outerBoundaryIs" ) );
366  std::unique_ptr< QgsLineString > exteriorLineString( exteriorRing()->curveToLine() );
367  QDomElement outerRing = exteriorLineString->asGml2( doc, precision, ns, axisOrder );
368  outerRing.toElement().setTagName( QStringLiteral( "LinearRing" ) );
369  elemOuterBoundaryIs.appendChild( outerRing );
370  elemPolygon.appendChild( elemOuterBoundaryIs );
371  std::unique_ptr< QgsLineString > interiorLineString;
372  for ( int i = 0, n = numInteriorRings(); i < n; ++i )
373  {
374  QDomElement elemInnerBoundaryIs = doc.createElementNS( ns, QStringLiteral( "innerBoundaryIs" ) );
375  interiorLineString.reset( interiorRing( i )->curveToLine() );
376  QDomElement innerRing = interiorLineString->asGml2( doc, precision, ns, axisOrder );
377  innerRing.toElement().setTagName( QStringLiteral( "LinearRing" ) );
378  elemInnerBoundaryIs.appendChild( innerRing );
379  elemPolygon.appendChild( elemInnerBoundaryIs );
380  }
381  return elemPolygon;
382 }
383 
384 QDomElement QgsCurvePolygon::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
385 {
386  QDomElement elemCurvePolygon = doc.createElementNS( ns, QStringLiteral( "Polygon" ) );
387 
388  if ( isEmpty() )
389  return elemCurvePolygon;
390 
391  QDomElement elemExterior = doc.createElementNS( ns, QStringLiteral( "exterior" ) );
392  QDomElement curveElem = exteriorRing()->asGml3( doc, precision, ns, axisOrder );
393  if ( curveElem.tagName() == QLatin1String( "LineString" ) )
394  {
395  curveElem.setTagName( QStringLiteral( "LinearRing" ) );
396  }
397  elemExterior.appendChild( curveElem );
398  elemCurvePolygon.appendChild( elemExterior );
399 
400  for ( int i = 0, n = numInteriorRings(); i < n; ++i )
401  {
402  QDomElement elemInterior = doc.createElementNS( ns, QStringLiteral( "interior" ) );
403  QDomElement innerRing = interiorRing( i )->asGml3( doc, precision, ns, axisOrder );
404  if ( innerRing.tagName() == QLatin1String( "LineString" ) )
405  {
406  innerRing.setTagName( QStringLiteral( "LinearRing" ) );
407  }
408  elemInterior.appendChild( innerRing );
409  elemCurvePolygon.appendChild( elemInterior );
410  }
411  return elemCurvePolygon;
412 }
413 
415 {
416  json coordinates( json::array( ) );
417  if ( exteriorRing() )
418  {
419  std::unique_ptr< QgsLineString > exteriorLineString( exteriorRing()->curveToLine() );
420  QgsPointSequence exteriorPts;
421  exteriorLineString->points( exteriorPts );
422  coordinates.push_back( QgsGeometryUtils::pointsToJson( exteriorPts, precision ) );
423 
424  std::unique_ptr< QgsLineString > interiorLineString;
425  for ( int i = 0, n = numInteriorRings(); i < n; ++i )
426  {
427  interiorLineString.reset( interiorRing( i )->curveToLine() );
428  QgsPointSequence interiorPts;
429  interiorLineString->points( interiorPts );
430  coordinates.push_back( QgsGeometryUtils::pointsToJson( interiorPts, precision ) );
431  }
432  }
433  return
434  {
435  { "type", "Polygon" },
436  { "coordinates", coordinates }
437  };
438 }
439 
440 QString QgsCurvePolygon::asKml( int precision ) const
441 {
442  QString kml;
443  kml.append( QLatin1String( "<Polygon>" ) );
444  if ( mExteriorRing )
445  {
446  kml.append( QLatin1String( "<outerBoundaryIs>" ) );
447  kml.append( mExteriorRing->asKml( precision ) );
448  kml.append( QLatin1String( "</outerBoundaryIs>" ) );
449  }
450  const QVector<QgsCurve *> &interiorRings = mInteriorRings;
451  for ( const QgsCurve *ring : interiorRings )
452  {
453  kml.append( QLatin1String( "<innerBoundaryIs>" ) );
454  kml.append( ring->asKml( precision ) );
455  kml.append( QLatin1String( "</innerBoundaryIs>" ) );
456  }
457  kml.append( QLatin1String( "</Polygon>" ) );
458  return kml;
459 }
460 
461 double QgsCurvePolygon::area() const
462 {
463  if ( !mExteriorRing )
464  {
465  return 0.0;
466  }
467 
468  double totalArea = 0.0;
469 
470  if ( mExteriorRing->isRing() )
471  {
472  double area = 0.0;
473  mExteriorRing->sumUpArea( area );
474  totalArea += std::fabs( area );
475  }
476 
477  for ( const QgsCurve *ring : mInteriorRings )
478  {
479  double area = 0.0;
480  if ( ring->isRing() )
481  {
482  ring->sumUpArea( area );
483  totalArea -= std::fabs( area );
484  }
485  }
486  return totalArea;
487 }
488 
490 {
491  if ( !mExteriorRing )
492  return 0.0;
493 
494  //sum perimeter of rings
495  double perimeter = mExteriorRing->length();
496  for ( const QgsCurve *ring : mInteriorRings )
497  {
498  perimeter += ring->length();
499  }
500  return perimeter;
501 }
502 
504 {
505  std::unique_ptr< QgsPolygon > polygon( new QgsPolygon() );
506  if ( !mExteriorRing )
507  return polygon.release();
508 
509  polygon->setExteriorRing( exteriorRing()->curveToLine() );
510  QVector<QgsCurve *> interiors;
511  int n = numInteriorRings();
512  interiors.reserve( n );
513  for ( int i = 0; i < n; ++i )
514  {
515  interiors.append( interiorRing( i )->curveToLine() );
516  }
517  polygon->setInteriorRings( interiors );
518  return polygon.release();
519 }
520 
522 {
523  if ( !mExteriorRing )
524  return nullptr;
525 
526  if ( mInteriorRings.isEmpty() )
527  {
528  return mExteriorRing->clone();
529  }
530  else
531  {
532  QgsMultiCurve *multiCurve = new QgsMultiCurve();
533  int nInteriorRings = mInteriorRings.size();
534  multiCurve->reserve( nInteriorRings + 1 );
535  multiCurve->addGeometry( mExteriorRing->clone() );
536  for ( int i = 0; i < nInteriorRings; ++i )
537  {
538  multiCurve->addGeometry( mInteriorRings.at( i )->clone() );
539  }
540  return multiCurve;
541  }
542 }
543 
544 QgsCurvePolygon *QgsCurvePolygon::snappedToGrid( double hSpacing, double vSpacing, double dSpacing, double mSpacing ) const
545 {
546  if ( !mExteriorRing )
547  return nullptr;
548 
549 
550  std::unique_ptr< QgsCurvePolygon > polygon( createEmptyWithSameType() );
551 
552  // exterior ring
553  auto exterior = std::unique_ptr<QgsCurve> { static_cast< QgsCurve *>( mExteriorRing->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) ) };
554 
555  if ( !exterior )
556  return nullptr;
557 
558  polygon->mExteriorRing = std::move( exterior );
559 
560  //interior rings
561  for ( auto interior : mInteriorRings )
562  {
563  if ( !interior )
564  continue;
565 
566  QgsCurve *gridifiedInterior = static_cast< QgsCurve * >( interior->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) );
567 
568  if ( !gridifiedInterior )
569  continue;
570 
571  polygon->mInteriorRings.append( gridifiedInterior );
572  }
573 
574  return polygon.release();
575 
576 }
577 
578 bool QgsCurvePolygon::removeDuplicateNodes( double epsilon, bool useZValues )
579 {
580  bool result = false;
581  auto cleanRing = [epsilon, useZValues ]( QgsCurve * ring )->bool
582  {
583  if ( ring->numPoints() <= 4 )
584  return false;
585 
586  if ( ring->removeDuplicateNodes( epsilon, useZValues ) )
587  {
588  QgsPoint startPoint;
590  ring->pointAt( 0, startPoint, type );
591  // ensure ring is properly closed - if we removed the final node, it may no longer be properly closed
592  ring->moveVertex( QgsVertexId( -1, -1, ring->numPoints() - 1 ), startPoint );
593  return true;
594  }
595 
596  return false;
597  };
598  if ( mExteriorRing )
599  {
600  result = cleanRing( mExteriorRing.get() );
601  }
602  for ( QgsCurve *ring : qgis::as_const( mInteriorRings ) )
603  {
604  if ( cleanRing( ring ) ) result = true;
605  }
606  return result;
607 }
608 
609 QgsPolygon *QgsCurvePolygon::toPolygon( double tolerance, SegmentationToleranceType toleranceType ) const
610 {
611  std::unique_ptr< QgsPolygon > poly( new QgsPolygon() );
612  if ( !mExteriorRing )
613  {
614  return poly.release();
615  }
616 
617  poly->setExteriorRing( mExteriorRing->curveToLine( tolerance, toleranceType ) );
618 
619  QVector<QgsCurve *> rings;
620  rings.reserve( mInteriorRings.size() );
621  for ( const QgsCurve *ring : mInteriorRings )
622  {
623  rings.push_back( ring->curveToLine( tolerance, toleranceType ) );
624  }
625  poly->setInteriorRings( rings );
626  return poly.release();
627 }
628 
630 {
631  if ( !ring )
632  {
633  return;
634  }
635  mExteriorRing.reset( ring );
636 
637  //set proper wkb type
639  {
641  }
643  {
645  }
646 
647  //match dimensionality for rings
648  for ( QgsCurve *ring : qgis::as_const( mInteriorRings ) )
649  {
650  if ( is3D() )
651  ring->addZValue();
652  else
653  ring->dropZValue();
654 
655  if ( isMeasure() )
656  ring->addMValue();
657  else
658  ring->dropMValue();
659  }
660  clearCache();
661 }
662 
663 void QgsCurvePolygon::setInteriorRings( const QVector<QgsCurve *> &rings )
664 {
665  qDeleteAll( mInteriorRings );
666  mInteriorRings.clear();
667 
668  //add rings one-by-one, so that they can each be converted to the correct type for the CurvePolygon
669  for ( QgsCurve *ring : rings )
670  {
671  addInteriorRing( ring );
672  }
673  clearCache();
674 }
675 
677 {
678  if ( !ring )
679  return;
680 
681  //ensure dimensionality of ring matches curve polygon
682  if ( !is3D() )
683  ring->dropZValue();
684  else if ( !ring->is3D() )
685  ring->addZValue();
686 
687  if ( !isMeasure() )
688  ring->dropMValue();
689  else if ( !ring->isMeasure() )
690  ring->addMValue();
691 
692  mInteriorRings.append( ring );
693  clearCache();
694 }
695 
697 {
698  if ( nr < 0 || nr >= mInteriorRings.size() )
699  {
700  return false;
701  }
702  delete mInteriorRings.takeAt( nr );
703  clearCache();
704  return true;
705 }
706 
707 void QgsCurvePolygon::removeInteriorRings( double minimumAllowedArea )
708 {
709  for ( int ringIndex = mInteriorRings.size() - 1; ringIndex >= 0; --ringIndex )
710  {
711  if ( minimumAllowedArea < 0 )
712  delete mInteriorRings.takeAt( ringIndex );
713  else
714  {
715  double area = 0.0;
716  mInteriorRings.at( ringIndex )->sumUpArea( area );
717  if ( area < minimumAllowedArea )
718  delete mInteriorRings.takeAt( ringIndex );
719  }
720  }
721 
722  clearCache();
723 }
724 
726 {
727  QVector<QgsCurve *> validRings;
728  validRings.reserve( mInteriorRings.size() );
729  for ( QgsCurve *curve : qgis::as_const( mInteriorRings ) )
730  {
731  if ( !curve->isRing() )
732  {
733  // remove invalid rings
734  delete curve;
735  }
736  else
737  {
738  validRings << curve;
739  }
740  }
741  mInteriorRings = validRings;
742 }
743 
745 {
746  if ( mExteriorRing && mExteriorRing->orientation() != QgsCurve::Clockwise )
747  {
748  // flip exterior ring orientation
749  std::unique_ptr< QgsCurve > flipped( mExteriorRing->reversed() );
750  mExteriorRing = std::move( flipped );
751  }
752 
753  QVector<QgsCurve *> validRings;
754  for ( QgsCurve *curve : qgis::as_const( mInteriorRings ) )
755  {
756  if ( curve && curve->orientation() != QgsCurve::CounterClockwise )
757  {
758  // flip interior ring orientation
759  QgsCurve *flipped = curve->reversed();
760  validRings << flipped;
761  delete curve;
762  }
763  else
764  {
765  validRings << curve;
766  }
767  }
768  mInteriorRings = validRings;
769 }
770 
771 void QgsCurvePolygon::draw( QPainter &p ) const
772 {
773  if ( !mExteriorRing )
774  return;
775 
776  if ( mInteriorRings.empty() )
777  {
778  mExteriorRing->drawAsPolygon( p );
779  }
780  else
781  {
782  QPainterPath path;
783  mExteriorRing->addToPainterPath( path );
784 
785  for ( const QgsCurve *ring : mInteriorRings )
786  {
787  ring->addToPainterPath( path );
788  }
789  p.drawPath( path );
790  }
791 }
792 
794 {
795  if ( mExteriorRing )
796  {
797  mExteriorRing->transform( ct, d, transformZ );
798  }
799 
800  for ( QgsCurve *curve : qgis::as_const( mInteriorRings ) )
801  {
802  curve->transform( ct, d, transformZ );
803  }
804  clearCache();
805 }
806 
807 void QgsCurvePolygon::transform( const QTransform &t, double zTranslate, double zScale, double mTranslate, double mScale )
808 {
809  if ( mExteriorRing )
810  {
811  mExteriorRing->transform( t, zTranslate, zScale, mTranslate, mScale );
812  }
813 
814  for ( QgsCurve *curve : qgis::as_const( mInteriorRings ) )
815  {
816  curve->transform( t, zTranslate, zScale, mTranslate, mScale );
817  }
818  clearCache();
819 }
820 
822 {
823  QgsCoordinateSequence sequence;
824  sequence.append( QgsRingSequence() );
825 
826  if ( mExteriorRing )
827  {
828  sequence.back().append( QgsPointSequence() );
829  mExteriorRing->points( sequence.back().back() );
830  }
831 
832  for ( const QgsCurve *ring : mInteriorRings )
833  {
834  sequence.back().append( QgsPointSequence() );
835  ring->points( sequence.back().back() );
836  }
837 
838  return sequence;
839 }
840 
842 {
843  int count = 0;
844 
845  if ( mExteriorRing )
846  {
847  count += mExteriorRing->nCoordinates();
848  }
849 
850  for ( const QgsCurve *ring : mInteriorRings )
851  {
852  count += ring->nCoordinates();
853  }
854 
855  return count;
856 }
857 
859 {
860  if ( id.part != 0 )
861  return -1;
862 
863  if ( id.ring < 0 || id.ring >= ringCount() )
864  return -1;
865 
866  int number = 0;
867  if ( id.ring == 0 && mExteriorRing )
868  {
869  return mExteriorRing->vertexNumberFromVertexId( QgsVertexId( 0, 0, id.vertex ) );
870  }
871  else
872  {
873  number += mExteriorRing->numPoints();
874  }
875 
876  for ( int i = 0; i < mInteriorRings.count(); ++i )
877  {
878  if ( id.ring == i + 1 )
879  {
880  int partNumber = mInteriorRings.at( i )->vertexNumberFromVertexId( QgsVertexId( 0, 0, id.vertex ) );
881  if ( partNumber == -1 )
882  return -1;
883  return number + partNumber;
884  }
885  else
886  {
887  number += mInteriorRings.at( i )->numPoints();
888  }
889  }
890  return -1; // should not happen
891 }
892 
894 {
895  if ( !mExteriorRing )
896  return true;
897 
898  return mExteriorRing->isEmpty();
899 }
900 
901 double QgsCurvePolygon::closestSegment( const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon ) const
902 {
903  if ( !mExteriorRing )
904  {
905  return -1;
906  }
907  QVector<QgsCurve *> segmentList;
908  segmentList.append( mExteriorRing.get() );
909  segmentList.append( mInteriorRings );
910  return QgsGeometryUtils::closestSegmentFromComponents( segmentList, QgsGeometryUtils::Ring, pt, segmentPt, vertexAfter, leftOf, epsilon );
911 }
912 
914 {
915  if ( !mExteriorRing || vId.ring >= 1 + mInteriorRings.size() )
916  {
917  return false;
918  }
919 
920  if ( vId.ring < 0 )
921  {
922  vId.ring = 0;
923  vId.vertex = -1;
924  if ( vId.part < 0 )
925  {
926  vId.part = 0;
927  }
928  return mExteriorRing->nextVertex( vId, vertex );
929  }
930  else
931  {
932  QgsCurve *ring = vId.ring == 0 ? mExteriorRing.get() : mInteriorRings[vId.ring - 1];
933 
934  if ( ring->nextVertex( vId, vertex ) )
935  {
936  return true;
937  }
938  ++vId.ring;
939  vId.vertex = -1;
940  if ( vId.ring >= 1 + mInteriorRings.size() )
941  {
942  return false;
943  }
944  ring = mInteriorRings[ vId.ring - 1 ];
945  return ring->nextVertex( vId, vertex );
946  }
947 }
948 
949 void ringAdjacentVertices( const QgsCurve *curve, QgsVertexId vertex, QgsVertexId &previousVertex, QgsVertexId &nextVertex )
950 {
951  int n = curve->numPoints();
952  if ( vertex.vertex < 0 || vertex.vertex >= n )
953  {
954  previousVertex = QgsVertexId();
955  nextVertex = QgsVertexId();
956  return;
957  }
958 
959  if ( vertex.vertex == 0 && n < 3 )
960  {
961  previousVertex = QgsVertexId();
962  }
963  else if ( vertex.vertex == 0 )
964  {
965  previousVertex = QgsVertexId( vertex.part, vertex.ring, n - 2 );
966  }
967  else
968  {
969  previousVertex = QgsVertexId( vertex.part, vertex.ring, vertex.vertex - 1 );
970  }
971  if ( vertex.vertex == n - 1 && n < 3 )
972  {
973  nextVertex = QgsVertexId();
974  }
975  else if ( vertex.vertex == n - 1 )
976  {
977  nextVertex = QgsVertexId( vertex.part, vertex.ring, 1 );
978  }
979  else
980  {
981  nextVertex = QgsVertexId( vertex.part, vertex.ring, vertex.vertex + 1 );
982  }
983 }
984 
985 void QgsCurvePolygon::adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex, QgsVertexId &nextVertex ) const
986 {
987  if ( !mExteriorRing || vertex.ring < 0 || vertex.ring >= 1 + mInteriorRings.size() )
988  {
989  previousVertex = QgsVertexId();
991  return;
992  }
993 
994  if ( vertex.ring == 0 )
995  {
996  ringAdjacentVertices( mExteriorRing.get(), vertex, previousVertex, nextVertex );
997  }
998  else
999  {
1000  ringAdjacentVertices( mInteriorRings.at( vertex.ring - 1 ), vertex, previousVertex, nextVertex );
1001  }
1002 }
1003 
1005 {
1006  if ( !mExteriorRing || vId.ring < 0 || vId.ring >= 1 + mInteriorRings.size() )
1007  {
1008  return false;
1009  }
1010 
1011  QgsCurve *ring = vId.ring == 0 ? mExteriorRing.get() : mInteriorRings.at( vId.ring - 1 );
1012  int n = ring->numPoints();
1013  bool success = ring->insertVertex( QgsVertexId( 0, 0, vId.vertex ), vertex );
1014  if ( !success )
1015  {
1016  return false;
1017  }
1018 
1019  // If first or last vertex is inserted, re-sync the last/first vertex
1020  if ( vId.vertex == 0 )
1021  ring->moveVertex( QgsVertexId( 0, 0, n ), vertex );
1022  else if ( vId.vertex == n )
1023  ring->moveVertex( QgsVertexId( 0, 0, 0 ), vertex );
1024 
1025  clearCache();
1026 
1027  return true;
1028 }
1029 
1031 {
1032  if ( !mExteriorRing || vId.ring < 0 || vId.ring >= 1 + mInteriorRings.size() )
1033  {
1034  return false;
1035  }
1036 
1037  QgsCurve *ring = vId.ring == 0 ? mExteriorRing.get() : mInteriorRings.at( vId.ring - 1 );
1038  int n = ring->numPoints();
1039  bool success = ring->moveVertex( vId, newPos );
1040  if ( success )
1041  {
1042  // If first or last vertex is moved, also move the last/first vertex
1043  if ( vId.vertex == 0 )
1044  ring->moveVertex( QgsVertexId( vId.part, vId.ring, n - 1 ), newPos );
1045  else if ( vId.vertex == n - 1 )
1046  ring->moveVertex( QgsVertexId( vId.part, vId.ring, 0 ), newPos );
1047  clearCache();
1048  }
1049  return success;
1050 }
1051 
1053 {
1054  if ( !mExteriorRing || vId.ring < 0 || vId.ring >= 1 + mInteriorRings.size() )
1055  {
1056  return false;
1057  }
1058 
1059  QgsCurve *ring = vId.ring == 0 ? mExteriorRing.get() : mInteriorRings.at( vId.ring - 1 );
1060  int n = ring->numPoints();
1061  if ( n <= 4 )
1062  {
1063  //no points will be left in ring, so remove whole ring
1064  if ( vId.ring == 0 )
1065  {
1066  mExteriorRing.reset();
1067  if ( !mInteriorRings.isEmpty() )
1068  {
1069  mExteriorRing.reset( mInteriorRings.takeFirst() );
1070  }
1071  }
1072  else
1073  {
1074  removeInteriorRing( vId.ring - 1 );
1075  }
1076  clearCache();
1077  return true;
1078  }
1079 
1080  bool success = ring->deleteVertex( vId );
1081  if ( success )
1082  {
1083  // If first or last vertex is removed, re-sync the last/first vertex
1084  // Do not use "n - 2", but "ring->numPoints() - 1" as more than one vertex
1085  // may have been deleted (e.g. with CircularString)
1086  if ( vId.vertex == 0 )
1087  ring->moveVertex( QgsVertexId( 0, 0, ring->numPoints() - 1 ), ring->vertexAt( QgsVertexId( 0, 0, 0 ) ) );
1088  else if ( vId.vertex == n - 1 )
1089  ring->moveVertex( QgsVertexId( 0, 0, 0 ), ring->vertexAt( QgsVertexId( 0, 0, ring->numPoints() - 1 ) ) );
1090  clearCache();
1091  }
1092  return success;
1093 }
1094 
1096 {
1097  if ( mExteriorRing && mExteriorRing->hasCurvedSegments() )
1098  {
1099  return true;
1100  }
1101 
1102  for ( const QgsCurve *ring : mInteriorRings )
1103  {
1104  if ( ring->hasCurvedSegments() )
1105  {
1106  return true;
1107  }
1108  }
1109  return false;
1110 }
1111 
1113 {
1114  return toPolygon( tolerance, toleranceType );
1115 }
1116 
1118 {
1119  if ( !mExteriorRing || vertex.ring < 0 || vertex.ring >= 1 + mInteriorRings.size() )
1120  {
1121  //makes no sense - conversion of false to double!
1122  return false;
1123  }
1124 
1125  QgsCurve *ring = vertex.ring == 0 ? mExteriorRing.get() : mInteriorRings[vertex.ring - 1];
1126  return ring->vertexAngle( vertex );
1127 }
1128 
1129 int QgsCurvePolygon::vertexCount( int /*part*/, int ring ) const
1130 {
1131  return ring == 0 ? mExteriorRing->vertexCount() : mInteriorRings[ring - 1]->vertexCount();
1132 }
1133 
1135 {
1136  return ( nullptr != mExteriorRing ) + mInteriorRings.size();
1137 }
1138 
1140 {
1141  return ringCount() > 0 ? 1 : 0;
1142 }
1143 
1145 {
1146  return id.ring == 0 ? mExteriorRing->vertexAt( id ) : mInteriorRings[id.ring - 1]->vertexAt( id );
1147 }
1148 
1149 double QgsCurvePolygon::segmentLength( QgsVertexId startVertex ) const
1150 {
1151  if ( !mExteriorRing || startVertex.ring < 0 || startVertex.ring >= 1 + mInteriorRings.size() )
1152  {
1153  return 0.0;
1154  }
1155 
1156  const QgsCurve *ring = startVertex.ring == 0 ? mExteriorRing.get() : mInteriorRings[startVertex.ring - 1];
1157  return ring->segmentLength( startVertex );
1158 }
1159 
1160 bool QgsCurvePolygon::addZValue( double zValue )
1161 {
1162  if ( QgsWkbTypes::hasZ( mWkbType ) )
1163  return false;
1164 
1166 
1167  if ( mExteriorRing )
1168  mExteriorRing->addZValue( zValue );
1169  for ( QgsCurve *curve : qgis::as_const( mInteriorRings ) )
1170  {
1171  curve->addZValue( zValue );
1172  }
1173  clearCache();
1174  return true;
1175 }
1176 
1177 bool QgsCurvePolygon::addMValue( double mValue )
1178 {
1179  if ( QgsWkbTypes::hasM( mWkbType ) )
1180  return false;
1181 
1183 
1184  if ( mExteriorRing )
1185  mExteriorRing->addMValue( mValue );
1186  for ( QgsCurve *curve : qgis::as_const( mInteriorRings ) )
1187  {
1188  curve->addMValue( mValue );
1189  }
1190  clearCache();
1191  return true;
1192 }
1193 
1195 {
1196  if ( !is3D() )
1197  return false;
1198 
1200  if ( mExteriorRing )
1201  mExteriorRing->dropZValue();
1202  for ( QgsCurve *curve : qgis::as_const( mInteriorRings ) )
1203  {
1204  curve->dropZValue();
1205  }
1206  clearCache();
1207  return true;
1208 }
1209 
1211 {
1212  if ( !isMeasure() )
1213  return false;
1214 
1216  if ( mExteriorRing )
1217  mExteriorRing->dropMValue();
1218  for ( QgsCurve *curve : qgis::as_const( mInteriorRings ) )
1219  {
1220  curve->dropMValue();
1221  }
1222  clearCache();
1223  return true;
1224 }
1225 
1227 {
1228  if ( mExteriorRing )
1229  mExteriorRing->swapXy();
1230  for ( QgsCurve *curve : qgis::as_const( mInteriorRings ) )
1231  {
1232  curve->swapXy();
1233  }
1234  clearCache();
1235 }
1236 
1238 {
1239  return clone();
1240 }
1241 
1242 void QgsCurvePolygon::filterVertices( const std::function<bool ( const QgsPoint & )> &filter )
1243 {
1244  if ( mExteriorRing )
1245  mExteriorRing->filterVertices( filter );
1246 
1247  for ( QgsCurve *curve : qgis::as_const( mInteriorRings ) )
1248  {
1249  curve->filterVertices( filter );
1250  }
1251  clearCache();
1252 }
1253 
1254 void QgsCurvePolygon::transformVertices( const std::function<QgsPoint( const QgsPoint & )> &transform )
1255 {
1256  if ( mExteriorRing )
1257  mExteriorRing->transformVertices( transform );
1258 
1259  for ( QgsCurve *curve : qgis::as_const( mInteriorRings ) )
1260  {
1261  curve->transformVertices( transform );
1262  }
1263  clearCache();
1264 }
1265 
1267 {
1268  return 1 + mInteriorRings.count();
1269 }
1270 
1272 {
1273  if ( index == 0 )
1274  return mExteriorRing.get();
1275  else
1276  return mInteriorRings.at( index - 1 );
1277 }
QgsCurve
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
qgspolygon.h
QgsCurve::nextVertex
bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const override
Returns next vertex id and coordinates.
Definition: qgscurve.cpp:71
QgsVertexId::part
int part
Definition: qgsabstractgeometry.h:1080
QgsCurvePolygon::hasCurvedSegments
bool hasCurvedSegments() const override
Returns true if the geometry contains curved segments.
Definition: qgscurvepolygon.cpp:1095
QgsCoordinateSequence
QVector< QgsRingSequence > QgsCoordinateSequence
Definition: qgsabstractgeometry.h:49
QgsCurvePolygon::addMValue
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
Definition: qgscurvepolygon.cpp:1177
QgsAbstractGeometry::dropMValue
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
QgsSurface::clearCache
void clearCache() const override
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
Definition: qgssurface.cpp:43
QgsVertexId::vertex
int vertex
Definition: qgsabstractgeometry.h:1082
QgsMultiCurve::addGeometry
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
Definition: qgsmulticurve.cpp:134
QgsCurvePolygon::toPolygon
virtual QgsPolygon * toPolygon(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a new polygon geometry corresponding to a segmentized approximation of the curve.
Definition: qgscurvepolygon.cpp:609
QgsAbstractGeometry::wkbType
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
Definition: qgsabstractgeometry.h:189
QgsAbstractGeometry::dropZValue
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
QgsGeometryUtils::pointsToJson
static json pointsToJson(const QgsPointSequence &points, int precision)
Returns coordinates as json object.
Definition: qgsgeometryutils.cpp:1268
QgsCurvePolygon::nCoordinates
int nCoordinates() const override
Returns the number of nodes contained in the geometry.
Definition: qgscurvepolygon.cpp:841
QgsPolygon
Polygon geometry type.
Definition: qgspolygon.h:33
qgslinestring.h
QgsAbstractGeometry::addZValue
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
QgsCurvePolygon::transformVertices
void transformVertices(const std::function< QgsPoint(const QgsPoint &) > &transform) override
Transforms the vertices from the geometry in place, applying the transform function to every vertex.
Definition: qgscurvepolygon.cpp:1254
QgsCurvePolygon::draw
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
Definition: qgscurvepolygon.cpp:771
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
QgsAbstractGeometry::moveVertex
virtual bool moveVertex(QgsVertexId position, const QgsPoint &newPos)=0
Moves a vertex within the geometry.
qgswkbptr.h
QgsGeometryCollection::reserve
void reserve(int size)
Attempts to allocate memory for at least size geometries.
Definition: qgsgeometrycollection.cpp:202
QgsCurve::reversed
virtual QgsCurve * reversed() const =0
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
QgsCurvePolygon::clear
void clear() override
Clears the geometry, ie reset it to a null geometry.
Definition: qgscurvepolygon.cpp:144
QgsCurvePolygon::setExteriorRing
virtual void setExteriorRing(QgsCurve *ring)
Sets the exterior ring of the polygon.
Definition: qgscurvepolygon.cpp:629
qgscompoundcurve.h
QgsAbstractGeometry::addMValue
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
QgsCurvePolygon::asGml2
QDomElement asGml2(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML2 representation of the geometry.
Definition: qgscurvepolygon.cpp:357
QgsCurvePolygon
Curve polygon geometry type.
Definition: qgscurvepolygon.h:34
QgsAbstractGeometry::parts
QgsGeometryConstPartIterator parts() const
Returns Java-style iterator for traversal of parts of the geometry.
Definition: qgsabstractgeometry.cpp:266
QgsCoordinateTransform::TransformDirection
TransformDirection
Enum used to indicate the direction (forward or inverse) of the transform.
Definition: qgscoordinatetransform.h:58
QgsCurvePolygon::clone
QgsCurvePolygon * clone() const override
Clones the geometry by performing a deep copy.
Definition: qgscurvepolygon.cpp:139
QgsWkbTypes::LineString
@ LineString
Definition: qgswkbtypes.h:72
QgsCurvePolygon::QgsCurvePolygon
QgsCurvePolygon()
Definition: qgscurvepolygon.cpp:35
QgsCurvePolygon::exteriorRing
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
Definition: qgscurvepolygon.h:86
QgsAbstractGeometry::wktTypeStr
QString wktTypeStr() const
Returns the WKT type string of the geometry.
Definition: qgsabstractgeometry.cpp:147
QgsSurface
Definition: qgssurface.h:32
QgsCurvePolygon::swapXy
void swapXy() override
Swaps the x and y coordinates from the geometry.
Definition: qgscurvepolygon.cpp:1226
QgsCurvePolygon::deleteVertex
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
Definition: qgscurvepolygon.cpp:1052
QgsCurvePolygon::setInteriorRings
void setInteriorRings(const QVector< QgsCurve * > &rings)
Sets all interior rings (takes ownership)
Definition: qgscurvepolygon.cpp:663
QgsWkbTypes::Type
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
QgsWkbTypes::hasZ
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:1042
QgsAbstractGeometry::SegmentationToleranceType
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle.
Definition: qgsabstractgeometry.h:112
QgsAbstractGeometry::mWkbType
QgsWkbTypes::Type mWkbType
Definition: qgsabstractgeometry.h:1005
QgsWkbTypes::dropM
static Type dropM(Type type)
Drops the m dimension (if present) for a WKB type and returns the new type.
Definition: qgswkbtypes.h:1212
QgsLineString
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:43
QgsWkbTypes::addM
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1163
QgsRectangle
Definition: qgsrectangle.h:41
QgsWkbTypes::PolygonGeometry
@ PolygonGeometry
Definition: qgswkbtypes.h:143
QgsCurvePolygon::interiorRing
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Definition: qgscurvepolygon.h:99
QgsCurvePolygon::dropZValue
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
Definition: qgscurvepolygon.cpp:1194
QgsCurvePolygon::calculateBoundingBox
QgsRectangle calculateBoundingBox() const override
Default calculator for the minimal bounding box for the geometry.
Definition: qgscurvepolygon.cpp:279
QgsCurvePolygon::asKml
QString asKml(int precision=17) const override
Returns a KML representation of the geometry.
Definition: qgscurvepolygon.cpp:440
QgsCurvePolygon::adjacentVertices
void adjacentVertices(QgsVertexId vertex, QgsVertexId &previousVertex, QgsVertexId &nextVertex) const override
Returns the vertices adjacent to a specified vertex within a geometry.
Definition: qgscurvepolygon.cpp:985
qgsapplication.h
QgsCurvePolygon::removeDuplicateNodes
bool removeDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false) override
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
Definition: qgscurvepolygon.cpp:578
QgsCurvePolygon::area
double area() const override
Returns the planar, 2-dimensional area of the geometry.
Definition: qgscurvepolygon.cpp:461
MathUtils::leftOf
double ANALYSIS_EXPORT leftOf(const QgsPoint &thepoint, const QgsPoint *p1, const QgsPoint *p2)
Returns whether 'thepoint' is left or right of the line from 'p1' to 'p2'. Negative values mean left ...
Definition: MathUtils.cpp:292
QgsAbstractGeometry::vertexAngle
virtual double vertexAngle(QgsVertexId vertex) const =0
Returns approximate angle at a vertex.
QgsCurvePolygon::dimension
int dimension() const override
Returns the inherent dimension of the geometry.
Definition: qgscurvepolygon.cpp:57
precision
int precision
Definition: qgswfsgetfeature.cpp:103
QgsCurvePolygon::insertVertex
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
Definition: qgscurvepolygon.cpp:1004
QgsCurvePolygon::removeInteriorRing
bool removeInteriorRing(int ringIndex)
Removes an interior ring from the polygon.
Definition: qgscurvepolygon.cpp:696
QgsCurvePolygon::asJsonObject
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
Definition: qgscurvepolygon.cpp:414
QgsGeometryUtils::closestSegmentFromComponents
static double closestSegmentFromComponents(T &container, ComponentType ctype, const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon)
Definition: qgsgeometryutils.h:739
QgsCurvePolygon::mExteriorRing
std::unique_ptr< QgsCurve > mExteriorRing
Definition: qgscurvepolygon.h:305
QgsCircularString
Circular string geometry type.
Definition: qgscircularstring.h:34
QgsCurvePolygon::fromWkb
bool fromWkb(QgsConstWkbPtr &wkb) override
Sets the geometry from a WKB string.
Definition: qgscurvepolygon.cpp:154
QgsAbstractGeometry::insertVertex
virtual bool insertVertex(QgsVertexId position, const QgsPoint &vertex)=0
Inserts a vertex into the geometry.
QgsCurvePolygon::removeInteriorRings
void removeInteriorRings(double minimumAllowedArea=-1)
Removes the interior rings from the polygon.
Definition: qgscurvepolygon.cpp:707
QgsAbstractGeometry::AxisOrder
AxisOrder
Axis order for GML generation.
Definition: qgsabstractgeometry.h:128
QgsCurvePolygon::childGeometry
QgsAbstractGeometry * childGeometry(int index) const override
Returns pointer to child geometry (for geometries with child geometries - i.e.
Definition: qgscurvepolygon.cpp:1271
QgsCurvePolygon::transform
void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) override SIP_THROW(QgsCsException)
Transforms the geometry using a coordinate transform.
Definition: qgscurvepolygon.cpp:793
QgsMultiCurve
Multi curve geometry collection.
Definition: qgsmulticurve.h:29
QgsCurvePolygon::~QgsCurvePolygon
~QgsCurvePolygon() override
Definition: qgscurvepolygon.cpp:40
QgsCurvePolygon::addInteriorRing
virtual void addInteriorRing(QgsCurve *ring)
Adds an interior ring to the geometry (takes ownership)
Definition: qgscurvepolygon.cpp:676
QgsConstWkbPtr
Definition: qgswkbptr.h:127
QgsCurvePolygon::childCount
int childCount() const override
Returns number of child geometries (for geometries with child geometries) or child points (for geomet...
Definition: qgscurvepolygon.cpp:1266
QgsCurvePolygon::removeInvalidRings
void removeInvalidRings()
Removes any interior rings which are not valid from the polygon.
Definition: qgscurvepolygon.cpp:725
QgsCurvePolygon::operator!=
bool operator!=(const QgsAbstractGeometry &other) const override
Definition: qgscurvepolygon.cpp:134
QgsCurve::Clockwise
@ Clockwise
Clockwise orientation.
Definition: qgscurve.h:238
QgsCurvePolygon::nextVertex
bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const override
Returns next vertex id and coordinates.
Definition: qgscurvepolygon.cpp:913
QgsWkbTypes::CurvePolygon
@ CurvePolygon
Definition: qgswkbtypes.h:81
QgsAbstractGeometry::deleteVertex
virtual bool deleteVertex(QgsVertexId position)=0
Deletes a vertex within the geometry.
QgsCurvePolygon::filterVertices
void filterVertices(const std::function< bool(const QgsPoint &) > &filter) override
Filters the vertices from the geometry in place, removing any which do not return true for the filter...
Definition: qgscurvepolygon.cpp:1242
QgsCurve::CounterClockwise
@ CounterClockwise
Counter-clockwise orientation.
Definition: qgscurve.h:239
QgsCurvePolygon::dropMValue
bool dropMValue() override
Drops any measure values which exist in the geometry.
Definition: qgscurvepolygon.cpp:1210
QgsWkbTypes::geometryType
static GeometryType geometryType(Type type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:937
QgsCurvePolygon::operator==
bool operator==(const QgsAbstractGeometry &other) const override
Definition: qgscurvepolygon.cpp:97
QgsApplication::endian
static endian_t endian()
Returns whether this machine uses big or little endian.
Definition: qgsapplication.cpp:1230
QgsCurvePolygon::partCount
int partCount() const override
Returns count of parts contained in the geometry.
Definition: qgscurvepolygon.cpp:1139
QgsAbstractGeometry::is3D
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
Definition: qgsabstractgeometry.h:202
QgsCurvePolygon::createEmptyWithSameType
QgsCurvePolygon * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
Definition: qgscurvepolygon.cpp:45
QgsCurvePolygon::vertexCount
int vertexCount(int part=0, int ring=0) const override
Returns the number of vertices of which this geometry is built.
Definition: qgscurvepolygon.cpp:1129
QgsGeometryUtils::Ring
@ Ring
Definition: qgsgeometryutils.h:734
QgsCurvePolygon::moveVertex
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
Definition: qgscurvepolygon.cpp:1030
QgsCurve::vertexAt
QgsPoint vertexAt(QgsVertexId id) const override
Returns the point corresponding to a specified vertex id.
Definition: qgscurve.cpp:182
QgsWkbPtr
Definition: qgswkbptr.h:42
QgsRingSequence
QVector< QgsPointSequence > QgsRingSequence
Definition: qgsabstractgeometry.h:48
qgscurvepolygon.h
qgscircularstring.h
QgsCurvePolygon::isEmpty
bool isEmpty() const override
Returns true if the geometry is empty.
Definition: qgscurvepolygon.cpp:893
QgsAbstractGeometry
Abstract base class for all geometries.
Definition: qgsabstractgeometry.h:71
QgsCurvePolygon::coordinateSequence
QgsCoordinateSequence coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
Definition: qgscurvepolygon.cpp:821
qgsgeometryutils.h
QgsCurvePolygon::perimeter
double perimeter() const override
Returns the planar, 2-dimensional perimeter of the geometry.
Definition: qgscurvepolygon.cpp:489
QgsCurvePolygon::asWkt
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
Definition: qgscurvepolygon.cpp:319
QgsWkbTypes::addZ
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1138
QgsGeometryUtils::wktGetChildBlocks
static QStringList wktGetChildBlocks(const QString &wkt, const QString &defaultType=QString())
Parses a WKT string and returns of list of blocks contained in the WKT.
Definition: qgsgeometryutils.cpp:1325
QgsCurve::clone
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
QgsCurvePolygon::fromWkt
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
Definition: qgscurvepolygon.cpp:207
QgsCurvePolygon::toCurveType
QgsCurvePolygon * toCurveType() const override
Returns the geometry converted to the more generic curve type.
Definition: qgscurvepolygon.cpp:1237
QgsWkbTypes::hasM
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1092
QgsCurvePolygon::numInteriorRings
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
Definition: qgscurvepolygon.h:76
QgsPoint::moveVertex
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
Definition: qgspoint.cpp:407
QgsWkbTypes::CircularString
@ CircularString
Definition: qgswkbtypes.h:79
QgsAbstractGeometry::asGml3
virtual QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const =0
Returns a GML3 representation of the geometry.
QgsCurvePolygon::vertexNumberFromVertexId
int vertexNumberFromVertexId(QgsVertexId id) const override
Returns the vertex number corresponding to a vertex id.
Definition: qgscurvepolygon.cpp:858
QgsCurvePolygon::boundary
QgsAbstractGeometry * boundary() const override
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
Definition: qgscurvepolygon.cpp:521
QgsAbstractGeometry::operator=
QgsAbstractGeometry & operator=(const QgsAbstractGeometry &geom)
Definition: qgsabstractgeometry.cpp:33
QgsPointSequence
QVector< QgsPoint > QgsPointSequence
Definition: qgsabstractgeometry.h:44
QgsCurvePolygon::asGml3
QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML3 representation of the geometry.
Definition: qgscurvepolygon.cpp:384
QgsWkbTypes::Polygon
@ Polygon
Definition: qgswkbtypes.h:73
QgsCurvePolygon::ringCount
int ringCount(int part=0) const override
Returns the number of rings of which this geometry is built.
Definition: qgscurvepolygon.cpp:1134
QgsAbstractGeometry::segmentLength
virtual double segmentLength(QgsVertexId startVertex) const =0
Returns the length of the segment of the geometry which begins at startVertex.
QgsVertexId
Utility class for identifying a unique vertex within a geometry.
Definition: qgsabstractgeometry.h:1033
QgsCurvePolygon::forceRHR
void forceRHR()
Forces the geometry to respect the Right-Hand-Rule, in which the area that is bounded by the polygon ...
Definition: qgscurvepolygon.cpp:744
QgsCurvePolygon::geometryType
QString geometryType() const override
Returns a unique string representing the geometry type.
Definition: qgscurvepolygon.cpp:52
QgsVertexId::ring
int ring
Definition: qgsabstractgeometry.h:1081
QgsCurvePolygon::surfaceToPolygon
QgsPolygon * surfaceToPolygon() const override
Gets a polygon representation of this surface.
Definition: qgscurvepolygon.cpp:503
QgsAbstractGeometry::isMeasure
bool isMeasure() const
Returns true if the geometry contains m values.
Definition: qgsabstractgeometry.h:211
QgsVertexId::VertexType
VertexType
Definition: qgsabstractgeometry.h:1035
qgsmulticurve.h
QgsCurvePolygon::mInteriorRings
QVector< QgsCurve * > mInteriorRings
Definition: qgscurvepolygon.h:306
QgsWkbTypes::dropZ
static Type dropZ(Type type)
Drops the z dimension (if present) for a WKB type and returns the new type.
Definition: qgswkbtypes.h:1194
QgsCurve::numPoints
virtual int numPoints() const =0
Returns the number of points in the curve.
QgsConstWkbPtr::readHeader
QgsWkbTypes::Type readHeader() const
readHeader
Definition: qgswkbptr.cpp:54
QgsGeometryUtils::wktReadBlock
static QPair< QgsWkbTypes::Type, QString > wktReadBlock(const QString &wkt)
Parses a WKT block of the format "TYPE( contents )" and returns a pair of geometry type to contents (...
Definition: qgsgeometryutils.cpp:1299
QgsAbstractGeometry::setZMTypeFromSubGeometry
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, QgsWkbTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
Definition: qgsabstractgeometry.cpp:43
QgsCurvePolygon::addZValue
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
Definition: qgscurvepolygon.cpp:1160
QgsCoordinateTransform
Definition: qgscoordinatetransform.h:52
QgsCurvePolygon::segmentize
QgsAbstractGeometry * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
Definition: qgscurvepolygon.cpp:1112
ringAdjacentVertices
void ringAdjacentVertices(const QgsCurve *curve, QgsVertexId vertex, QgsVertexId &previousVertex, QgsVertexId &nextVertex)
Definition: qgscurvepolygon.cpp:949
QgsCurvePolygon::vertexAngle
double vertexAngle(QgsVertexId vertex) const override
Returns approximate rotation angle for a vertex.
Definition: qgscurvepolygon.cpp:1117
QgsCurvePolygon::closestSegment
double closestSegment(const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf=nullptr, double epsilon=4 *std::numeric_limits< double >::epsilon()) const override
Searches for the closest segment of the geometry to a given point.
Definition: qgscurvepolygon.cpp:901
QgsWkbTypes::flatType
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:701
QgsCompoundCurve
Compound curve geometry type.
Definition: qgscompoundcurve.h:31
QgsCurvePolygon::segmentLength
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
Definition: qgscurvepolygon.cpp:1149
QgsCurvePolygon::snappedToGrid
QgsCurvePolygon * snappedToGrid(double hSpacing, double vSpacing, double dSpacing=0, double mSpacing=0) const override
Makes a new geometry with all the points or vertices snapped to the closest point of the grid.
Definition: qgscurvepolygon.cpp:544
QgsCurvePolygon::asWkb
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const override
Definition: qgscurvepolygon.cpp:288
QgsWkbTypes::CompoundCurve
@ CompoundCurve
Definition: qgswkbtypes.h:80
QgsCurvePolygon::operator=
QgsCurvePolygon & operator=(const QgsCurvePolygon &p)
Definition: qgscurvepolygon.cpp:78
QgsCurvePolygon::vertexAt
QgsPoint vertexAt(QgsVertexId id) const override
Returns the point corresponding to a specified vertex id.
Definition: qgscurvepolygon.cpp:1144