QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
qgsgeometrycollection.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgeometrycollection.cpp
3  -------------------------------------------------------------------
4 Date : 28 Oct 2014
5 Copyright : (C) 2014 by Marco Hugentobler
6 email : marco.hugentobler at sourcepole dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsgeometrycollection.h"
17 #include "qgsapplication.h"
18 #include "qgsgeometryfactory.h"
19 #include "qgsgeometryutils.h"
20 #include "qgscircularstring.h"
21 #include "qgscompoundcurve.h"
22 #include "qgslinestring.h"
23 #include "qgsmultilinestring.h"
24 #include "qgspoint.h"
25 #include "qgsmultipoint.h"
26 #include "qgspolygon.h"
27 #include "qgsmultipolygon.h"
28 #include "qgswkbptr.h"
29 #include "qgsgeos.h"
30 
31 #include <nlohmann/json.hpp>
32 #include <memory>
33 
35 {
37 }
38 
40 {
41  int nGeoms = c.mGeometries.size();
42  mGeometries.resize( nGeoms );
43  for ( int i = 0; i < nGeoms; ++i )
44  {
45  mGeometries[i] = c.mGeometries.at( i )->clone();
46  }
47 }
48 
50 {
51  if ( &c != this )
52  {
53  clearCache();
55  int nGeoms = c.mGeometries.size();
56  mGeometries.resize( nGeoms );
57  for ( int i = 0; i < nGeoms; ++i )
58  {
59  mGeometries[i] = c.mGeometries.at( i )->clone();
60  }
61  }
62  return *this;
63 }
64 
66 {
67  clear();
68 }
69 
71 {
72  const QgsGeometryCollection *otherCollection = qgsgeometry_cast< const QgsGeometryCollection * >( &other );
73  if ( !otherCollection )
74  return false;
75 
76  if ( mWkbType != otherCollection->mWkbType )
77  return false;
78 
79  if ( mGeometries.count() != otherCollection->mGeometries.count() )
80  return false;
81 
82  for ( int i = 0; i < mGeometries.count(); ++i )
83  {
84  QgsAbstractGeometry *g1 = mGeometries.at( i );
85  QgsAbstractGeometry *g2 = otherCollection->mGeometries.at( i );
86 
87  // Quick check if the geometries are exactly the same
88  if ( g1 != g2 )
89  {
90  if ( !g1 || !g2 )
91  return false;
92 
93  // Slower check, compare the contents of the geometries
94  if ( *g1 != *g2 )
95  return false;
96  }
97  }
98 
99  return true;
100 }
101 
103 {
104  return !operator==( other );
105 }
106 
108 {
109  auto result = qgis::make_unique< QgsGeometryCollection >();
110  result->mWkbType = mWkbType;
111  return result.release();
112 }
113 
115 {
116  return new QgsGeometryCollection( *this );
117 }
118 
120 {
121  qDeleteAll( mGeometries );
122  mGeometries.clear();
123  clearCache(); //set bounding box invalid
124 }
125 
126 QgsGeometryCollection *QgsGeometryCollection::snappedToGrid( double hSpacing, double vSpacing, double dSpacing, double mSpacing ) const
127 {
128  std::unique_ptr<QgsGeometryCollection> result;
129 
130  for ( auto geom : mGeometries )
131  {
132  std::unique_ptr<QgsAbstractGeometry> gridified { geom->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) };
133  if ( gridified )
134  {
135  if ( !result )
136  result = std::unique_ptr<QgsGeometryCollection> { createEmptyWithSameType() };
137 
138  result->mGeometries.append( gridified.release() );
139  }
140  }
141 
142  return result.release();
143 }
144 
145 bool QgsGeometryCollection::removeDuplicateNodes( double epsilon, bool useZValues )
146 {
147  bool result = false;
148  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
149  {
150  result = result || geom->removeDuplicateNodes( epsilon, useZValues );
151  }
152  return result;
153 }
154 
156 {
157  return nullptr;
158 }
159 
161 {
162  if ( vertex.part < 0 || vertex.part >= mGeometries.count() )
163  {
164  previousVertex = QgsVertexId();
165  nextVertex = QgsVertexId();
166  return;
167  }
168 
169  mGeometries.at( vertex.part )->adjacentVertices( vertex, previousVertex, nextVertex );
170 }
171 
173 {
174  if ( id.part < 0 || id.part >= mGeometries.count() )
175  return -1;
176 
177  int number = 0;
178  int part = 0;
179  for ( QgsAbstractGeometry *geometry : mGeometries )
180  {
181  if ( part == id.part )
182  {
183  int partNumber = geometry->vertexNumberFromVertexId( QgsVertexId( 0, id.ring, id.vertex ) );
184  if ( partNumber == -1 )
185  return -1;
186  return number + partNumber;
187  }
188  else
189  {
190  number += geometry->nCoordinates();
191  }
192 
193  part++;
194  }
195  return -1; // should not happen
196 }
197 
199 {
200  mGeometries.reserve( size );
201 }
202 
204 {
205  clearCache();
206  return mGeometries.value( n );
207 }
208 
210 {
211  if ( mGeometries.isEmpty() )
212  return true;
213 
214  for ( QgsAbstractGeometry *geometry : mGeometries )
215  {
216  if ( !geometry->isEmpty() )
217  return false;
218  }
219  return true;
220 }
221 
223 {
224  if ( !g )
225  {
226  return false;
227  }
228 
229  mGeometries.append( g );
230  clearCache(); //set bounding box invalid
231  return true;
232 }
233 
235 {
236  if ( !g )
237  {
238  return false;
239  }
240 
241  index = std::min( mGeometries.count(), index );
242 
243  mGeometries.insert( index, g );
244  clearCache(); //set bounding box invalid
245  return true;
246 }
247 
249 {
250  if ( nr >= mGeometries.size() || nr < 0 )
251  {
252  return false;
253  }
254  delete mGeometries.at( nr );
255  mGeometries.remove( nr );
256  clearCache(); //set bounding box invalid
257  return true;
258 }
259 
261 {
262  int maxDim = 0;
263  QVector< QgsAbstractGeometry * >::const_iterator it = mGeometries.constBegin();
264  for ( ; it != mGeometries.constEnd(); ++it )
265  {
266  int dim = ( *it )->dimension();
267  if ( dim > maxDim )
268  {
269  maxDim = dim;
270  }
271  }
272  return maxDim;
273 }
274 
276 {
277  return QStringLiteral( "GeometryCollection" );
278 }
279 
281 {
282  for ( QgsAbstractGeometry *g : qgis::as_const( mGeometries ) )
283  {
284  g->transform( ct, d, transformZ );
285  }
286  clearCache(); //set bounding box invalid
287 }
288 
289 void QgsGeometryCollection::transform( const QTransform &t, double zTranslate, double zScale, double mTranslate, double mScale )
290 {
291  for ( QgsAbstractGeometry *g : qgis::as_const( mGeometries ) )
292  {
293  g->transform( t, zTranslate, zScale, mTranslate, mScale );
294  }
295  clearCache(); //set bounding box invalid
296 }
297 
298 void QgsGeometryCollection::draw( QPainter &p ) const
299 {
300  QVector< QgsAbstractGeometry * >::const_iterator it = mGeometries.constBegin();
301  for ( ; it != mGeometries.constEnd(); ++it )
302  {
303  ( *it )->draw( p );
304  }
305 }
306 
308 {
309  if ( !wkbPtr )
310  {
311  return false;
312  }
313 
316  return false;
317 
318  mWkbType = wkbType;
319 
320  int nGeometries = 0;
321  wkbPtr >> nGeometries;
322 
323  QVector<QgsAbstractGeometry *> geometryListBackup = mGeometries;
324  mGeometries.clear();
325  mGeometries.reserve( nGeometries );
326  for ( int i = 0; i < nGeometries; ++i )
327  {
328  std::unique_ptr< QgsAbstractGeometry > geom( QgsGeometryFactory::geomFromWkb( wkbPtr ) ); // also updates wkbPtr
329  if ( geom )
330  {
331  if ( !addGeometry( geom.release() ) )
332  {
333  qDeleteAll( mGeometries );
334  mGeometries = geometryListBackup;
335  return false;
336  }
337  }
338  }
339  qDeleteAll( geometryListBackup );
340 
341  clearCache(); //set bounding box invalid
342 
343  return true;
344 }
345 
346 bool QgsGeometryCollection::fromWkt( const QString &wkt )
347 {
348  return fromCollectionWkt( wkt, QVector<QgsAbstractGeometry *>() << new QgsPoint << new QgsLineString << new QgsPolygon
349  << new QgsCircularString << new QgsCompoundCurve
350  << new QgsCurvePolygon
351  << new QgsMultiPoint << new QgsMultiLineString
353  << new QgsMultiCurve << new QgsMultiSurface, QStringLiteral( "GeometryCollection" ) );
354 }
355 
357 {
358  int binarySize = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 );
359  QVector<QByteArray> wkbForGeometries;
360  for ( const QgsAbstractGeometry *geom : mGeometries )
361  {
362  if ( geom )
363  {
364  QByteArray wkb( geom->asWkb() );
365  binarySize += wkb.length();
366  wkbForGeometries << wkb;
367  }
368  }
369 
370  QByteArray wkbArray;
371  wkbArray.resize( binarySize );
372  QgsWkbPtr wkb( wkbArray );
373  wkb << static_cast<char>( QgsApplication::endian() );
374  wkb << static_cast<quint32>( wkbType() );
375  wkb << static_cast<quint32>( wkbForGeometries.count() );
376  for ( const QByteArray &wkbForGeometry : qgis::as_const( wkbForGeometries ) )
377  {
378  wkb << wkbForGeometry;
379  }
380  return wkbArray;
381 }
382 
384 {
385  QString wkt = wktTypeStr();
386 
387  if ( isEmpty() )
388  wkt += QStringLiteral( " EMPTY" );
389  else
390  {
391  wkt += QLatin1String( " (" );
392  for ( const QgsAbstractGeometry *geom : mGeometries )
393  {
394  QString childWkt = geom->asWkt( precision );
395  if ( wktOmitChildType() )
396  {
397  childWkt = childWkt.mid( childWkt.indexOf( '(' ) );
398  }
399  wkt += childWkt + ',';
400  }
401  if ( wkt.endsWith( ',' ) )
402  {
403  wkt.chop( 1 ); // Remove last ','
404  }
405  wkt += ')';
406  }
407  return wkt;
408 }
409 
410 QDomElement QgsGeometryCollection::asGml2( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
411 {
412  QDomElement elemMultiGeometry = doc.createElementNS( ns, QStringLiteral( "MultiGeometry" ) );
413  for ( const QgsAbstractGeometry *geom : mGeometries )
414  {
415  QDomElement elemGeometryMember = doc.createElementNS( ns, QStringLiteral( "geometryMember" ) );
416  elemGeometryMember.appendChild( geom->asGml2( doc, precision, ns, axisOrder ) );
417  elemMultiGeometry.appendChild( elemGeometryMember );
418  }
419  return elemMultiGeometry;
420 }
421 
422 QDomElement QgsGeometryCollection::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
423 {
424  QDomElement elemMultiGeometry = doc.createElementNS( ns, QStringLiteral( "MultiGeometry" ) );
425  for ( const QgsAbstractGeometry *geom : mGeometries )
426  {
427  QDomElement elemGeometryMember = doc.createElementNS( ns, QStringLiteral( "geometryMember" ) );
428  elemGeometryMember.appendChild( geom->asGml3( doc, precision, ns, axisOrder ) );
429  elemMultiGeometry.appendChild( elemGeometryMember );
430  }
431  return elemMultiGeometry;
432 }
433 
435 {
436  json coordinates( json::array( ) );
437  for ( const QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
438  {
439  coordinates.push_back( geom->asJsonObject( precision ) );
440  }
441  return
442  {
443  { "type", "GeometryCollection" },
444  { "geometries", coordinates }
445  };
446 }
447 
449 {
450  if ( mBoundingBox.isNull() )
451  {
452  mBoundingBox = calculateBoundingBox();
453  }
454  return mBoundingBox;
455 }
456 
458 {
459  if ( mGeometries.empty() )
460  {
461  return QgsRectangle();
462  }
463 
464  QgsRectangle bbox = mGeometries.at( 0 )->boundingBox();
465  for ( int i = 1; i < mGeometries.size(); ++i )
466  {
467  QgsRectangle geomBox = mGeometries.at( i )->boundingBox();
468  bbox.combineExtentWith( geomBox );
469  }
470  return bbox;
471 }
472 
474 {
475  mBoundingBox = QgsRectangle();
476  mHasCachedValidity = false;
477  mValidityFailureReason.clear();
479 }
480 
482 {
483  QgsCoordinateSequence sequence;
484  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
485  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
486  {
487  QgsCoordinateSequence geomCoords = ( *geomIt )->coordinateSequence();
488 
489  QgsCoordinateSequence::const_iterator cIt = geomCoords.constBegin();
490  for ( ; cIt != geomCoords.constEnd(); ++cIt )
491  {
492  sequence.push_back( *cIt );
493  }
494  }
495 
496  return sequence;
497 }
498 
500 {
501  int count = 0;
502 
503  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
504  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
505  {
506  count += ( *geomIt )->nCoordinates();
507  }
508 
509  return count;
510 }
511 
512 double QgsGeometryCollection::closestSegment( const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon ) const
513 {
514  return QgsGeometryUtils::closestSegmentFromComponents( mGeometries, QgsGeometryUtils::Part, pt, segmentPt, vertexAfter, leftOf, epsilon );
515 }
516 
518 {
519  if ( id.part < 0 )
520  {
521  id.part = 0;
522  id.ring = -1;
523  id.vertex = -1;
524  }
525  if ( mGeometries.isEmpty() )
526  {
527  return false;
528  }
529 
530  if ( id.part >= mGeometries.count() )
531  return false;
532 
533  QgsAbstractGeometry *geom = mGeometries.at( id.part );
534  if ( geom->nextVertex( id, vertex ) )
535  {
536  return true;
537  }
538  if ( ( id.part + 1 ) >= numGeometries() )
539  {
540  return false;
541  }
542  ++id.part;
543  id.ring = -1;
544  id.vertex = -1;
545  return mGeometries.at( id.part )->nextVertex( id, vertex );
546 }
547 
549 {
550  if ( position.part >= mGeometries.size() )
551  {
552  return false;
553  }
554 
555  bool success = mGeometries.at( position.part )->insertVertex( position, vertex );
556  if ( success )
557  {
558  clearCache(); //set bounding box invalid
559  }
560  return success;
561 }
562 
564 {
565  if ( position.part < 0 || position.part >= mGeometries.size() )
566  {
567  return false;
568  }
569 
570  bool success = mGeometries.at( position.part )->moveVertex( position, newPos );
571  if ( success )
572  {
573  clearCache(); //set bounding box invalid
574  }
575  return success;
576 }
577 
579 {
580  if ( position.part < 0 || position.part >= mGeometries.size() )
581  {
582  return false;
583  }
584 
585  QgsAbstractGeometry *geom = mGeometries.at( position.part );
586  if ( !geom )
587  {
588  return false;
589  }
590 
591  bool success = geom->deleteVertex( position );
592 
593  //remove geometry if no vertices left
594  if ( geom->isEmpty() )
595  {
596  removeGeometry( position.part );
597  }
598 
599  if ( success )
600  {
601  clearCache(); //set bounding box invalid
602  }
603  return success;
604 }
605 
607 {
608  double length = 0.0;
609  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
610  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
611  {
612  length += ( *geomIt )->length();
613  }
614  return length;
615 }
616 
618 {
619  double area = 0.0;
620  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
621  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
622  {
623  area += ( *geomIt )->area();
624  }
625  return area;
626 }
627 
629 {
630  double perimeter = 0.0;
631  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
632  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
633  {
634  perimeter += ( *geomIt )->perimeter();
635  }
636  return perimeter;
637 }
638 
639 bool QgsGeometryCollection::fromCollectionWkt( const QString &wkt, const QVector<QgsAbstractGeometry *> &subtypes, const QString &defaultChildWkbType )
640 {
641  clear();
642 
643  QPair<QgsWkbTypes::Type, QString> parts = QgsGeometryUtils::wktReadBlock( wkt );
644 
645  if ( QgsWkbTypes::flatType( parts.first ) != QgsWkbTypes::flatType( wkbType() ) )
646  {
647  qDeleteAll( subtypes );
648  return false;
649  }
650  mWkbType = parts.first;
651 
652  if ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 )
653  return true;
654 
655  QString defChildWkbType = QStringLiteral( "%1%2%3 " ).arg( defaultChildWkbType, is3D() ? QStringLiteral( "Z" ) : QString(), isMeasure() ? QStringLiteral( "M" ) : QString() );
656 
657  const QStringList blocks = QgsGeometryUtils::wktGetChildBlocks( parts.second, defChildWkbType );
658  for ( const QString &childWkt : blocks )
659  {
660  QPair<QgsWkbTypes::Type, QString> childParts = QgsGeometryUtils::wktReadBlock( childWkt );
661 
662  bool success = false;
663  for ( const QgsAbstractGeometry *geom : subtypes )
664  {
665  if ( QgsWkbTypes::flatType( childParts.first ) == QgsWkbTypes::flatType( geom->wkbType() ) )
666  {
667  mGeometries.append( geom->clone() );
668  if ( mGeometries.back()->fromWkt( childWkt ) )
669  {
670  success = true;
671  break;
672  }
673  }
674  }
675  if ( !success )
676  {
677  clear();
678  qDeleteAll( subtypes );
679  return false;
680  }
681  }
682  qDeleteAll( subtypes );
683 
684  //scan through geometries and check if dimensionality of geometries is different to collection.
685  //if so, update the type dimensionality of the collection to match
686  bool hasZ = false;
687  bool hasM = false;
688  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
689  {
690  hasZ = hasZ || geom->is3D();
691  hasM = hasM || geom->isMeasure();
692  if ( hasZ && hasM )
693  break;
694  }
695  if ( hasZ )
696  addZValue( 0 );
697  if ( hasM )
698  addMValue( 0 );
699 
700  return true;
701 }
702 
704 {
705  QVector< QgsAbstractGeometry * >::const_iterator it = mGeometries.constBegin();
706  for ( ; it != mGeometries.constEnd(); ++it )
707  {
708  if ( ( *it )->hasCurvedSegments() )
709  {
710  return true;
711  }
712  }
713  return false;
714 }
715 
717 {
718  std::unique_ptr< QgsAbstractGeometry > geom( QgsGeometryFactory::geomFromWkbType( mWkbType ) );
719  QgsGeometryCollection *geomCollection = qgsgeometry_cast<QgsGeometryCollection *>( geom.get() );
720  if ( !geomCollection )
721  {
722  return clone();
723  }
724 
725  geomCollection->reserve( mGeometries.size() );
726  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
727  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
728  {
729  geomCollection->addGeometry( ( *geomIt )->segmentize( tolerance, toleranceType ) );
730  }
731  return geom.release();
732 }
733 
735 {
736  if ( vertex.part < 0 || vertex.part >= mGeometries.size() )
737  {
738  return 0.0;
739  }
740 
741  QgsAbstractGeometry *geom = mGeometries[vertex.part];
742  if ( !geom )
743  {
744  return 0.0;
745  }
746 
747  return geom->vertexAngle( vertex );
748 }
749 
751 {
752  if ( startVertex.part < 0 || startVertex.part >= mGeometries.size() )
753  {
754  return 0.0;
755  }
756 
757  const QgsAbstractGeometry *geom = mGeometries[startVertex.part];
758  if ( !geom )
759  {
760  return 0.0;
761  }
762 
763  return geom->segmentLength( startVertex );
764 }
765 
766 int QgsGeometryCollection::vertexCount( int part, int ring ) const
767 {
768  if ( part < 0 || part >= mGeometries.size() )
769  {
770  return 0;
771  }
772 
773  return mGeometries[part]->vertexCount( 0, ring );
774 }
775 
776 int QgsGeometryCollection::ringCount( int part ) const
777 {
778  if ( part < 0 || part >= mGeometries.size() )
779  {
780  return 0;
781  }
782 
783  return mGeometries[part]->ringCount();
784 }
785 
787 {
788  return mGeometries.size();
789 }
790 
792 {
793  return mGeometries[id.part]->vertexAt( id );
794 }
795 
796 bool QgsGeometryCollection::isValid( QString &error, int flags ) const
797 {
798  if ( flags == 0 && mHasCachedValidity )
799  {
800  // use cached validity results
801  error = mValidityFailureReason;
802  return error.isEmpty();
803  }
804 
805  QgsGeos geos( this );
806  bool res = geos.isValid( &error, flags & QgsGeometry::FlagAllowSelfTouchingHoles, nullptr );
807  if ( flags == 0 )
808  {
809  mValidityFailureReason = !res ? error : QString();
810  mHasCachedValidity = true;
811  }
812  return res;
813 }
814 
815 bool QgsGeometryCollection::addZValue( double zValue )
816 {
817  if ( QgsWkbTypes::hasZ( mWkbType ) )
818  return false;
819 
821 
822  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
823  {
824  geom->addZValue( zValue );
825  }
826  clearCache();
827  return true;
828 }
829 
830 bool QgsGeometryCollection::addMValue( double mValue )
831 {
832  if ( QgsWkbTypes::hasM( mWkbType ) )
833  return false;
834 
836 
837  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
838  {
839  geom->addMValue( mValue );
840  }
841  clearCache();
842  return true;
843 }
844 
845 
847 {
849  return false;
850 
852  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
853  {
854  geom->dropZValue();
855  }
856  clearCache();
857  return true;
858 }
859 
861 {
863  return false;
864 
866  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
867  {
868  geom->dropMValue();
869  }
870  clearCache();
871  return true;
872 }
873 
874 void QgsGeometryCollection::filterVertices( const std::function<bool ( const QgsPoint & )> &filter )
875 {
876  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
877  {
878  if ( geom )
879  geom->filterVertices( filter );
880  }
881  clearCache();
882 }
883 
884 void QgsGeometryCollection::transformVertices( const std::function<QgsPoint( const QgsPoint & )> &transform )
885 {
886  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
887  {
888  if ( geom )
889  geom->transformVertices( transform );
890  }
891  clearCache();
892 }
893 
895 {
896  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
897  {
898  if ( geom )
899  geom->swapXy();
900  }
901  clearCache();
902 }
903 
905 {
906  std::unique_ptr< QgsGeometryCollection > newCollection( new QgsGeometryCollection() );
907  newCollection->reserve( mGeometries.size() );
908  for ( QgsAbstractGeometry *geom : mGeometries )
909  {
910  newCollection->addGeometry( geom->toCurveType() );
911  }
912  return newCollection.release();
913 }
914 
916 {
917  return false;
918 }
919 
921 {
922  return mGeometries.count();
923 }
924 
926 {
927  if ( index < 0 || index > mGeometries.count() )
928  return nullptr;
929  return mGeometries.at( index );
930 }
bool isMeasure() const
Returns true if the geometry contains m values.
static std::unique_ptr< QgsAbstractGeometry > geomFromWkb(QgsConstWkbPtr &wkb)
Construct geometry from a WKB string.
int precision
virtual bool removeGeometry(int nr)
Removes a geometry from the collection.
bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const override
Returns next vertex id and coordinates.
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
void filterVertices(const std::function< bool(const QgsPoint &) > &filter) override
Filters the vertices from the geometry in place, removing any which do not return true for the filter...
bool operator!=(const QgsAbstractGeometry &other) const override
virtual bool isEmpty() const
Returns true if the geometry is empty.
QDomElement asGml2(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML2 representation of the geometry.
static std::unique_ptr< QgsAbstractGeometry > geomFromWkbType(QgsWkbTypes::Type t)
Returns empty geometry from wkb type.
virtual bool deleteVertex(QgsVertexId position)=0
Deletes a vertex within the geometry.
bool fromWkb(QgsConstWkbPtr &wkb) override
Sets the geometry from a WKB string.
bool operator==(const QgsAbstractGeometry &other) const override
void clear() override
Clears the geometry, ie reset it to a null geometry.
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
QgsAbstractGeometry & operator=(const QgsAbstractGeometry &geom)
Multi point geometry collection.
Definition: qgsmultipoint.h:29
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 (...
QgsGeometryCollection * snappedToGrid(double hSpacing, double vSpacing, double dSpacing=0, double mSpacing=0) const override
Makes a new geometry with all the points or vertices snapped to the closest point of the grid...
QVector< QgsRingSequence > QgsCoordinateSequence
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
bool isValid(QString &error, int flags=0) const override
Checks validity of the geometry, and returns true if the geometry is valid.
TransformDirection
Enum used to indicate the direction (forward or inverse) of the transform.
bool hasCurvedSegments() const override
Returns true if the geometry contains curved segments.
bool isValid(QString *errorMsg=nullptr, bool allowSelfTouchingHoles=false, QgsGeometry *errorLoc=nullptr) const override
Returns true if the geometry is valid.
Definition: qgsgeos.cpp:1665
virtual double vertexAngle(QgsVertexId vertex) const =0
Returns approximate angle at a vertex.
Multi line string geometry collection.
Curve polygon geometry type.
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
QgsAbstractGeometry * boundary() const override
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
virtual bool wktOmitChildType() const
Returns whether child type names are omitted from Wkt representations of the collection.
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle...
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
QgsGeometryCollection & operator=(const QgsGeometryCollection &c)
virtual bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const =0
Returns next vertex id and coordinates.
bool dropMValue() override
Drops any measure values which exist in the geometry.
static endian_t endian()
Returns whether this machine uses big or little endian.
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:917
static QStringList wktGetChildBlocks(const QString &wkt, const QString &defaultType=QString())
Parses a WKT string and returns of list of blocks contained in the WKT.
static Type dropM(Type type)
Drops the m dimension (if present) for a WKB type and returns the new type.
Definition: qgswkbtypes.h:1087
Multi surface geometry collection.
double length() const override
Returns the planar, 2-dimensional length of the geometry.
QgsWkbTypes::Type mWkbType
virtual bool insertGeometry(QgsAbstractGeometry *g, int index)
Inserts a geometry before a specified index and takes ownership.
void transformVertices(const std::function< QgsPoint(const QgsPoint &) > &transform) override
Transforms the vertices from the geometry in place, applying the transform function to every vertex...
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Indicates that self-touching holes are permitted. OGC validity states that self-touching holes are NO...
Definition: qgsgeometry.h:367
QString wktTypeStr() const
Returns the WKT type string of the geometry.
bool isEmpty() const override
Returns true if the geometry is empty.
void adjacentVertices(QgsVertexId vertex, QgsVertexId &previousVertex, QgsVertexId &nextVertex) const override
Returns the vertices adjacent to a specified vertex within a geometry.
int nCoordinates() const override
Returns the number of nodes contained in the geometry.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
void swapXy() override
Swaps the x and y coordinates from the geometry.
virtual void clearCache() const
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
virtual double segmentLength(QgsVertexId startVertex) const =0
Returns the length of the segment of the geometry which begins at startVertex.
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1038
int dimension() const override
Returns the inherent dimension of the geometry.
QgsGeometryConstPartIterator parts() const
Returns Java-style iterator for traversal of parts of the geometry.
Utility class for identifying a unique vertex within a geometry.
Geometry collection.
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
QgsGeometryCollection * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership...
double area() const override
Returns the planar, 2-dimensional area of the geometry.
QgsAbstractGeometry * childGeometry(int index) const override
Returns pointer to child geometry (for geometries with child geometries - i.e.
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1013
T qgsgeometry_cast(const QgsAbstractGeometry *geom)
int childCount() const override
Returns number of child geometries (for geometries with child geometries) or child points (for geomet...
Multi curve geometry collection.
Definition: qgsmulticurve.h:29
QgsAbstractGeometry * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
QString geometryType() const override
Returns a unique string representing the geometry type.
QByteArray asWkb() const override
Returns a WKB representation of the geometry.
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
Abstract base class for all geometries.
void clearCache() const override
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
Does vector analysis using the geos library and handles import, export, exception handling*...
Definition: qgsgeos.h:103
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
int vertexNumberFromVertexId(QgsVertexId id) const override
Returns the vertex number corresponding to a vertex id.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
bool fromCollectionWkt(const QString &wkt, const QVector< QgsAbstractGeometry *> &subtypes, const QString &defaultChildWkbType=QString())
Reads a collection from a WKT string.
AxisOrder
Axis order for GML generation.
int numGeometries() const
Returns the number of geometries within the collection.
Contains geos related utilities and functions.
Definition: qgsgeos.h:41
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle...
Definition: qgsrectangle.h:359
bool removeDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false) override
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
int partCount() const override
Returns count of parts contained in the geometry.
QVector< QgsAbstractGeometry *> mGeometries
void reserve(int size)
Attempts to allocate memory for at least size geometries.
double closestSegment(const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf=nullptr, double epsilon=4 *std::numeric_limits< double >::epsilon()) const override
Searches for the closest segment of the geometry to a given point.
QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML3 representation of the geometry.
static Type dropZ(Type type)
Drops the z dimension (if present) for a WKB type and returns the new type.
Definition: qgswkbtypes.h:1069
Multi polygon geometry collection.
QgsPoint vertexAt(QgsVertexId id) const override
Returns the point corresponding to a specified vertex id.
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:43
QgsGeometryCollection * toCurveType() const override
Returns the geometry converted to the more generic curve type.
QgsCoordinateSequence coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:436
Class for doing transforms between two map coordinate systems.
double perimeter() const override
Returns the planar, 2-dimensional perimeter of the geometry.
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) override SIP_THROW(QgsCsException)
Transforms the geometry using a coordinate transform.
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:967
Compound curve geometry type.
Circular string geometry type.
QgsGeometryCollection * clone() const override
Clones the geometry by performing a deep copy.
Polygon geometry type.
Definition: qgspolygon.h:31
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:576
QgsWkbTypes::Type readHeader() const
readHeader
Definition: qgswkbptr.cpp:54
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
double ANALYSIS_EXPORT leftOf(const QgsPoint &thepoint, const QgsPoint *p1, const QgsPoint *p2)
Returns whether &#39;thepoint&#39; is left or right of the line from &#39;p1&#39; to &#39;p2&#39;. Negativ values mean left a...
Definition: MathUtils.cpp:292
static double closestSegmentFromComponents(T &container, ComponentType ctype, const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon)
int vertexCount(int part=0, int ring=0) const override
Returns the number of vertices of which this geometry is built.
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
double vertexAngle(QgsVertexId vertex) const override
Returns approximate angle at a vertex.
QgsRectangle calculateBoundingBox() const override
Default calculator for the minimal bounding box for the geometry.
int ringCount(int part=0) const override
Returns the number of rings of which this geometry is built.