QGIS API Documentation  2.14.11-Essen
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 <QPainter>
27 #include <QPainterPath>
28 
29 QgsCurvePolygonV2::QgsCurvePolygonV2(): QgsSurfaceV2(), mExteriorRing( nullptr )
30 {
31 
32 }
33 
35 {
36  clear();
37 }
38 
40 {
41  if ( p.mExteriorRing )
42  {
43  mExteriorRing = static_cast<QgsCurveV2*>( p.mExteriorRing->clone() );
44  }
45 
46  Q_FOREACH ( const QgsCurveV2* ring, p.mInteriorRings )
47  {
48  mInteriorRings.push_back( static_cast<QgsCurveV2*>( ring->clone() ) );
49  }
50 }
51 
53 {
54  if ( &p != this )
55  {
56  clearCache();
58  if ( p.mExteriorRing )
59  {
60  mExteriorRing = static_cast<QgsCurveV2*>( p.mExteriorRing->clone() );
61  }
62 
63  Q_FOREACH ( const QgsCurveV2* ring, p.mInteriorRings )
64  {
65  mInteriorRings.push_back( static_cast<QgsCurveV2*>( ring->clone() ) );
66  }
67  }
68  return *this;
69 }
70 
72 {
73  return new QgsCurvePolygonV2( *this );
74 }
75 
77 {
78  delete mExteriorRing;
79  mExteriorRing = nullptr;
80  qDeleteAll( mInteriorRings );
83  clearCache();
84 }
85 
86 
88 {
89  clear();
90  if ( !wkbPtr )
91  {
92  return false;
93  }
94 
95  QgsWKBTypes::Type type = wkbPtr.readHeader();
97  {
98  return false;
99  }
100  mWkbType = type;
101 
102  int nRings;
103  wkbPtr >> nRings;
104  QgsCurveV2* currentCurve = nullptr;
105  int currentCurveSize = 0;
106  for ( int i = 0; i < nRings; ++i )
107  {
108  QgsWKBTypes::Type curveType = wkbPtr.readHeader();
109  wkbPtr -= 1 + sizeof( int );
110  if ( curveType == QgsWKBTypes::LineString || curveType == QgsWKBTypes::LineStringZ || curveType == QgsWKBTypes::LineStringM ||
111  curveType == QgsWKBTypes::LineStringZM || curveType == QgsWKBTypes::LineString25D )
112  {
113  currentCurve = new QgsLineStringV2();
114  }
115  else if ( curveType == QgsWKBTypes::CircularString || curveType == QgsWKBTypes::CircularStringZ || curveType == QgsWKBTypes::CircularStringZM ||
116  curveType == QgsWKBTypes::CircularStringM )
117  {
118  currentCurve = new QgsCircularStringV2();
119  }
120  else if ( curveType == QgsWKBTypes::CompoundCurve || curveType == QgsWKBTypes::CompoundCurveZ || curveType == QgsWKBTypes::CompoundCurveZM )
121  {
122  currentCurve = new QgsCompoundCurveV2();
123  }
124  else
125  {
126  return false;
127  }
128  currentCurve->fromWkb( wkbPtr );
129  currentCurveSize = currentCurve->wkbSize();
130  if ( i == 0 )
131  {
132  mExteriorRing = currentCurve;
133  }
134  else
135  {
136  mInteriorRings.append( currentCurve );
137  }
138  wkbPtr += currentCurveSize;
139  }
140 
141  return true;
142 }
143 
145 {
146  clear();
147 
149 
150  if ( QgsWKBTypes::flatType( parts.first ) != QgsWKBTypes::parseType( geometryType() ) )
151  return false;
152 
153  mWkbType = parts.first;
154 
155  QString defaultChildWkbType = QString( "LineString%1%2" ).arg( is3D() ? "Z" : "", isMeasure() ? "M" : "" );
156 
157  Q_FOREACH ( const QString& childWkt, QgsGeometryUtils::wktGetChildBlocks( parts.second, defaultChildWkbType ) )
158  {
160 
161  if ( QgsWKBTypes::flatType( childParts.first ) == QgsWKBTypes::LineString )
163  else if ( QgsWKBTypes::flatType( childParts.first ) == QgsWKBTypes::CircularString )
165  else
166  {
167  clear();
168  return false;
169  }
170  if ( !mInteriorRings.back()->fromWkt( childWkt ) )
171  {
172  clear();
173  return false;
174  }
175  }
176 
177  if ( mInteriorRings.isEmpty() )
178  {
179  clear();
180  return false;
181  }
182 
185 
186  //scan through rings and check if dimensionality of rings is different to CurvePolygon.
187  //if so, update the type dimensionality of the CurvePolygon to match
188  bool hasZ = false;
189  bool hasM = false;
190  if ( mExteriorRing )
191  {
192  hasZ = hasZ || mExteriorRing->is3D();
193  hasM = hasM || mExteriorRing->isMeasure();
194  }
195  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
196  {
197  hasZ = hasZ || curve->is3D();
198  hasM = hasM || curve->isMeasure();
199  if ( hasZ && hasM )
200  break;
201  }
202  if ( hasZ )
203  addZValue( 0 );
204  if ( hasM )
205  addMValue( 0 );
206 
207  return true;
208 }
209 
211 {
212  if ( mExteriorRing )
213  {
214  return mExteriorRing->boundingBox();
215  }
216  return QgsRectangle();
217 }
218 
220 {
221  int size = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 );
222  if ( mExteriorRing )
223  {
224  size += mExteriorRing->wkbSize();
225  }
226  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
227  {
228  size += curve->wkbSize();
229  }
230  return size;
231 }
232 
233 unsigned char* QgsCurvePolygonV2::asWkb( int& binarySize ) const
234 {
235  binarySize = wkbSize();
236  unsigned char* geomPtr = new unsigned char[binarySize];
237  QgsWkbPtr wkbPtr( geomPtr, binarySize );
238  wkbPtr << static_cast<char>( QgsApplication::endian() );
239  wkbPtr << static_cast<quint32>( wkbType() );
240  wkbPtr << static_cast<quint32>(( nullptr != mExteriorRing ) + mInteriorRings.size() );
241  if ( mExteriorRing )
242  {
243  int curveWkbLen = 0;
244  unsigned char *ringWkb = mExteriorRing->asWkb( curveWkbLen );
245  memcpy( wkbPtr, ringWkb, curveWkbLen );
246  wkbPtr += curveWkbLen;
247  }
248  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
249  {
250  int curveWkbLen = 0;
251  unsigned char *ringWkb = curve->asWkb( curveWkbLen );
252  memcpy( wkbPtr, ringWkb, curveWkbLen );
253  wkbPtr += curveWkbLen;
254  }
255  return geomPtr;
256 }
257 
258 QString QgsCurvePolygonV2::asWkt( int precision ) const
259 {
260  QString wkt = wktTypeStr() + " (";
261  if ( mExteriorRing )
262  {
263  QString childWkt = mExteriorRing->asWkt( precision );
264  if ( dynamic_cast<QgsLineStringV2*>( mExteriorRing ) )
265  {
266  // Type names of linear geometries are omitted
267  childWkt = childWkt.mid( childWkt.indexOf( '(' ) );
268  }
269  wkt += childWkt + ',';
270  }
271  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
272  {
273  QString childWkt = curve->asWkt( precision );
274  if ( dynamic_cast<const QgsLineStringV2*>( curve ) )
275  {
276  // Type names of linear geometries are omitted
277  childWkt = childWkt.mid( childWkt.indexOf( '(' ) );
278  }
279  wkt += childWkt + ',';
280  }
281  if ( wkt.endsWith( ',' ) )
282  {
283  wkt.chop( 1 ); // Remove last ','
284  }
285  wkt += ')';
286  return wkt;
287 }
288 
289 QDomElement QgsCurvePolygonV2::asGML2( QDomDocument& doc, int precision, const QString& ns ) const
290 {
291  // GML2 does not support curves
292  QDomElement elemPolygon = doc.createElementNS( ns, "Polygon" );
293  QDomElement elemOuterBoundaryIs = doc.createElementNS( ns, "outerBoundaryIs" );
294  QgsLineStringV2* exteriorLineString = exteriorRing()->curveToLine();
295  QDomElement outerRing = exteriorLineString->asGML2( doc, precision, ns );
296  outerRing.toElement().setTagName( "LinearRing" );
297  elemOuterBoundaryIs.appendChild( outerRing );
298  delete exteriorLineString;
299  elemPolygon.appendChild( elemOuterBoundaryIs );
300  QDomElement elemInnerBoundaryIs = doc.createElementNS( ns, "innerBoundaryIs" );
301  for ( int i = 0, n = numInteriorRings(); i < n; ++i )
302  {
303  QgsLineStringV2* interiorLineString = interiorRing( i )->curveToLine();
304  QDomElement innerRing = interiorLineString->asGML2( doc, precision, ns );
305  innerRing.toElement().setTagName( "LinearRing" );
306  elemInnerBoundaryIs.appendChild( innerRing );
307  delete interiorLineString;
308  }
309  elemPolygon.appendChild( elemInnerBoundaryIs );
310  return elemPolygon;
311 }
312 
313 QDomElement QgsCurvePolygonV2::asGML3( QDomDocument& doc, int precision, const QString& ns ) const
314 {
315  QDomElement elemCurvePolygon = doc.createElementNS( ns, "Polygon" );
316  QDomElement elemExterior = doc.createElementNS( ns, "exterior" );
317  QDomElement outerRing = exteriorRing()->asGML2( doc, precision, ns );
318  outerRing.toElement().setTagName( "LinearRing" );
319  elemExterior.appendChild( outerRing );
320  elemCurvePolygon.appendChild( elemExterior );
321  QDomElement elemInterior = doc.createElementNS( ns, "interior" );
322  for ( int i = 0, n = numInteriorRings(); i < n; ++i )
323  {
324  QDomElement innerRing = interiorRing( i )->asGML2( doc, precision, ns );
325  innerRing.toElement().setTagName( "LinearRing" );
326  elemInterior.appendChild( innerRing );
327  }
328  elemCurvePolygon.appendChild( elemInterior );
329  return elemCurvePolygon;
330 }
331 
332 QString QgsCurvePolygonV2::asJSON( int precision ) const
333 {
334  // GeoJSON does not support curves
335  QString json = "{\"type\": \"Polygon\", \"coordinates\": [";
336 
337  QgsLineStringV2* exteriorLineString = exteriorRing()->curveToLine();
338  QgsPointSequenceV2 exteriorPts;
339  exteriorLineString->points( exteriorPts );
340  json += QgsGeometryUtils::pointsToJSON( exteriorPts, precision ) + ", ";
341  delete exteriorLineString;
342 
343  for ( int i = 0, n = numInteriorRings(); i < n; ++i )
344  {
345  QgsLineStringV2* interiorLineString = interiorRing( i )->curveToLine();
346  QgsPointSequenceV2 interiorPts;
347  interiorLineString->points( interiorPts );
348  json += QgsGeometryUtils::pointsToJSON( interiorPts, precision ) + ", ";
349  delete interiorLineString;
350  }
351  if ( json.endsWith( ", " ) )
352  {
353  json.chop( 2 ); // Remove last ", "
354  }
355  json += "] }";
356  return json;
357 }
358 
360 {
361  if ( !mExteriorRing )
362  {
363  return 0.0;
364  }
365 
366  double totalArea = 0.0;
367 
368  if ( mExteriorRing->isRing() )
369  {
370  double area = 0.0;
371  mExteriorRing->sumUpArea( area );
372  totalArea += qAbs( area );
373  }
374 
376  for ( ; ringIt != mInteriorRings.constEnd(); ++ringIt )
377  {
378  double area = 0.0;
379  if (( *ringIt )->isRing() )
380  {
381  ( *ringIt )->sumUpArea( area );
382  totalArea -= qAbs( area );
383  }
384  }
385  return totalArea;
386 }
387 
389 {
390  if ( !mExteriorRing )
391  return 0.0;
392 
393  //sum perimeter of rings
394  double perimeter = mExteriorRing->length();
396  for ( ; ringIt != mInteriorRings.constEnd(); ++ringIt )
397  {
398  perimeter += ( *ringIt )->length();
399  }
400  return perimeter;
401 }
402 
404 {
405  QgsPolygonV2* polygon = new QgsPolygonV2();
406  polygon->setExteriorRing( exteriorRing()->curveToLine() );
407  QList<QgsCurveV2*> interiors;
408  int n = numInteriorRings();
409  interiors.reserve( n );
410  for ( int i = 0; i < n; ++i )
411  {
412  interiors.append( interiorRing( i )->curveToLine() );
413  }
414  polygon->setInteriorRings( interiors );
415  return polygon;
416 }
417 
419 {
420  if ( !mExteriorRing )
421  {
422  return nullptr;
423  }
424 
425  QgsPolygonV2* poly = new QgsPolygonV2();
427 
428  QList<QgsCurveV2*> rings;
430  for ( ; it != mInteriorRings.constEnd(); ++it )
431  {
432  rings.push_back(( *it )->curveToLine() );
433  }
434  poly->setInteriorRings( rings );
435  return poly;
436 }
437 
439 {
440  return mInteriorRings.size();
441 }
442 
444 {
445  return mExteriorRing;
446 }
447 
449 {
450  if ( i < 0 || i >= mInteriorRings.size() )
451  {
452  return nullptr;
453  }
454  return mInteriorRings.at( i );
455 }
456 
458 {
459  if ( !ring )
460  {
461  return;
462  }
463  delete mExteriorRing;
464  mExteriorRing = ring;
465 
466  //set proper wkb type
467  if ( geometryType() == "Polygon" )
468  {
470  }
471  else if ( geometryType() == "CurvePolygon" )
472  {
474  }
475 
476  //match dimensionality for rings
477  Q_FOREACH ( QgsCurveV2* ring, mInteriorRings )
478  {
479  if ( is3D() )
480  ring->addZValue();
481  else
482  ring->dropZValue();
483 
484  if ( isMeasure() )
485  ring->addMValue();
486  else
487  ring->dropMValue();
488  }
489  clearCache();
490 }
491 
493 {
494  qDeleteAll( mInteriorRings );
496 
497  //add rings one-by-one, so that they can each be converted to the correct type for the CurvePolygon
498  Q_FOREACH ( QgsCurveV2* ring, rings )
499  {
500  addInteriorRing( ring );
501  }
502  clearCache();
503 }
504 
506 {
507  if ( !ring )
508  return;
509 
510  //ensure dimensionality of ring matches curve polygon
511  if ( !is3D() )
512  ring->dropZValue();
513  else if ( !ring->is3D() )
514  ring->addZValue();
515 
516  if ( !isMeasure() )
517  ring->dropMValue();
518  else if ( !ring->isMeasure() )
519  ring->addMValue();
520 
521  mInteriorRings.append( ring );
522  clearCache();
523 }
524 
526 {
527  if ( nr < 0 || nr >= mInteriorRings.size() )
528  {
529  return false;
530  }
531  delete mInteriorRings.takeAt( nr );
532  clearCache();
533  return true;
534 }
535 
537 {
538  if ( mInteriorRings.size() < 1 )
539  {
540  if ( mExteriorRing )
541  {
543  }
544  }
545  else
546  {
547  QPainterPath path;
549 
551  for ( ; it != mInteriorRings.constEnd(); ++it )
552  {
553  ( *it )->addToPainterPath( path );
554  }
555  p.drawPath( path );
556  }
557 }
558 
560 {
561  if ( mExteriorRing )
562  {
563  mExteriorRing->transform( ct, d );
564  }
565 
566  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
567  {
568  curve->transform( ct, d );
569  }
570  clearCache();
571 }
572 
574 {
575  if ( mExteriorRing )
576  {
577  mExteriorRing->transform( t );
578  }
579 
580  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
581  {
582  curve->transform( t );
583  }
584  clearCache();
585 }
586 
588 {
589  if ( !mCoordinateSequence.isEmpty() )
590  return mCoordinateSequence;
591 
593 
594  if ( mExteriorRing )
595  {
598  }
599 
601  for ( ; it != mInteriorRings.constEnd(); ++it )
602  {
604  ( *it )->points( mCoordinateSequence.back().back() );
605  }
606 
607  return mCoordinateSequence;
608 }
609 
611 {
612  if ( !mCoordinateSequence.isEmpty() )
614 
615  int count = 0;
616 
617  if ( mExteriorRing )
618  {
619  count += mExteriorRing->nCoordinates();
620  }
621 
623  for ( ; it != mInteriorRings.constEnd(); ++it )
624  {
625  count += ( *it )->nCoordinates();
626  }
627 
628  return count;
629 }
630 
631 double QgsCurvePolygonV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const
632 {
633  if ( !mExteriorRing )
634  {
635  return -1;
636  }
637  QList<QgsCurveV2*> segmentList;
638  segmentList.append( mExteriorRing );
639  segmentList.append( mInteriorRings );
640  return QgsGeometryUtils::closestSegmentFromComponents( segmentList, QgsGeometryUtils::RING, pt, segmentPt, vertexAfter, leftOf, epsilon );
641 }
642 
644 {
645  if ( !mExteriorRing || vId.ring >= 1 + mInteriorRings.size() )
646  {
647  return false;
648  }
649 
650  if ( vId.ring < 0 )
651  {
652  vId.ring = 0;
653  vId.vertex = -1;
654  if ( vId.part < 0 )
655  {
656  vId.part = 0;
657  }
658  return mExteriorRing->nextVertex( vId, vertex );
659  }
660  else
661  {
662  QgsCurveV2* ring = vId.ring == 0 ? mExteriorRing : mInteriorRings[vId.ring - 1];
663 
664  if ( ring->nextVertex( vId, vertex ) )
665  {
666  return true;
667  }
668  ++vId.ring;
669  vId.vertex = -1;
670  if ( vId.ring >= 1 + mInteriorRings.size() )
671  {
672  return false;
673  }
674  ring = mInteriorRings[ vId.ring - 1 ];
675  return ring->nextVertex( vId, vertex );
676  }
677 }
678 
680 {
681  if ( !mExteriorRing || vId.ring < 0 || vId.ring >= 1 + mInteriorRings.size() )
682  {
683  return false;
684  }
685 
686  QgsCurveV2* ring = vId.ring == 0 ? mExteriorRing : mInteriorRings.at( vId.ring - 1 );
687  int n = ring->numPoints();
688  bool success = ring->insertVertex( QgsVertexId( 0, 0, vId.vertex ), vertex );
689  if ( !success )
690  {
691  return false;
692  }
693 
694  // If first or last vertex is inserted, re-sync the last/first vertex
695  if ( vId.vertex == 0 )
696  ring->moveVertex( QgsVertexId( 0, 0, n ), vertex );
697  else if ( vId.vertex == n )
698  ring->moveVertex( QgsVertexId( 0, 0, 0 ), vertex );
699 
700  clearCache();
701 
702  return true;
703 }
704 
706 {
707  if ( !mExteriorRing || vId.ring < 0 || vId.ring >= 1 + mInteriorRings.size() )
708  {
709  return false;
710  }
711 
712  QgsCurveV2* ring = vId.ring == 0 ? mExteriorRing : mInteriorRings.at( vId.ring - 1 );
713  int n = ring->numPoints();
714  bool success = ring->moveVertex( vId, newPos );
715  if ( success )
716  {
717  // If first or last vertex is moved, also move the last/first vertex
718  if ( vId.vertex == 0 )
719  ring->moveVertex( QgsVertexId( vId.part, vId.ring, n - 1 ), newPos );
720  else if ( vId.vertex == n - 1 )
721  ring->moveVertex( QgsVertexId( vId.part, vId.ring, 0 ), newPos );
722  clearCache();
723  }
724  return success;
725 }
726 
728 {
729  if ( !mExteriorRing || vId.ring < 0 || vId.ring >= 1 + mInteriorRings.size() )
730  {
731  return false;
732  }
733 
734  QgsCurveV2* ring = vId.ring == 0 ? mExteriorRing : mInteriorRings.at( vId.ring - 1 );
735  int n = ring->numPoints();
736  if ( n <= 4 )
737  {
738  //no points will be left in ring, so remove whole ring
739  if ( vId.ring == 0 )
740  {
741  delete mExteriorRing;
742  mExteriorRing = nullptr;
743  if ( !mInteriorRings.isEmpty() )
744  {
746  }
747  }
748  else
749  {
750  removeInteriorRing( vId.ring - 1 );
751  }
752  clearCache();
753  return true;
754  }
755 
756  bool success = ring->deleteVertex( vId );
757  if ( success )
758  {
759  // If first or last vertex is removed, re-sync the last/first vertex
760  if ( vId.vertex == 0 )
761  ring->moveVertex( QgsVertexId( 0, 0, n - 2 ), ring->vertexAt( QgsVertexId( 0, 0, 0 ) ) );
762  else if ( vId.vertex == n - 1 )
763  ring->moveVertex( QgsVertexId( 0, 0, 0 ), ring->vertexAt( QgsVertexId( 0, 0, n - 2 ) ) );
764  clearCache();
765  }
766  return success;
767 }
768 
770 {
772  {
773  return true;
774  }
775 
777  for ( ; it != mInteriorRings.constEnd(); ++it )
778  {
779  if (( *it )->hasCurvedSegments() )
780  {
781  return true;
782  }
783  }
784  return false;
785 }
786 
788 {
789  return toPolygon();
790 }
791 
793 {
794  if ( !mExteriorRing || vertex.ring < 0 || vertex.ring >= 1 + mInteriorRings.size() )
795  {
796  //makes no sense - conversion of false to double!
797  return false;
798  }
799 
800  QgsCurveV2* ring = vertex.ring == 0 ? mExteriorRing : mInteriorRings[vertex.ring - 1];
801  return ring->vertexAngle( vertex );
802 }
803 
804 int QgsCurvePolygonV2::vertexCount( int /*part*/, int ring ) const
805 {
806  return ring == 0 ? mExteriorRing->vertexCount() : mInteriorRings[ring - 1]->vertexCount();
807 }
808 
810 {
811  return id.ring == 0 ? mExteriorRing->vertexAt( id ) : mInteriorRings[id.ring - 1]->vertexAt( id );
812 }
813 
814 bool QgsCurvePolygonV2::addZValue( double zValue )
815 {
816  if ( QgsWKBTypes::hasZ( mWkbType ) )
817  return false;
818 
820 
821  if ( mExteriorRing )
822  mExteriorRing->addZValue( zValue );
823  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
824  {
825  curve->addZValue( zValue );
826  }
827  clearCache();
828  return true;
829 }
830 
831 bool QgsCurvePolygonV2::addMValue( double mValue )
832 {
833  if ( QgsWKBTypes::hasM( mWkbType ) )
834  return false;
835 
837 
838  if ( mExteriorRing )
839  mExteriorRing->addMValue( mValue );
840  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
841  {
842  curve->addMValue( mValue );
843  }
844  clearCache();
845  return true;
846 }
847 
849 {
850  if ( !is3D() )
851  return false;
852 
854  if ( mExteriorRing )
856  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
857  {
858  curve->dropZValue();
859  }
860  clearCache();
861  return true;
862 }
863 
865 {
866  if ( !isMeasure() )
867  return false;
868 
870  if ( mExteriorRing )
872  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
873  {
874  curve->dropMValue();
875  }
876  clearCache();
877  return true;
878 }
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 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:746
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:703
Circular string geometry type.
QgsPolygonV2 * surfaceToPolygon() const override
void reserve(int alloc)
virtual bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
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:656
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:40
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:45
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:800
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.
virtual QString geometryType() const override
Returns a unique string representing the geometry type.
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:770
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
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 void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform)=0
Transforms the geometry using a coordinate transform.
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.
void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform) override
Transforms the geometry using a coordinate transform.
virtual bool nextVertex(QgsVertexId &id, QgsPointV2 &vertex) const override
Returns next vertex id and coordinates.
Definition: qgscurvev2.cpp:57
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:47
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:817
bool nextVertex(QgsVertexId &id, QgsPointV2 &vertex) const override
Returns next vertex id and coordinates.
QList< QgsCurveV2 * > mInteriorRings
virtual QgsLineStringV2 * curveToLine() const =0
Returns a new line string geometry corresponding to a segmentized approximation of the curve...
QString asJSON(int precision=17) const override
Returns a GeoJSON representation of the geometry.
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 double length() const
Returns the length of the geometry.
virtual QgsPolygonV2 * toPolygon() const
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.
static Type parseType(const QString &wktStr)
Attempts to extract the WKB type from a WKT string.
Definition: qgswkbtypes.cpp:32
QgsAbstractGeometryV2 * segmentize() const override
Returns a version of the geometry without curves.
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:87
Curve polygon geometry type.
QgsWKBTypes::Type readHeader() const
Definition: qgswkbptr.cpp:37
virtual QDomElement asGML2(QDomDocument &doc, int precision=17, const QString &ns="gml") const =0
Returns a GML2 representation of the geometry.
const_iterator constEnd() const
const_iterator constBegin() const
Abstract base class for curved geometry type.
Definition: qgscurvev2.h:32
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:106
virtual double area() const override
Returns the area of the geometry.
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:95
QList< QgsPointV2 > QgsPointSequenceV2
virtual QgsPointV2 vertexAt(QgsVertexId id) const override
Returns the point corresponding to a specified vertex id.
QgsCurveV2 * mExteriorRing
int numInteriorRings() const