QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgscurvepolygonv2.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscurvepolygonv2.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 "qgscurvepolygonv2.h"
19 #include "qgsapplication.h"
20 #include "qgscircularstringv2.h"
21 #include "qgscompoundcurvev2.h"
22 #include "qgsgeometryutils.h"
23 #include "qgslinestringv2.h"
24 #include "qgspolygonv2.h"
25 #include "qgswkbptr.h"
26 #include "qgsmulticurvev2.h"
27 #include <QPainter>
28 #include <QPainterPath>
29 
30 QgsCurvePolygonV2::QgsCurvePolygonV2(): QgsSurfaceV2(), mExteriorRing( nullptr )
31 {
33 }
34 
36 {
37  clear();
38 }
39 
41  : QgsSurfaceV2( p )
42  , mExteriorRing( nullptr )
43 {
44  mWkbType = p.mWkbType;
45  if ( p.mExteriorRing )
46  {
47  mExteriorRing = static_cast<QgsCurveV2*>( p.mExteriorRing->clone() );
48  }
49 
50  Q_FOREACH ( const QgsCurveV2* ring, p.mInteriorRings )
51  {
52  mInteriorRings.push_back( static_cast<QgsCurveV2*>( ring->clone() ) );
53  }
54 }
55 
57 {
58  if ( &p != this )
59  {
60  clearCache();
62  if ( p.mExteriorRing )
63  {
64  mExteriorRing = static_cast<QgsCurveV2*>( p.mExteriorRing->clone() );
65  }
66 
67  Q_FOREACH ( const QgsCurveV2* ring, p.mInteriorRings )
68  {
69  mInteriorRings.push_back( static_cast<QgsCurveV2*>( ring->clone() ) );
70  }
71  }
72  return *this;
73 }
74 
76 {
77  return new QgsCurvePolygonV2( *this );
78 }
79 
81 {
83  delete mExteriorRing;
84  mExteriorRing = nullptr;
85  qDeleteAll( mInteriorRings );
87  clearCache();
88 }
89 
90 
92 {
93  clear();
94  if ( !wkbPtr )
95  {
96  return false;
97  }
98 
99  QgsWKBTypes::Type type = wkbPtr.readHeader();
101  {
102  return false;
103  }
104  mWkbType = type;
105 
106  int nRings;
107  wkbPtr >> nRings;
108  QgsCurveV2* currentCurve = nullptr;
109  int currentCurveSize = 0;
110  for ( int i = 0; i < nRings; ++i )
111  {
112  QgsWKBTypes::Type curveType = wkbPtr.readHeader();
113  wkbPtr -= 1 + sizeof( int );
114  QgsWKBTypes::Type flatCurveType = QgsWKBTypes::flatType( curveType );
115  if ( flatCurveType == QgsWKBTypes::LineString )
116  {
117  currentCurve = new QgsLineStringV2();
118  }
119  else if ( flatCurveType == QgsWKBTypes::CircularString )
120  {
121  currentCurve = new QgsCircularStringV2();
122  }
123  else if ( flatCurveType == QgsWKBTypes::CompoundCurve )
124  {
125  currentCurve = new QgsCompoundCurveV2();
126  }
127  else
128  {
129  return false;
130  }
131  currentCurve->fromWkb( wkbPtr );
132  currentCurveSize = currentCurve->wkbSize();
133  if ( i == 0 )
134  {
135  mExteriorRing = currentCurve;
136  }
137  else
138  {
139  mInteriorRings.append( currentCurve );
140  }
141  wkbPtr += currentCurveSize;
142  }
143 
144  return true;
145 }
146 
148 {
149  clear();
150 
152 
154  return false;
155 
156  mWkbType = parts.first;
157 
158  QString defaultChildWkbType = QString( "LineString%1%2" ).arg( is3D() ? "Z" : "", isMeasure() ? "M" : "" );
159 
160  Q_FOREACH ( const QString& childWkt, QgsGeometryUtils::wktGetChildBlocks( parts.second, defaultChildWkbType ) )
161  {
163 
164  QgsWKBTypes::Type flatCurveType = QgsWKBTypes::flatType( childParts.first );
165  if ( flatCurveType == QgsWKBTypes::LineString )
167  else if ( flatCurveType == QgsWKBTypes::CircularString )
169  else if ( flatCurveType == QgsWKBTypes::CompoundCurve )
171  else
172  {
173  clear();
174  return false;
175  }
176  if ( !mInteriorRings.back()->fromWkt( childWkt ) )
177  {
178  clear();
179  return false;
180  }
181  }
182 
183  if ( mInteriorRings.isEmpty() )
184  {
185  clear();
186  return false;
187  }
188 
191 
192  //scan through rings and check if dimensionality of rings is different to CurvePolygon.
193  //if so, update the type dimensionality of the CurvePolygon to match
194  bool hasZ = false;
195  bool hasM = false;
196  if ( mExteriorRing )
197  {
198  hasZ = hasZ || mExteriorRing->is3D();
199  hasM = hasM || mExteriorRing->isMeasure();
200  }
201  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
202  {
203  hasZ = hasZ || curve->is3D();
204  hasM = hasM || curve->isMeasure();
205  if ( hasZ && hasM )
206  break;
207  }
208  if ( hasZ )
209  addZValue( 0 );
210  if ( hasM )
211  addMValue( 0 );
212 
213  return true;
214 }
215 
217 {
218  if ( mExteriorRing )
219  {
220  return mExteriorRing->boundingBox();
221  }
222  return QgsRectangle();
223 }
224 
226 {
227  int size = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 );
228  if ( mExteriorRing )
229  {
230  size += mExteriorRing->wkbSize();
231  }
232  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
233  {
234  size += curve->wkbSize();
235  }
236  return size;
237 }
238 
239 unsigned char* QgsCurvePolygonV2::asWkb( int& binarySize ) const
240 {
241  binarySize = wkbSize();
242  unsigned char* geomPtr = new unsigned char[binarySize];
243  QgsWkbPtr wkbPtr( geomPtr, binarySize );
244  wkbPtr << static_cast<char>( QgsApplication::endian() );
245  wkbPtr << static_cast<quint32>( wkbType() );
246  wkbPtr << static_cast<quint32>(( nullptr != mExteriorRing ) + mInteriorRings.size() );
247  if ( mExteriorRing )
248  {
249  int curveWkbLen = 0;
250  unsigned char *ringWkb = mExteriorRing->asWkb( curveWkbLen );
251  memcpy( wkbPtr, ringWkb, curveWkbLen );
252  wkbPtr += curveWkbLen;
253  }
254  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
255  {
256  int curveWkbLen = 0;
257  unsigned char *ringWkb = curve->asWkb( curveWkbLen );
258  memcpy( wkbPtr, ringWkb, curveWkbLen );
259  wkbPtr += curveWkbLen;
260  }
261  return geomPtr;
262 }
263 
264 QString QgsCurvePolygonV2::asWkt( int precision ) const
265 {
266  QString wkt = wktTypeStr() + " (";
267  if ( mExteriorRing )
268  {
269  QString childWkt = mExteriorRing->asWkt( precision );
270  if ( dynamic_cast<QgsLineStringV2*>( mExteriorRing ) )
271  {
272  // Type names of linear geometries are omitted
273  childWkt = childWkt.mid( childWkt.indexOf( '(' ) );
274  }
275  wkt += childWkt + ',';
276  }
277  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
278  {
279  QString childWkt = curve->asWkt( precision );
280  if ( dynamic_cast<const QgsLineStringV2*>( curve ) )
281  {
282  // Type names of linear geometries are omitted
283  childWkt = childWkt.mid( childWkt.indexOf( '(' ) );
284  }
285  wkt += childWkt + ',';
286  }
287  if ( wkt.endsWith( ',' ) )
288  {
289  wkt.chop( 1 ); // Remove last ','
290  }
291  wkt += ')';
292  return wkt;
293 }
294 
295 QDomElement QgsCurvePolygonV2::asGML2( QDomDocument& doc, int precision, const QString& ns ) const
296 {
297  // GML2 does not support curves
298  QDomElement elemPolygon = doc.createElementNS( ns, "Polygon" );
299  QDomElement elemOuterBoundaryIs = doc.createElementNS( ns, "outerBoundaryIs" );
300  QgsLineStringV2* exteriorLineString = exteriorRing()->curveToLine();
301  QDomElement outerRing = exteriorLineString->asGML2( doc, precision, ns );
302  outerRing.toElement().setTagName( "LinearRing" );
303  elemOuterBoundaryIs.appendChild( outerRing );
304  delete exteriorLineString;
305  elemPolygon.appendChild( elemOuterBoundaryIs );
306  for ( int i = 0, n = numInteriorRings(); i < n; ++i )
307  {
308  QDomElement elemInnerBoundaryIs = doc.createElementNS( ns, "innerBoundaryIs" );
309  QgsLineStringV2* interiorLineString = interiorRing( i )->curveToLine();
310  QDomElement innerRing = interiorLineString->asGML2( doc, precision, ns );
311  innerRing.toElement().setTagName( "LinearRing" );
312  elemInnerBoundaryIs.appendChild( innerRing );
313  delete interiorLineString;
314  elemPolygon.appendChild( elemInnerBoundaryIs );
315  }
316  return elemPolygon;
317 }
318 
319 QDomElement QgsCurvePolygonV2::asGML3( QDomDocument& doc, int precision, const QString& ns ) const
320 {
321  QDomElement elemCurvePolygon = doc.createElementNS( ns, "Polygon" );
322  QDomElement elemExterior = doc.createElementNS( ns, "exterior" );
323  QDomElement curveElem = exteriorRing()->asGML3( doc, precision, ns );
324  if ( curveElem.tagName() == "LineString" )
325  {
326  curveElem.setTagName( "LinearRing" );
327  }
328  elemExterior.appendChild( curveElem );
329  elemCurvePolygon.appendChild( elemExterior );
330 
331  for ( int i = 0, n = numInteriorRings(); i < n; ++i )
332  {
333  QDomElement elemInterior = doc.createElementNS( ns, "interior" );
334  QDomElement innerRing = interiorRing( i )->asGML3( doc, precision, ns );
335  if ( innerRing.tagName() == "LineString" )
336  {
337  innerRing.setTagName( "LinearRing" );
338  }
339  elemInterior.appendChild( innerRing );
340  elemCurvePolygon.appendChild( elemInterior );
341  }
342  return elemCurvePolygon;
343 }
344 
345 QString QgsCurvePolygonV2::asJSON( int precision ) const
346 {
347  // GeoJSON does not support curves
348  QString json = "{\"type\": \"Polygon\", \"coordinates\": [";
349 
350  QgsLineStringV2* exteriorLineString = exteriorRing()->curveToLine();
351  QgsPointSequenceV2 exteriorPts;
352  exteriorLineString->points( exteriorPts );
353  json += QgsGeometryUtils::pointsToJSON( exteriorPts, precision ) + ", ";
354  delete exteriorLineString;
355 
356  for ( int i = 0, n = numInteriorRings(); i < n; ++i )
357  {
358  QgsLineStringV2* interiorLineString = interiorRing( i )->curveToLine();
359  QgsPointSequenceV2 interiorPts;
360  interiorLineString->points( interiorPts );
361  json += QgsGeometryUtils::pointsToJSON( interiorPts, precision ) + ", ";
362  delete interiorLineString;
363  }
364  if ( json.endsWith( ", " ) )
365  {
366  json.chop( 2 ); // Remove last ", "
367  }
368  json += "] }";
369  return json;
370 }
371 
373 {
374  if ( !mExteriorRing )
375  {
376  return 0.0;
377  }
378 
379  double totalArea = 0.0;
380 
381  if ( mExteriorRing->isRing() )
382  {
383  double area = 0.0;
384  mExteriorRing->sumUpArea( area );
385  totalArea += qAbs( area );
386  }
387 
389  for ( ; ringIt != mInteriorRings.constEnd(); ++ringIt )
390  {
391  double area = 0.0;
392  if (( *ringIt )->isRing() )
393  {
394  ( *ringIt )->sumUpArea( area );
395  totalArea -= qAbs( area );
396  }
397  }
398  return totalArea;
399 }
400 
402 {
403  if ( !mExteriorRing )
404  return 0.0;
405 
406  //sum perimeter of rings
407  double perimeter = mExteriorRing->length();
409  for ( ; ringIt != mInteriorRings.constEnd(); ++ringIt )
410  {
411  perimeter += ( *ringIt )->length();
412  }
413  return perimeter;
414 }
415 
417 {
418  QgsPolygonV2* polygon = new QgsPolygonV2();
419  polygon->setExteriorRing( exteriorRing()->curveToLine() );
420  QList<QgsCurveV2*> interiors;
421  int n = numInteriorRings();
422  interiors.reserve( n );
423  for ( int i = 0; i < n; ++i )
424  {
425  interiors.append( interiorRing( i )->curveToLine() );
426  }
427  polygon->setInteriorRings( interiors );
428  return polygon;
429 }
430 
432 {
433  if ( mInteriorRings.isEmpty() )
434  {
435  return mExteriorRing->clone();
436  }
437  else
438  {
439  QgsMultiCurveV2* multiCurve = new QgsMultiCurveV2();
440  multiCurve->addGeometry( mExteriorRing->clone() );
441  int nInteriorRings = mInteriorRings.size();
442  for ( int i = 0; i < nInteriorRings; ++i )
443  {
444  multiCurve->addGeometry( mInteriorRings.at( i )->clone() );
445  }
446  return multiCurve;
447  }
448 }
449 
450 QgsPolygonV2* QgsCurvePolygonV2::toPolygon( double tolerance, SegmentationToleranceType toleranceType ) const
451 {
452  if ( !mExteriorRing )
453  {
454  return nullptr;
455  }
456 
457  QgsPolygonV2* poly = new QgsPolygonV2();
458  poly->setExteriorRing( mExteriorRing->curveToLine( tolerance, toleranceType ) );
459 
460  QList<QgsCurveV2*> rings;
462  for ( ; it != mInteriorRings.constEnd(); ++it )
463  {
464  rings.push_back(( *it )->curveToLine( tolerance, toleranceType ) );
465  }
466  poly->setInteriorRings( rings );
467  return poly;
468 }
469 
471 {
472  return mInteriorRings.size();
473 }
474 
476 {
477  return mExteriorRing;
478 }
479 
481 {
482  if ( i < 0 || i >= mInteriorRings.size() )
483  {
484  return nullptr;
485  }
486  return mInteriorRings.at( i );
487 }
488 
490 {
491  if ( !ring )
492  {
493  return;
494  }
495  delete mExteriorRing;
496  mExteriorRing = ring;
497 
498  //set proper wkb type
500  {
502  }
504  {
506  }
507 
508  //match dimensionality for rings
509  Q_FOREACH ( QgsCurveV2* ring, mInteriorRings )
510  {
511  if ( is3D() )
512  ring->addZValue();
513  else
514  ring->dropZValue();
515 
516  if ( isMeasure() )
517  ring->addMValue();
518  else
519  ring->dropMValue();
520  }
521  clearCache();
522 }
523 
525 {
526  qDeleteAll( mInteriorRings );
528 
529  //add rings one-by-one, so that they can each be converted to the correct type for the CurvePolygon
530  Q_FOREACH ( QgsCurveV2* ring, rings )
531  {
532  addInteriorRing( ring );
533  }
534  clearCache();
535 }
536 
538 {
539  if ( !ring )
540  return;
541 
542  //ensure dimensionality of ring matches curve polygon
543  if ( !is3D() )
544  ring->dropZValue();
545  else if ( !ring->is3D() )
546  ring->addZValue();
547 
548  if ( !isMeasure() )
549  ring->dropMValue();
550  else if ( !ring->isMeasure() )
551  ring->addMValue();
552 
553  mInteriorRings.append( ring );
554  clearCache();
555 }
556 
558 {
559  if ( nr < 0 || nr >= mInteriorRings.size() )
560  {
561  return false;
562  }
563  delete mInteriorRings.takeAt( nr );
564  clearCache();
565  return true;
566 }
567 
569 {
570  if ( mInteriorRings.size() < 1 )
571  {
572  if ( mExteriorRing )
573  {
575  }
576  }
577  else
578  {
579  QPainterPath path;
581 
583  for ( ; it != mInteriorRings.constEnd(); ++it )
584  {
585  ( *it )->addToPainterPath( path );
586  }
587  p.drawPath( path );
588  }
589 }
590 
592 {
593  if ( mExteriorRing )
594  {
595  mExteriorRing->transform( ct, d, transformZ );
596  }
597 
598  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
599  {
600  curve->transform( ct, d, transformZ );
601  }
602  clearCache();
603 }
604 
606 {
607  if ( mExteriorRing )
608  {
609  mExteriorRing->transform( t );
610  }
611 
612  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
613  {
614  curve->transform( t );
615  }
616  clearCache();
617 }
618 
620 {
621  if ( !mCoordinateSequence.isEmpty() )
622  return mCoordinateSequence;
623 
625 
626  if ( mExteriorRing )
627  {
630  }
631 
633  for ( ; it != mInteriorRings.constEnd(); ++it )
634  {
636  ( *it )->points( mCoordinateSequence.back().back() );
637  }
638 
639  return mCoordinateSequence;
640 }
641 
643 {
644  if ( !mCoordinateSequence.isEmpty() )
646 
647  int count = 0;
648 
649  if ( mExteriorRing )
650  {
651  count += mExteriorRing->nCoordinates();
652  }
653 
655  for ( ; it != mInteriorRings.constEnd(); ++it )
656  {
657  count += ( *it )->nCoordinates();
658  }
659 
660  return count;
661 }
662 
663 double QgsCurvePolygonV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const
664 {
665  if ( !mExteriorRing )
666  {
667  return -1;
668  }
669  QList<QgsCurveV2*> segmentList;
670  segmentList.append( mExteriorRing );
671  segmentList.append( mInteriorRings );
672  return QgsGeometryUtils::closestSegmentFromComponents( segmentList, QgsGeometryUtils::RING, pt, segmentPt, vertexAfter, leftOf, epsilon );
673 }
674 
676 {
677  if ( !mExteriorRing || vId.ring >= 1 + mInteriorRings.size() )
678  {
679  return false;
680  }
681 
682  if ( vId.ring < 0 )
683  {
684  vId.ring = 0;
685  vId.vertex = -1;
686  if ( vId.part < 0 )
687  {
688  vId.part = 0;
689  }
690  return mExteriorRing->nextVertex( vId, vertex );
691  }
692  else
693  {
694  QgsCurveV2* ring = vId.ring == 0 ? mExteriorRing : mInteriorRings[vId.ring - 1];
695 
696  if ( ring->nextVertex( vId, vertex ) )
697  {
698  return true;
699  }
700  ++vId.ring;
701  vId.vertex = -1;
702  if ( vId.ring >= 1 + mInteriorRings.size() )
703  {
704  return false;
705  }
706  ring = mInteriorRings[ vId.ring - 1 ];
707  return ring->nextVertex( vId, vertex );
708  }
709 }
710 
712 {
713  if ( !mExteriorRing || vId.ring < 0 || vId.ring >= 1 + mInteriorRings.size() )
714  {
715  return false;
716  }
717 
718  QgsCurveV2* ring = vId.ring == 0 ? mExteriorRing : mInteriorRings.at( vId.ring - 1 );
719  int n = ring->numPoints();
720  bool success = ring->insertVertex( QgsVertexId( 0, 0, vId.vertex ), vertex );
721  if ( !success )
722  {
723  return false;
724  }
725 
726  // If first or last vertex is inserted, re-sync the last/first vertex
727  if ( vId.vertex == 0 )
728  ring->moveVertex( QgsVertexId( 0, 0, n ), vertex );
729  else if ( vId.vertex == n )
730  ring->moveVertex( QgsVertexId( 0, 0, 0 ), vertex );
731 
732  clearCache();
733 
734  return true;
735 }
736 
738 {
739  if ( !mExteriorRing || vId.ring < 0 || vId.ring >= 1 + mInteriorRings.size() )
740  {
741  return false;
742  }
743 
744  QgsCurveV2* ring = vId.ring == 0 ? mExteriorRing : mInteriorRings.at( vId.ring - 1 );
745  int n = ring->numPoints();
746  bool success = ring->moveVertex( vId, newPos );
747  if ( success )
748  {
749  // If first or last vertex is moved, also move the last/first vertex
750  if ( vId.vertex == 0 )
751  ring->moveVertex( QgsVertexId( vId.part, vId.ring, n - 1 ), newPos );
752  else if ( vId.vertex == n - 1 )
753  ring->moveVertex( QgsVertexId( vId.part, vId.ring, 0 ), newPos );
754  clearCache();
755  }
756  return success;
757 }
758 
760 {
761  if ( !mExteriorRing || vId.ring < 0 || vId.ring >= 1 + mInteriorRings.size() )
762  {
763  return false;
764  }
765 
766  QgsCurveV2* ring = vId.ring == 0 ? mExteriorRing : mInteriorRings.at( vId.ring - 1 );
767  int n = ring->numPoints();
768  if ( n <= 4 )
769  {
770  //no points will be left in ring, so remove whole ring
771  if ( vId.ring == 0 )
772  {
773  delete mExteriorRing;
774  mExteriorRing = nullptr;
775  if ( !mInteriorRings.isEmpty() )
776  {
778  }
779  }
780  else
781  {
782  removeInteriorRing( vId.ring - 1 );
783  }
784  clearCache();
785  return true;
786  }
787 
788  bool success = ring->deleteVertex( vId );
789  if ( success )
790  {
791  // If first or last vertex is removed, re-sync the last/first vertex
792  // Do not use "n - 2", but "ring->numPoints() - 1" as more than one vertex
793  // may have been deleted (e.g. with CircularString)
794  if ( vId.vertex == 0 )
795  ring->moveVertex( QgsVertexId( 0, 0, ring->numPoints() - 1 ), ring->vertexAt( QgsVertexId( 0, 0, 0 ) ) );
796  else if ( vId.vertex == n - 1 )
797  ring->moveVertex( QgsVertexId( 0, 0, 0 ), ring->vertexAt( QgsVertexId( 0, 0, ring->numPoints() - 1 ) ) );
798  clearCache();
799  }
800  return success;
801 }
802 
804 {
806  {
807  return true;
808  }
809 
811  for ( ; it != mInteriorRings.constEnd(); ++it )
812  {
813  if (( *it )->hasCurvedSegments() )
814  {
815  return true;
816  }
817  }
818  return false;
819 }
820 
822 {
823  return toPolygon( tolerance, toleranceType );
824 }
825 
827 {
828  if ( !mExteriorRing || vertex.ring < 0 || vertex.ring >= 1 + mInteriorRings.size() )
829  {
830  //makes no sense - conversion of false to double!
831  return false;
832  }
833 
834  QgsCurveV2* ring = vertex.ring == 0 ? mExteriorRing : mInteriorRings[vertex.ring - 1];
835  return ring->vertexAngle( vertex );
836 }
837 
838 int QgsCurvePolygonV2::vertexCount( int /*part*/, int ring ) const
839 {
840  return ring == 0 ? mExteriorRing->vertexCount() : mInteriorRings[ring - 1]->vertexCount();
841 }
842 
844 {
845  return id.ring == 0 ? mExteriorRing->vertexAt( id ) : mInteriorRings[id.ring - 1]->vertexAt( id );
846 }
847 
848 bool QgsCurvePolygonV2::addZValue( double zValue )
849 {
850  if ( QgsWKBTypes::hasZ( mWkbType ) )
851  return false;
852 
854 
855  if ( mExteriorRing )
856  mExteriorRing->addZValue( zValue );
857  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
858  {
859  curve->addZValue( zValue );
860  }
861  clearCache();
862  return true;
863 }
864 
865 bool QgsCurvePolygonV2::addMValue( double mValue )
866 {
867  if ( QgsWKBTypes::hasM( mWkbType ) )
868  return false;
869 
871 
872  if ( mExteriorRing )
873  mExteriorRing->addMValue( mValue );
874  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
875  {
876  curve->addMValue( mValue );
877  }
878  clearCache();
879  return true;
880 }
881 
883 {
884  if ( !is3D() )
885  return false;
886 
888  if ( mExteriorRing )
890  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
891  {
892  curve->dropZValue();
893  }
894  clearCache();
895  return true;
896 }
897 
899 {
900  if ( !isMeasure() )
901  return false;
902 
904  if ( mExteriorRing )
906  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
907  {
908  curve->dropMValue();
909  }
910  clearCache();
911  return true;
912 }
QString wktTypeStr() const
Returns the WKT type string of the geometry.
void clear()
bool removeInteriorRing(int nr)
Removes ring.
bool hasCurvedSegments() const override
Returns true if the geometry contains curved segments.
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
const QgsCurveV2 * exteriorRing() const
void setInteriorRings(const QList< QgsCurveV2 *> &rings)
Sets all interior rings (takes ownership)
A rectangle specified with double values.
Definition: qgsrectangle.h:35
QDomElement asGML2(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML2 representation of the geometry.
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
virtual bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
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 (...
const QgsCurveV2 * interiorRing(int i) const
QDomElement asGML2(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML2 representation of the geometry.
virtual QgsRectangle calculateBoundingBox() const override
Default calculator for the minimal bounding box for the geometry.
virtual QgsAbstractGeometryV2 & operator=(const QgsAbstractGeometryV2 &geom)
QDomNode appendChild(const QDomNode &newChild)
virtual void addInteriorRing(QgsCurveV2 *ring)
Adds an interior ring to the geometry (takes ownership)
void push_back(const T &value)
void clear() override
Clears the geometry, ie reset it to a null geometry.
void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) override
Transforms the geometry using a coordinate transform.
void points(QgsPointSequenceV2 &pt) const override
Returns a list of points within the curve.
void setTagName(const QString &name)
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:757
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:714
Circular string geometry type.
QgsPolygonV2 * surfaceToPolygon() const override
Multi curve geometry collection.
void reserve(int alloc)
virtual bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle...
void removeFirst()
virtual QgsCoordinateSequenceV2 coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
TransformDirection
Enum used to indicate the direction (forward or inverse) of the transform.
const T & at(int i) const
virtual bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
virtual void addToPainterPath(QPainterPath &path) const =0
Adds a curve to a painter path.
static QString pointsToJSON(const QgsPointSequenceV2 &points, int precision)
Returns a geoJSON coordinates string.
Abstract base class for all geometries.
double vertexAngle(QgsVertexId vertex) const override
Returns approximate rotation angle for a vertex.
static QStringList wktGetChildBlocks(const QString &wkt, const QString &defaultType="")
Parses a WKT string and returns of list of blocks contained in the WKT.
T takeAt(int i)
static double closestSegmentFromComponents(T &container, componentType ctype, const QgsPointV2 &pt, QgsPointV2 &segmentPt, QgsVertexId &vertexAfter, bool *leftOf, double epsilon)
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
virtual bool moveVertex(QgsVertexId position, const QgsPointV2 &newPos) override
Moves a vertex within the geometry.
QDomElement createElementNS(const QString &nsURI, const QString &qName)
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:667
virtual QgsCurveV2 * clone() const override=0
Clones the geometry by performing a deep copy.
void chop(int n)
static endian_t endian()
Returns whether this machine uses big or little endian.
virtual bool isRing() const
Returns true if the curve is a ring.
Definition: qgscurvev2.cpp:42
virtual int wkbSize() const =0
Returns the size of the WKB representation of the geometry.
int size() const
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
virtual void clearCache() const override
Clears any cached parameters associated with the geometry, eg bounding boxes.
Definition: qgssurfacev2.h:48
QDomElement toElement() const
virtual int numPoints() const =0
Returns the number of points in the curve.
int wkbSize() const override
Returns the size of the WKB representation of the geometry.
Polygon geometry type.
Definition: qgspolygonv2.h:29
virtual bool dropMValue() override
Drops any measure values which exist in the geometry.
void append(const T &value)
static Type dropZ(Type type)
Drops the z dimension (if present) for a WKB type and returns the new type.
Definition: qgswkbtypes.h:811
virtual bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
virtual double perimeter() const override
Returns the perimeter of the geometry.
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:781
virtual void setExteriorRing(QgsCurveV2 *ring) override
Sets the exterior ring of the polygon.
Utility class for identifying a unique vertex within a geometry.
Line string geometry type, with support for z-dimension and m-values.
virtual bool fromWkb(QgsConstWkbPtr wkb)=0
Sets the geometry from a WKB string.
bool isMeasure() const
Returns true if the geometry contains m values.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspointv2.h:34
bool isEmpty() const
virtual bool addGeometry(QgsAbstractGeometryV2 *g) override
Adds a geometry and takes ownership.
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
QgsCurvePolygonV2 & operator=(const QgsCurvePolygonV2 &p)
virtual unsigned char * asWkb(int &binarySize) const =0
Returns a WKB representation of the geometry.
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
virtual QgsPolygonV2 * toPolygon(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a new polygon geometry corresponding to a segmentized approximation of the curve...
void setZMTypeFromSubGeometry(const QgsAbstractGeometryV2 *subggeom, QgsWKBTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
virtual QDomElement asGML3(QDomDocument &doc, int precision=17, const QString &ns="gml") const =0
Returns a GML3 representation of the geometry.
virtual bool nextVertex(QgsVertexId &id, QgsPointV2 &vertex) const override
Returns next vertex id and coordinates.
Definition: qgscurvev2.cpp:59
virtual int vertexCount(int=0, int ring=0) const override
unsigned char * asWkb(int &binarySize) const override
Returns a WKB representation of the geometry.
virtual void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
virtual QgsCurvePolygonV2 * clone() const override
Clones the geometry by performing a deep copy.
double closestSegment(const QgsPointV2 &pt, QgsPointV2 &segmentPt, QgsVertexId &vertexAfter, bool *leftOf, double epsilon) const override
Searches for the closest segment of the geometry to a given point.
Compound curve geometry type.
QList< QgsPointSequenceV2 > QgsRingSequenceV2
QgsCoordinateSequenceV2 mCoordinateSequence
Definition: qgssurfacev2.h:50
static GeometryType geometryType(Type type)
Returns the geometry type for a WKB type, eg both MultiPolygon and CurvePolygon would have a PolygonG...
Definition: qgswkbtypes.h:584
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
virtual void sumUpArea(double &sum) const =0
Sums up the area of the curve by iterating over the vertices (shoelace formula).
virtual double vertexAngle(QgsVertexId vertex) const =0
Returns approximate angle at a vertex.
static Type dropM(Type type)
Drops the m dimension (if present) for a WKB type and returns the new type.
Definition: qgswkbtypes.h:828
bool nextVertex(QgsVertexId &id, QgsPointV2 &vertex) const override
Returns next vertex id and coordinates.
QList< QgsCurveV2 * > mInteriorRings
QString asJSON(int precision=17) const override
Returns a GeoJSON representation of the geometry.
virtual QgsAbstractGeometryV2 * boundary() const override
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
virtual bool deleteVertex(QgsVertexId position)=0
Deletes a vertex within the geometry.
virtual bool insertVertex(QgsVertexId position, const QgsPointV2 &vertex) override
Inserts a vertex into the geometry.
QString mid(int position, int n) const
void drawPath(const QPainterPath &path)
virtual void setExteriorRing(QgsCurveV2 *ring)
Sets the exterior ring of the polygon.
T takeFirst()
virtual bool insertVertex(QgsVertexId position, const QgsPointV2 &vertex)=0
Inserts a vertex into the geometry.
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
virtual bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
virtual QgsLineStringV2 * curveToLine(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const =0
Returns a new line string geometry corresponding to a segmentized approximation of the curve...
virtual double length() const
Returns the length of the geometry.
Class for doing transforms between two map coordinate systems.
virtual QString asWkt(int precision=17) const =0
Returns a WKT representation of the geometry.
virtual int nCoordinates() const override
Returns the number of nodes contained in the geometry.
virtual bool fromWkb(QgsConstWkbPtr wkb) override
Sets the geometry from a WKB string.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:366
virtual bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
virtual void drawAsPolygon(QPainter &p) const =0
Draws the curve as a polygon on the specified QPainter.
QString tagName() const
double ANALYSIS_EXPORT leftOf(Point3D *thepoint, Point3D *p1, Point3D *p2)
Returns whether &#39;thepoint&#39; is left or right of the line from &#39;p1&#39; to &#39;p2&#39;.
virtual QgsPointV2 vertexAt(QgsVertexId id) const override
Returns the point corresponding to a specified vertex id.
Definition: qgscurvev2.cpp:103
Curve polygon geometry type.
QgsWKBTypes::Type readHeader() const
Definition: qgswkbptr.cpp:38
const_iterator constEnd() const
const_iterator constBegin() const
Abstract base class for curved geometry type.
Definition: qgscurvev2.h:32
QgsAbstractGeometryV2 * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
virtual bool moveVertex(QgsVertexId position, const QgsPointV2 &newPos)=0
Moves a vertex within the geometry.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QDomElement asGML3(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML3 representation of the geometry.
T & back()
virtual void points(QgsPointSequenceV2 &pt) const =0
Returns a list of points within the curve.
virtual int vertexCount(int part=0, int ring=0) const override
Definition: qgscurvev2.h:111
virtual double area() const override
Returns the area of the geometry.
virtual void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform, bool transformZ=false)=0
Transforms the geometry using a coordinate transform.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
virtual QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
Definition: qgscurvev2.cpp:111
QList< QgsPointV2 > QgsPointSequenceV2
virtual QgsPointV2 vertexAt(QgsVertexId id) const override
Returns the point corresponding to a specified vertex id.
QgsCurveV2 * mExteriorRing
int numInteriorRings() const