QGIS API Documentation  2.14.0-Essen
qgscurvepolygonv2.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscurvepolygonv2.cpp
3  ---------------------
4  begin : September 2014
5  copyright : (C) 2014 by Marco Hugentobler
6  email : marco at sourcepole dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgscurvepolygonv2.h"
19 #include "qgsapplication.h"
20 #include "qgscircularstringv2.h"
21 #include "qgscompoundcurvev2.h"
22 #include "qgsgeometryutils.h"
23 #include "qgslinestringv2.h"
24 #include "qgspolygonv2.h"
25 #include "qgswkbptr.h"
26 #include <QPainter>
27 #include <QPainterPath>
28 
29 QgsCurvePolygonV2::QgsCurvePolygonV2(): QgsSurfaceV2(), mExteriorRing( nullptr )
30 {
31 
32 }
33 
35 {
36  clear();
37 }
38 
40 {
41  if ( p.mExteriorRing )
42  {
43  mExteriorRing = static_cast<QgsCurveV2*>( p.mExteriorRing->clone() );
44  }
45 
46  Q_FOREACH ( const QgsCurveV2* ring, p.mInteriorRings )
47  {
48  mInteriorRings.push_back( static_cast<QgsCurveV2*>( ring->clone() ) );
49  }
50 }
51 
53 {
54  if ( &p != this )
55  {
56  clearCache();
58  if ( p.mExteriorRing )
59  {
60  mExteriorRing = static_cast<QgsCurveV2*>( p.mExteriorRing->clone() );
61  }
62 
63  Q_FOREACH ( const QgsCurveV2* ring, p.mInteriorRings )
64  {
65  mInteriorRings.push_back( static_cast<QgsCurveV2*>( ring->clone() ) );
66  }
67  }
68  return *this;
69 }
70 
72 {
73  return new QgsCurvePolygonV2( *this );
74 }
75 
77 {
78  delete mExteriorRing;
79  mExteriorRing = nullptr;
80  qDeleteAll( mInteriorRings );
83  clearCache();
84 }
85 
86 
88 {
89  clear();
90  if ( !wkbPtr )
91  {
92  return false;
93  }
94 
95  QgsWKBTypes::Type type = wkbPtr.readHeader();
97  {
98  return false;
99  }
100  mWkbType = type;
101 
102  int nRings;
103  wkbPtr >> nRings;
104  QgsCurveV2* currentCurve = nullptr;
105  int currentCurveSize = 0;
106  for ( int i = 0; i < nRings; ++i )
107  {
108  QgsWKBTypes::Type curveType = wkbPtr.readHeader();
109  wkbPtr -= 1 + sizeof( int );
110  if ( curveType == QgsWKBTypes::LineString || curveType == QgsWKBTypes::LineStringZ || curveType == QgsWKBTypes::LineStringM ||
111  curveType == QgsWKBTypes::LineStringZM || curveType == QgsWKBTypes::LineString25D )
112  {
113  currentCurve = new QgsLineStringV2();
114  }
115  else if ( curveType == QgsWKBTypes::CircularString || curveType == QgsWKBTypes::CircularStringZ || curveType == QgsWKBTypes::CircularStringZM ||
116  curveType == QgsWKBTypes::CircularStringM )
117  {
118  currentCurve = new QgsCircularStringV2();
119  }
120  else if ( curveType == QgsWKBTypes::CompoundCurve || curveType == QgsWKBTypes::CompoundCurveZ || curveType == QgsWKBTypes::CompoundCurveZM )
121  {
122  currentCurve = new QgsCompoundCurveV2();
123  }
124  else
125  {
126  return false;
127  }
128  currentCurve->fromWkb( wkbPtr );
129  currentCurveSize = currentCurve->wkbSize();
130  if ( i == 0 )
131  {
132  mExteriorRing = currentCurve;
133  }
134  else
135  {
136  mInteriorRings.append( currentCurve );
137  }
138  wkbPtr += currentCurveSize;
139  }
140 
141  return true;
142 }
143 
145 {
146  clear();
147 
149 
150  if ( QgsWKBTypes::flatType( parts.first ) != QgsWKBTypes::parseType( geometryType() ) )
151  return false;
152 
153  mWkbType = parts.first;
154 
155  QString defaultChildWkbType = QString( "LineString%1%2" ).arg( is3D() ? "Z" : "", isMeasure() ? "M" : "" );
156 
157  Q_FOREACH ( const QString& childWkt, QgsGeometryUtils::wktGetChildBlocks( parts.second, defaultChildWkbType ) )
158  {
160 
161  if ( QgsWKBTypes::flatType( childParts.first ) == QgsWKBTypes::LineString )
163  else if ( QgsWKBTypes::flatType( childParts.first ) == QgsWKBTypes::CircularString )
165  else
166  {
167  clear();
168  return false;
169  }
170  if ( !mInteriorRings.back()->fromWkt( childWkt ) )
171  {
172  clear();
173  return false;
174  }
175  }
176 
177  if ( mInteriorRings.isEmpty() )
178  {
179  clear();
180  return false;
181  }
182 
185 
186  //scan through rings and check if dimensionality of rings is different to CurvePolygon.
187  //if so, update the type dimensionality of the CurvePolygon to match
188  bool hasZ = false;
189  bool hasM = false;
190  if ( mExteriorRing )
191  {
192  hasZ = hasZ || mExteriorRing->is3D();
193  hasM = hasM || mExteriorRing->isMeasure();
194  }
195  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
196  {
197  hasZ = hasZ || curve->is3D();
198  hasM = hasM || curve->isMeasure();
199  if ( hasZ && hasM )
200  break;
201  }
202  if ( hasZ )
203  addZValue( 0 );
204  if ( hasM )
205  addMValue( 0 );
206 
207  return true;
208 }
209 
211 {
212  if ( mExteriorRing )
213  {
214  return mExteriorRing->boundingBox();
215  }
216  return QgsRectangle();
217 }
218 
220 {
221  int size = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 );
222  if ( mExteriorRing )
223  {
224  size += mExteriorRing->wkbSize();
225  }
226  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
227  {
228  size += curve->wkbSize();
229  }
230  return size;
231 }
232 
233 unsigned char* QgsCurvePolygonV2::asWkb( int& binarySize ) const
234 {
235  binarySize = wkbSize();
236  unsigned char* geomPtr = new unsigned char[binarySize];
237  QgsWkbPtr wkbPtr( geomPtr, binarySize );
238  wkbPtr << static_cast<char>( QgsApplication::endian() );
239  wkbPtr << static_cast<quint32>( wkbType() );
240  wkbPtr << static_cast<quint32>(( nullptr != mExteriorRing ) + mInteriorRings.size() );
241  if ( mExteriorRing )
242  {
243  int curveWkbLen = 0;
244  unsigned char *ringWkb = mExteriorRing->asWkb( curveWkbLen );
245  memcpy( wkbPtr, ringWkb, curveWkbLen );
246  wkbPtr += curveWkbLen;
247  }
248  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
249  {
250  int curveWkbLen = 0;
251  unsigned char *ringWkb = curve->asWkb( curveWkbLen );
252  memcpy( wkbPtr, ringWkb, curveWkbLen );
253  wkbPtr += curveWkbLen;
254  }
255  return geomPtr;
256 }
257 
258 QString QgsCurvePolygonV2::asWkt( int precision ) const
259 {
260  QString wkt = wktTypeStr() + " (";
261  if ( mExteriorRing )
262  {
263  QString childWkt = mExteriorRing->asWkt( precision );
264  if ( dynamic_cast<QgsLineStringV2*>( mExteriorRing ) )
265  {
266  // Type names of linear geometries are omitted
267  childWkt = childWkt.mid( childWkt.indexOf( '(' ) );
268  }
269  wkt += childWkt + ',';
270  }
271  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
272  {
273  QString childWkt = curve->asWkt( precision );
274  if ( dynamic_cast<const QgsLineStringV2*>( curve ) )
275  {
276  // Type names of linear geometries are omitted
277  childWkt = childWkt.mid( childWkt.indexOf( '(' ) );
278  }
279  wkt += childWkt + ',';
280  }
281  if ( wkt.endsWith( ',' ) )
282  {
283  wkt.chop( 1 ); // Remove last ','
284  }
285  wkt += ')';
286  return wkt;
287 }
288 
289 QDomElement QgsCurvePolygonV2::asGML2( QDomDocument& doc, int precision, const QString& ns ) const
290 {
291  // GML2 does not support curves
292  QDomElement elemPolygon = doc.createElementNS( ns, "Polygon" );
293  QDomElement elemOuterBoundaryIs = doc.createElementNS( ns, "outerBoundaryIs" );
294  QgsLineStringV2* exteriorLineString = exteriorRing()->curveToLine();
295  QDomElement outerRing = exteriorLineString->asGML2( doc, precision, ns );
296  outerRing.toElement().setTagName( "LinearRing" );
297  elemOuterBoundaryIs.appendChild( outerRing );
298  delete exteriorLineString;
299  elemPolygon.appendChild( elemOuterBoundaryIs );
300  QDomElement elemInnerBoundaryIs = doc.createElementNS( ns, "innerBoundaryIs" );
301  for ( int i = 0, n = numInteriorRings(); i < n; ++i )
302  {
303  QgsLineStringV2* interiorLineString = interiorRing( i )->curveToLine();
304  QDomElement innerRing = interiorLineString->asGML2( doc, precision, ns );
305  innerRing.toElement().setTagName( "LinearRing" );
306  elemInnerBoundaryIs.appendChild( innerRing );
307  delete interiorLineString;
308  }
309  elemPolygon.appendChild( elemInnerBoundaryIs );
310  return elemPolygon;
311 }
312 
313 QDomElement QgsCurvePolygonV2::asGML3( QDomDocument& doc, int precision, const QString& ns ) const
314 {
315  QDomElement elemCurvePolygon = doc.createElementNS( ns, "Polygon" );
316  QDomElement elemExterior = doc.createElementNS( ns, "exterior" );
317  QDomElement outerRing = exteriorRing()->asGML2( doc, precision, ns );
318  outerRing.toElement().setTagName( "LinearRing" );
319  elemExterior.appendChild( outerRing );
320  elemCurvePolygon.appendChild( elemExterior );
321  QDomElement elemInterior = doc.createElementNS( ns, "interior" );
322  for ( int i = 0, n = numInteriorRings(); i < n; ++i )
323  {
324  QDomElement innerRing = interiorRing( i )->asGML2( doc, precision, ns );
325  innerRing.toElement().setTagName( "LinearRing" );
326  elemInterior.appendChild( innerRing );
327  }
328  elemCurvePolygon.appendChild( elemInterior );
329  return elemCurvePolygon;
330 }
331 
332 QString QgsCurvePolygonV2::asJSON( int precision ) const
333 {
334  // GeoJSON does not support curves
335  QString json = "{\"type\": \"Polygon\", \"coordinates\": [";
336 
337  QgsLineStringV2* exteriorLineString = exteriorRing()->curveToLine();
338  QgsPointSequenceV2 exteriorPts;
339  exteriorLineString->points( exteriorPts );
340  json += QgsGeometryUtils::pointsToJSON( exteriorPts, precision ) + ", ";
341  delete exteriorLineString;
342 
343  for ( int i = 0, n = numInteriorRings(); i < n; ++i )
344  {
345  QgsLineStringV2* interiorLineString = interiorRing( i )->curveToLine();
346  QgsPointSequenceV2 interiorPts;
347  interiorLineString->points( interiorPts );
348  json += QgsGeometryUtils::pointsToJSON( interiorPts, precision ) + ", ";
349  delete interiorLineString;
350  }
351  if ( json.endsWith( ", " ) )
352  {
353  json.chop( 2 ); // Remove last ", "
354  }
355  json += "] }";
356  return json;
357 }
358 
360 {
361  if ( !mExteriorRing )
362  {
363  return 0.0;
364  }
365 
366  double totalArea = 0.0;
367 
368  if ( mExteriorRing->isClosed() )
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 )->isClosed() )
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 
610 double QgsCurvePolygonV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const
611 {
612  if ( !mExteriorRing )
613  {
614  return 0.0;
615  }
616  QList<QgsCurveV2*> segmentList;
617  segmentList.append( mExteriorRing );
618  segmentList.append( mInteriorRings );
619  return QgsGeometryUtils::closestSegmentFromComponents( segmentList, QgsGeometryUtils::RING, pt, segmentPt, vertexAfter, leftOf, epsilon );
620 }
621 
623 {
624  if ( !mExteriorRing || vId.ring >= 1 + mInteriorRings.size() )
625  {
626  return false;
627  }
628 
629  if ( vId.ring < 0 )
630  {
631  vId.ring = 0;
632  vId.vertex = -1;
633  if ( vId.part < 0 )
634  {
635  vId.part = 0;
636  }
637  return mExteriorRing->nextVertex( vId, vertex );
638  }
639  else
640  {
641  QgsCurveV2* ring = vId.ring == 0 ? mExteriorRing : mInteriorRings[vId.ring - 1];
642 
643  if ( ring->nextVertex( vId, vertex ) )
644  {
645  return true;
646  }
647  ++vId.ring;
648  vId.vertex = -1;
649  if ( vId.ring >= 1 + mInteriorRings.size() )
650  {
651  return false;
652  }
653  ring = mInteriorRings[ vId.ring - 1 ];
654  return ring->nextVertex( vId, vertex );
655  }
656 }
657 
659 {
660  if ( !mExteriorRing || vId.ring < 0 || vId.ring >= 1 + mInteriorRings.size() )
661  {
662  return false;
663  }
664 
665  QgsCurveV2* ring = vId.ring == 0 ? mExteriorRing : mInteriorRings.at( vId.ring - 1 );
666  int n = ring->numPoints();
667  bool success = ring->insertVertex( QgsVertexId( 0, 0, vId.vertex ), vertex );
668  if ( !success )
669  {
670  return false;
671  }
672 
673  // If first or last vertex is inserted, re-sync the last/first vertex
674  if ( vId.vertex == 0 )
675  ring->moveVertex( QgsVertexId( 0, 0, n ), vertex );
676  else if ( vId.vertex == n )
677  ring->moveVertex( QgsVertexId( 0, 0, 0 ), vertex );
678 
679  clearCache();
680 
681  return true;
682 }
683 
685 {
686  if ( !mExteriorRing || vId.ring < 0 || vId.ring >= 1 + mInteriorRings.size() )
687  {
688  return false;
689  }
690 
691  QgsCurveV2* ring = vId.ring == 0 ? mExteriorRing : mInteriorRings.at( vId.ring - 1 );
692  int n = ring->numPoints();
693  bool success = ring->moveVertex( vId, newPos );
694  if ( success )
695  {
696  // If first or last vertex is moved, also move the last/first vertex
697  if ( vId.vertex == 0 )
698  ring->moveVertex( QgsVertexId( vId.part, vId.ring, n - 1 ), newPos );
699  else if ( vId.vertex == n - 1 )
700  ring->moveVertex( QgsVertexId( vId.part, vId.ring, 0 ), newPos );
701  clearCache();
702  }
703  return success;
704 }
705 
707 {
708  if ( !mExteriorRing || vId.ring < 0 || vId.ring >= 1 + mInteriorRings.size() )
709  {
710  return false;
711  }
712 
713  QgsCurveV2* ring = vId.ring == 0 ? mExteriorRing : mInteriorRings.at( vId.ring - 1 );
714  int n = ring->numPoints();
715  if ( n <= 4 )
716  {
717  //no points will be left in ring, so remove whole ring
718  if ( vId.ring == 0 )
719  {
720  delete mExteriorRing;
721  mExteriorRing = nullptr;
722  if ( !mInteriorRings.isEmpty() )
723  {
725  }
726  }
727  else
728  {
729  removeInteriorRing( vId.ring - 1 );
730  }
731  clearCache();
732  return true;
733  }
734 
735  bool success = ring->deleteVertex( vId );
736  if ( success )
737  {
738  // If first or last vertex is removed, re-sync the last/first vertex
739  if ( vId.vertex == 0 )
740  ring->moveVertex( QgsVertexId( 0, 0, n - 2 ), ring->vertexAt( QgsVertexId( 0, 0, 0 ) ) );
741  else if ( vId.vertex == n - 1 )
742  ring->moveVertex( QgsVertexId( 0, 0, 0 ), ring->vertexAt( QgsVertexId( 0, 0, n - 2 ) ) );
743  clearCache();
744  }
745  return success;
746 }
747 
749 {
751  {
752  return true;
753  }
754 
756  for ( ; it != mInteriorRings.constEnd(); ++it )
757  {
758  if (( *it )->hasCurvedSegments() )
759  {
760  return true;
761  }
762  }
763  return false;
764 }
765 
767 {
768  return toPolygon();
769 }
770 
772 {
773  if ( !mExteriorRing || vertex.ring < 0 || vertex.ring >= 1 + mInteriorRings.size() )
774  {
775  //makes no sense - conversion of false to double!
776  return false;
777  }
778 
779  QgsCurveV2* ring = vertex.ring == 0 ? mExteriorRing : mInteriorRings[vertex.ring - 1];
780  return ring->vertexAngle( vertex );
781 }
782 
783 int QgsCurvePolygonV2::vertexCount( int /*part*/, int ring ) const
784 {
785  return ring == 0 ? mExteriorRing->vertexCount() : mInteriorRings[ring - 1]->vertexCount();
786 }
787 
789 {
790  return id.ring == 0 ? mExteriorRing->vertexAt( id ) : mInteriorRings[id.ring - 1]->vertexAt( id );
791 }
792 
793 bool QgsCurvePolygonV2::addZValue( double zValue )
794 {
795  if ( QgsWKBTypes::hasZ( mWkbType ) )
796  return false;
797 
799 
800  if ( mExteriorRing )
801  mExteriorRing->addZValue( zValue );
802  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
803  {
804  curve->addZValue( zValue );
805  }
806  clearCache();
807  return true;
808 }
809 
810 bool QgsCurvePolygonV2::addMValue( double mValue )
811 {
812  if ( QgsWKBTypes::hasM( mWkbType ) )
813  return false;
814 
816 
817  if ( mExteriorRing )
818  mExteriorRing->addMValue( mValue );
819  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
820  {
821  curve->addMValue( mValue );
822  }
823  clearCache();
824  return true;
825 }
826 
828 {
829  if ( !is3D() )
830  return false;
831 
833  if ( mExteriorRing )
835  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
836  {
837  curve->dropZValue();
838  }
839  clearCache();
840  return true;
841 }
842 
844 {
845  if ( !isMeasure() )
846  return false;
847 
849  if ( mExteriorRing )
851  Q_FOREACH ( QgsCurveV2* curve, mInteriorRings )
852  {
853  curve->dropMValue();
854  }
855  clearCache();
856  return true;
857 }
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.
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: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.
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
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: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 isClosed() const
Returns true if the curve is closed.
Definition: qgscurvev2.cpp:27
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 bool fromWkb(QgsConstWkbPtr wkb) override
Sets the geometry from a WKB string.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:366
virtual bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
virtual void drawAsPolygon(QPainter &p) const =0
Draws the curve as a polygon on the specified QPainter.
static Type parseType(const QString &wktStr)
Attempts to extract the WKB type from a WKT string.
Definition: qgswkbtypes.cpp:32
QgsAbstractGeometryV2 * segmentize() const override
Returns a version of the geometry without curves.
double ANALYSIS_EXPORT leftOf(Point3D *thepoint, Point3D *p1, Point3D *p2)
Returns whether &#39;thepoint&#39; is left or right of the line from &#39;p1&#39; to &#39;p2&#39;.
virtual QgsPointV2 vertexAt(QgsVertexId id) const override
Returns the point corresponding to a specified vertex id.
Definition: qgscurvev2.cpp:87
Curve polygon geometry type.
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:107
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