QGIS API Documentation  2.14.11-Essen
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 
39 QgsCurvePolygonV2::QgsCurvePolygonV2( const QgsCurvePolygonV2& p ) : QgsSurfaceV2( p ), mExteriorRing( nullptr )
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 }
const QgsCurveV2 * exteriorRing() const
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
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
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 (...
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.
virtual double length() const
Returns the length of the geometry.
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.
const T & at(int i) const
virtual bool isRing() const
Returns true if the curve is a ring.
Definition: qgscurvev2.cpp:40
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.
TransformDirection
Enum used to indicate the direction (forward or inverse) of the transform.
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.
QString wktTypeStr() const
Returns the WKT type string of the geometry.
virtual int wkbSize() const =0
Returns the size of the WKB representation of the geometry.
virtual int nCoordinates() const
Returns the number of nodes contained in 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.
QgsWKBTypes::Type readHeader() const
Definition: qgswkbptr.cpp:37
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.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
void setInteriorRings(const QList< QgsCurveV2 * > &rings)
Sets all interior rings (takes ownership)
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.
bool isMeasure() const
Returns true if the geometry contains m values.
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.
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 bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
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() 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
const QgsCurveV2 * interiorRing(int i) const
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.
virtual bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
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 'thepoint' is left or right of the line from 'p1' to 'p2'.
virtual QgsPointV2 vertexAt(QgsVertexId id) const override
Returns the point corresponding to a specified vertex id.
Definition: qgscurvev2.cpp:87
Curve polygon geometry type.
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
int numInteriorRings() 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.
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