QGIS API Documentation  2.14.18-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  QgsWKBTypes::Type flatCurveType = QgsWKBTypes::flatType( childParts.first );
162  if ( flatCurveType == QgsWKBTypes::LineString )
164  else if ( flatCurveType == QgsWKBTypes::CircularString )
166  else if ( flatCurveType == QgsWKBTypes::CompoundCurve )
168  else
169  {
170  clear();
171  return false;
172  }
173  if ( !mInteriorRings.back()->fromWkt( childWkt ) )
174  {
175  clear();
176  return false;
177  }
178  }
179 
180  if ( mInteriorRings.isEmpty() )
181  {
182  clear();
183  return false;
184  }
185 
188 
189  //scan through rings and check if dimensionality of rings is different to CurvePolygon.
190  //if so, update the type dimensionality of the CurvePolygon to match
191  bool hasZ = false;
192  bool hasM = false;
193  if ( mExteriorRing )
194  {
195  hasZ = hasZ || mExteriorRing->is3D();
196  hasM = hasM || mExteriorRing->isMeasure();
197  }
198  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
199  {
200  hasZ = hasZ || curve->is3D();
201  hasM = hasM || curve->isMeasure();
202  if ( hasZ && hasM )
203  break;
204  }
205  if ( hasZ )
206  addZValue( 0 );
207  if ( hasM )
208  addMValue( 0 );
209 
210  return true;
211 }
212 
214 {
215  if ( mExteriorRing )
216  {
217  return mExteriorRing->boundingBox();
218  }
219  return QgsRectangle();
220 }
221 
223 {
224  int size = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 );
225  if ( mExteriorRing )
226  {
227  size += mExteriorRing->wkbSize();
228  }
229  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
230  {
231  size += curve->wkbSize();
232  }
233  return size;
234 }
235 
236 unsigned char* QgsCurvePolygonV2::asWkb( int& binarySize ) const
237 {
238  binarySize = wkbSize();
239  unsigned char* geomPtr = new unsigned char[binarySize];
240  QgsWkbPtr wkbPtr( geomPtr, binarySize );
241  wkbPtr << static_cast<char>( QgsApplication::endian() );
242  wkbPtr << static_cast<quint32>( wkbType() );
243  wkbPtr << static_cast<quint32>(( nullptr != mExteriorRing ) + mInteriorRings.size() );
244  if ( mExteriorRing )
245  {
246  int curveWkbLen = 0;
247  unsigned char *ringWkb = mExteriorRing->asWkb( curveWkbLen );
248  memcpy( wkbPtr, ringWkb, curveWkbLen );
249  wkbPtr += curveWkbLen;
250  }
251  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
252  {
253  int curveWkbLen = 0;
254  unsigned char *ringWkb = curve->asWkb( curveWkbLen );
255  memcpy( wkbPtr, ringWkb, curveWkbLen );
256  wkbPtr += curveWkbLen;
257  }
258  return geomPtr;
259 }
260 
261 QString QgsCurvePolygonV2::asWkt( int precision ) const
262 {
263  QString wkt = wktTypeStr() + " (";
264  if ( mExteriorRing )
265  {
266  QString childWkt = mExteriorRing->asWkt( precision );
267  if ( dynamic_cast<QgsLineStringV2*>( mExteriorRing ) )
268  {
269  // Type names of linear geometries are omitted
270  childWkt = childWkt.mid( childWkt.indexOf( '(' ) );
271  }
272  wkt += childWkt + ',';
273  }
274  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
275  {
276  QString childWkt = curve->asWkt( precision );
277  if ( dynamic_cast<const QgsLineStringV2*>( curve ) )
278  {
279  // Type names of linear geometries are omitted
280  childWkt = childWkt.mid( childWkt.indexOf( '(' ) );
281  }
282  wkt += childWkt + ',';
283  }
284  if ( wkt.endsWith( ',' ) )
285  {
286  wkt.chop( 1 ); // Remove last ','
287  }
288  wkt += ')';
289  return wkt;
290 }
291 
292 QDomElement QgsCurvePolygonV2::asGML2( QDomDocument& doc, int precision, const QString& ns ) const
293 {
294  // GML2 does not support curves
295  QDomElement elemPolygon = doc.createElementNS( ns, "Polygon" );
296  QDomElement elemOuterBoundaryIs = doc.createElementNS( ns, "outerBoundaryIs" );
297  QgsLineStringV2* exteriorLineString = exteriorRing()->curveToLine();
298  QDomElement outerRing = exteriorLineString->asGML2( doc, precision, ns );
299  outerRing.toElement().setTagName( "LinearRing" );
300  elemOuterBoundaryIs.appendChild( outerRing );
301  delete exteriorLineString;
302  elemPolygon.appendChild( elemOuterBoundaryIs );
303  for ( int i = 0, n = numInteriorRings(); i < n; ++i )
304  {
305  QDomElement elemInnerBoundaryIs = doc.createElementNS( ns, "innerBoundaryIs" );
306  QgsLineStringV2* interiorLineString = interiorRing( i )->curveToLine();
307  QDomElement innerRing = interiorLineString->asGML2( doc, precision, ns );
308  innerRing.toElement().setTagName( "LinearRing" );
309  elemInnerBoundaryIs.appendChild( innerRing );
310  delete interiorLineString;
311  elemPolygon.appendChild( elemInnerBoundaryIs );
312  }
313  return elemPolygon;
314 }
315 
316 QDomElement QgsCurvePolygonV2::asGML3( QDomDocument& doc, int precision, const QString& ns ) const
317 {
318  QDomElement elemCurvePolygon = doc.createElementNS( ns, "Polygon" );
319  QDomElement elemExterior = doc.createElementNS( ns, "exterior" );
320  QDomElement curveElem = exteriorRing()->asGML3( doc, precision, ns );
321  if ( curveElem.tagName() == "LineString" )
322  {
323  curveElem.setTagName( "LinearRing" );
324  }
325  elemExterior.appendChild( curveElem );
326  elemCurvePolygon.appendChild( elemExterior );
327 
328  for ( int i = 0, n = numInteriorRings(); i < n; ++i )
329  {
330  QDomElement elemInterior = doc.createElementNS( ns, "interior" );
331  QDomElement innerRing = interiorRing( i )->asGML3( doc, precision, ns );
332  if ( innerRing.tagName() == "LineString" )
333  {
334  innerRing.setTagName( "LinearRing" );
335  }
336  elemInterior.appendChild( innerRing );
337  elemCurvePolygon.appendChild( elemInterior );
338  }
339  return elemCurvePolygon;
340 }
341 
342 QString QgsCurvePolygonV2::asJSON( int precision ) const
343 {
344  // GeoJSON does not support curves
345  QString json = "{\"type\": \"Polygon\", \"coordinates\": [";
346 
347  QgsLineStringV2* exteriorLineString = exteriorRing()->curveToLine();
348  QgsPointSequenceV2 exteriorPts;
349  exteriorLineString->points( exteriorPts );
350  json += QgsGeometryUtils::pointsToJSON( exteriorPts, precision ) + ", ";
351  delete exteriorLineString;
352 
353  for ( int i = 0, n = numInteriorRings(); i < n; ++i )
354  {
355  QgsLineStringV2* interiorLineString = interiorRing( i )->curveToLine();
356  QgsPointSequenceV2 interiorPts;
357  interiorLineString->points( interiorPts );
358  json += QgsGeometryUtils::pointsToJSON( interiorPts, precision ) + ", ";
359  delete interiorLineString;
360  }
361  if ( json.endsWith( ", " ) )
362  {
363  json.chop( 2 ); // Remove last ", "
364  }
365  json += "] }";
366  return json;
367 }
368 
370 {
371  if ( !mExteriorRing )
372  {
373  return 0.0;
374  }
375 
376  double totalArea = 0.0;
377 
378  if ( mExteriorRing->isRing() )
379  {
380  double area = 0.0;
381  mExteriorRing->sumUpArea( area );
382  totalArea += qAbs( area );
383  }
384 
386  for ( ; ringIt != mInteriorRings.constEnd(); ++ringIt )
387  {
388  double area = 0.0;
389  if (( *ringIt )->isRing() )
390  {
391  ( *ringIt )->sumUpArea( area );
392  totalArea -= qAbs( area );
393  }
394  }
395  return totalArea;
396 }
397 
399 {
400  if ( !mExteriorRing )
401  return 0.0;
402 
403  //sum perimeter of rings
404  double perimeter = mExteriorRing->length();
406  for ( ; ringIt != mInteriorRings.constEnd(); ++ringIt )
407  {
408  perimeter += ( *ringIt )->length();
409  }
410  return perimeter;
411 }
412 
414 {
415  QgsPolygonV2* polygon = new QgsPolygonV2();
416  polygon->setExteriorRing( exteriorRing()->curveToLine() );
417  QList<QgsCurveV2*> interiors;
418  int n = numInteriorRings();
419  interiors.reserve( n );
420  for ( int i = 0; i < n; ++i )
421  {
422  interiors.append( interiorRing( i )->curveToLine() );
423  }
424  polygon->setInteriorRings( interiors );
425  return polygon;
426 }
427 
429 {
430  if ( !mExteriorRing )
431  {
432  return nullptr;
433  }
434 
435  QgsPolygonV2* poly = new QgsPolygonV2();
437 
438  QList<QgsCurveV2*> rings;
440  for ( ; it != mInteriorRings.constEnd(); ++it )
441  {
442  rings.push_back(( *it )->curveToLine() );
443  }
444  poly->setInteriorRings( rings );
445  return poly;
446 }
447 
449 {
450  return mInteriorRings.size();
451 }
452 
454 {
455  return mExteriorRing;
456 }
457 
459 {
460  if ( i < 0 || i >= mInteriorRings.size() )
461  {
462  return nullptr;
463  }
464  return mInteriorRings.at( i );
465 }
466 
468 {
469  if ( !ring )
470  {
471  return;
472  }
473  delete mExteriorRing;
474  mExteriorRing = ring;
475 
476  //set proper wkb type
477  if ( geometryType() == "Polygon" )
478  {
480  }
481  else if ( geometryType() == "CurvePolygon" )
482  {
484  }
485 
486  //match dimensionality for rings
487  Q_FOREACH ( QgsCurveV2* ring, mInteriorRings )
488  {
489  if ( is3D() )
490  ring->addZValue();
491  else
492  ring->dropZValue();
493 
494  if ( isMeasure() )
495  ring->addMValue();
496  else
497  ring->dropMValue();
498  }
499  clearCache();
500 }
501 
503 {
504  qDeleteAll( mInteriorRings );
506 
507  //add rings one-by-one, so that they can each be converted to the correct type for the CurvePolygon
508  Q_FOREACH ( QgsCurveV2* ring, rings )
509  {
510  addInteriorRing( ring );
511  }
512  clearCache();
513 }
514 
516 {
517  if ( !ring )
518  return;
519 
520  //ensure dimensionality of ring matches curve polygon
521  if ( !is3D() )
522  ring->dropZValue();
523  else if ( !ring->is3D() )
524  ring->addZValue();
525 
526  if ( !isMeasure() )
527  ring->dropMValue();
528  else if ( !ring->isMeasure() )
529  ring->addMValue();
530 
531  mInteriorRings.append( ring );
532  clearCache();
533 }
534 
536 {
537  if ( nr < 0 || nr >= mInteriorRings.size() )
538  {
539  return false;
540  }
541  delete mInteriorRings.takeAt( nr );
542  clearCache();
543  return true;
544 }
545 
547 {
548  if ( mInteriorRings.size() < 1 )
549  {
550  if ( mExteriorRing )
551  {
553  }
554  }
555  else
556  {
557  QPainterPath path;
559 
561  for ( ; it != mInteriorRings.constEnd(); ++it )
562  {
563  ( *it )->addToPainterPath( path );
564  }
565  p.drawPath( path );
566  }
567 }
568 
570 {
571  if ( mExteriorRing )
572  {
573  mExteriorRing->transform( ct, d );
574  }
575 
576  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
577  {
578  curve->transform( ct, d );
579  }
580  clearCache();
581 }
582 
584 {
585  if ( mExteriorRing )
586  {
587  mExteriorRing->transform( t );
588  }
589 
590  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
591  {
592  curve->transform( t );
593  }
594  clearCache();
595 }
596 
598 {
599  if ( !mCoordinateSequence.isEmpty() )
600  return mCoordinateSequence;
601 
603 
604  if ( mExteriorRing )
605  {
608  }
609 
611  for ( ; it != mInteriorRings.constEnd(); ++it )
612  {
614  ( *it )->points( mCoordinateSequence.back().back() );
615  }
616 
617  return mCoordinateSequence;
618 }
619 
621 {
622  if ( !mCoordinateSequence.isEmpty() )
624 
625  int count = 0;
626 
627  if ( mExteriorRing )
628  {
629  count += mExteriorRing->nCoordinates();
630  }
631 
633  for ( ; it != mInteriorRings.constEnd(); ++it )
634  {
635  count += ( *it )->nCoordinates();
636  }
637 
638  return count;
639 }
640 
641 double QgsCurvePolygonV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const
642 {
643  if ( !mExteriorRing )
644  {
645  return -1;
646  }
647  QList<QgsCurveV2*> segmentList;
648  segmentList.append( mExteriorRing );
649  segmentList.append( mInteriorRings );
650  return QgsGeometryUtils::closestSegmentFromComponents( segmentList, QgsGeometryUtils::RING, pt, segmentPt, vertexAfter, leftOf, epsilon );
651 }
652 
654 {
655  if ( !mExteriorRing || vId.ring >= 1 + mInteriorRings.size() )
656  {
657  return false;
658  }
659 
660  if ( vId.ring < 0 )
661  {
662  vId.ring = 0;
663  vId.vertex = -1;
664  if ( vId.part < 0 )
665  {
666  vId.part = 0;
667  }
668  return mExteriorRing->nextVertex( vId, vertex );
669  }
670  else
671  {
672  QgsCurveV2* ring = vId.ring == 0 ? mExteriorRing : mInteriorRings[vId.ring - 1];
673 
674  if ( ring->nextVertex( vId, vertex ) )
675  {
676  return true;
677  }
678  ++vId.ring;
679  vId.vertex = -1;
680  if ( vId.ring >= 1 + mInteriorRings.size() )
681  {
682  return false;
683  }
684  ring = mInteriorRings[ vId.ring - 1 ];
685  return ring->nextVertex( vId, vertex );
686  }
687 }
688 
690 {
691  if ( !mExteriorRing || vId.ring < 0 || vId.ring >= 1 + mInteriorRings.size() )
692  {
693  return false;
694  }
695 
696  QgsCurveV2* ring = vId.ring == 0 ? mExteriorRing : mInteriorRings.at( vId.ring - 1 );
697  int n = ring->numPoints();
698  bool success = ring->insertVertex( QgsVertexId( 0, 0, vId.vertex ), vertex );
699  if ( !success )
700  {
701  return false;
702  }
703 
704  // If first or last vertex is inserted, re-sync the last/first vertex
705  if ( vId.vertex == 0 )
706  ring->moveVertex( QgsVertexId( 0, 0, n ), vertex );
707  else if ( vId.vertex == n )
708  ring->moveVertex( QgsVertexId( 0, 0, 0 ), vertex );
709 
710  clearCache();
711 
712  return true;
713 }
714 
716 {
717  if ( !mExteriorRing || vId.ring < 0 || vId.ring >= 1 + mInteriorRings.size() )
718  {
719  return false;
720  }
721 
722  QgsCurveV2* ring = vId.ring == 0 ? mExteriorRing : mInteriorRings.at( vId.ring - 1 );
723  int n = ring->numPoints();
724  bool success = ring->moveVertex( vId, newPos );
725  if ( success )
726  {
727  // If first or last vertex is moved, also move the last/first vertex
728  if ( vId.vertex == 0 )
729  ring->moveVertex( QgsVertexId( vId.part, vId.ring, n - 1 ), newPos );
730  else if ( vId.vertex == n - 1 )
731  ring->moveVertex( QgsVertexId( vId.part, vId.ring, 0 ), newPos );
732  clearCache();
733  }
734  return success;
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  if ( n <= 4 )
747  {
748  //no points will be left in ring, so remove whole ring
749  if ( vId.ring == 0 )
750  {
751  delete mExteriorRing;
752  mExteriorRing = nullptr;
753  if ( !mInteriorRings.isEmpty() )
754  {
756  }
757  }
758  else
759  {
760  removeInteriorRing( vId.ring - 1 );
761  }
762  clearCache();
763  return true;
764  }
765 
766  bool success = ring->deleteVertex( vId );
767  if ( success )
768  {
769  // If first or last vertex is removed, re-sync the last/first vertex
770  if ( vId.vertex == 0 )
771  ring->moveVertex( QgsVertexId( 0, 0, n - 2 ), ring->vertexAt( QgsVertexId( 0, 0, 0 ) ) );
772  else if ( vId.vertex == n - 1 )
773  ring->moveVertex( QgsVertexId( 0, 0, 0 ), ring->vertexAt( QgsVertexId( 0, 0, n - 2 ) ) );
774  clearCache();
775  }
776  return success;
777 }
778 
780 {
782  {
783  return true;
784  }
785 
787  for ( ; it != mInteriorRings.constEnd(); ++it )
788  {
789  if (( *it )->hasCurvedSegments() )
790  {
791  return true;
792  }
793  }
794  return false;
795 }
796 
798 {
799  return toPolygon();
800 }
801 
803 {
804  if ( !mExteriorRing || vertex.ring < 0 || vertex.ring >= 1 + mInteriorRings.size() )
805  {
806  //makes no sense - conversion of false to double!
807  return false;
808  }
809 
810  QgsCurveV2* ring = vertex.ring == 0 ? mExteriorRing : mInteriorRings[vertex.ring - 1];
811  return ring->vertexAngle( vertex );
812 }
813 
814 int QgsCurvePolygonV2::vertexCount( int /*part*/, int ring ) const
815 {
816  return ring == 0 ? mExteriorRing->vertexCount() : mInteriorRings[ring - 1]->vertexCount();
817 }
818 
820 {
821  return id.ring == 0 ? mExteriorRing->vertexAt( id ) : mInteriorRings[id.ring - 1]->vertexAt( id );
822 }
823 
824 bool QgsCurvePolygonV2::addZValue( double zValue )
825 {
826  if ( QgsWKBTypes::hasZ( mWkbType ) )
827  return false;
828 
830 
831  if ( mExteriorRing )
832  mExteriorRing->addZValue( zValue );
833  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
834  {
835  curve->addZValue( zValue );
836  }
837  clearCache();
838  return true;
839 }
840 
841 bool QgsCurvePolygonV2::addMValue( double mValue )
842 {
843  if ( QgsWKBTypes::hasM( mWkbType ) )
844  return false;
845 
847 
848  if ( mExteriorRing )
849  mExteriorRing->addMValue( mValue );
850  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
851  {
852  curve->addMValue( mValue );
853  }
854  clearCache();
855  return true;
856 }
857 
859 {
860  if ( !is3D() )
861  return false;
862 
864  if ( mExteriorRing )
866  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
867  {
868  curve->dropZValue();
869  }
870  clearCache();
871  return true;
872 }
873 
875 {
876  if ( !isMeasure() )
877  return false;
878 
880  if ( mExteriorRing )
882  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
883  {
884  curve->dropMValue();
885  }
886  clearCache();
887  return true;
888 }
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 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: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
QString tagName() const
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
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