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