QGIS API Documentation  3.12.1-BucureČ™ti (121cc00ff0)
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  QString kml;
451  kml.append( QLatin1String( "<MultiGeometry>" ) );
452  const QVector< QgsAbstractGeometry * > &geometries = mGeometries;
453  for ( const QgsAbstractGeometry *geometry : geometries )
454  {
455  kml.append( geometry->asKml( precision ) );
456  }
457  kml.append( QLatin1String( "</MultiGeometry>" ) );
458  return kml;
459 }
460 
462 {
463  if ( mBoundingBox.isNull() )
464  {
465  mBoundingBox = calculateBoundingBox();
466  }
467  return mBoundingBox;
468 }
469 
471 {
472  if ( mGeometries.empty() )
473  {
474  return QgsRectangle();
475  }
476 
477  QgsRectangle bbox = mGeometries.at( 0 )->boundingBox();
478  for ( int i = 1; i < mGeometries.size(); ++i )
479  {
480  QgsRectangle geomBox = mGeometries.at( i )->boundingBox();
481  bbox.combineExtentWith( geomBox );
482  }
483  return bbox;
484 }
485 
487 {
488  mBoundingBox = QgsRectangle();
489  mHasCachedValidity = false;
490  mValidityFailureReason.clear();
492 }
493 
495 {
496  QgsCoordinateSequence sequence;
497  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
498  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
499  {
500  QgsCoordinateSequence geomCoords = ( *geomIt )->coordinateSequence();
501 
502  QgsCoordinateSequence::const_iterator cIt = geomCoords.constBegin();
503  for ( ; cIt != geomCoords.constEnd(); ++cIt )
504  {
505  sequence.push_back( *cIt );
506  }
507  }
508 
509  return sequence;
510 }
511 
513 {
514  int count = 0;
515 
516  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
517  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
518  {
519  count += ( *geomIt )->nCoordinates();
520  }
521 
522  return count;
523 }
524 
525 double QgsGeometryCollection::closestSegment( const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon ) const
526 {
527  return QgsGeometryUtils::closestSegmentFromComponents( mGeometries, QgsGeometryUtils::Part, pt, segmentPt, vertexAfter, leftOf, epsilon );
528 }
529 
531 {
532  if ( id.part < 0 )
533  {
534  id.part = 0;
535  id.ring = -1;
536  id.vertex = -1;
537  }
538  if ( mGeometries.isEmpty() )
539  {
540  return false;
541  }
542 
543  if ( id.part >= mGeometries.count() )
544  return false;
545 
546  QgsAbstractGeometry *geom = mGeometries.at( id.part );
547  if ( geom->nextVertex( id, vertex ) )
548  {
549  return true;
550  }
551  if ( ( id.part + 1 ) >= numGeometries() )
552  {
553  return false;
554  }
555  ++id.part;
556  id.ring = -1;
557  id.vertex = -1;
558  return mGeometries.at( id.part )->nextVertex( id, vertex );
559 }
560 
562 {
563  if ( position.part >= mGeometries.size() )
564  {
565  return false;
566  }
567 
568  bool success = mGeometries.at( position.part )->insertVertex( position, vertex );
569  if ( success )
570  {
571  clearCache(); //set bounding box invalid
572  }
573  return success;
574 }
575 
577 {
578  if ( position.part < 0 || position.part >= mGeometries.size() )
579  {
580  return false;
581  }
582 
583  bool success = mGeometries.at( position.part )->moveVertex( position, newPos );
584  if ( success )
585  {
586  clearCache(); //set bounding box invalid
587  }
588  return success;
589 }
590 
592 {
593  if ( position.part < 0 || position.part >= mGeometries.size() )
594  {
595  return false;
596  }
597 
598  QgsAbstractGeometry *geom = mGeometries.at( position.part );
599  if ( !geom )
600  {
601  return false;
602  }
603 
604  bool success = geom->deleteVertex( position );
605 
606  //remove geometry if no vertices left
607  if ( geom->isEmpty() )
608  {
609  removeGeometry( position.part );
610  }
611 
612  if ( success )
613  {
614  clearCache(); //set bounding box invalid
615  }
616  return success;
617 }
618 
620 {
621  double length = 0.0;
622  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
623  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
624  {
625  length += ( *geomIt )->length();
626  }
627  return length;
628 }
629 
631 {
632  double area = 0.0;
633  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
634  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
635  {
636  area += ( *geomIt )->area();
637  }
638  return area;
639 }
640 
642 {
643  double perimeter = 0.0;
644  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
645  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
646  {
647  perimeter += ( *geomIt )->perimeter();
648  }
649  return perimeter;
650 }
651 
652 bool QgsGeometryCollection::fromCollectionWkt( const QString &wkt, const QVector<QgsAbstractGeometry *> &subtypes, const QString &defaultChildWkbType )
653 {
654  clear();
655 
656  QPair<QgsWkbTypes::Type, QString> parts = QgsGeometryUtils::wktReadBlock( wkt );
657 
658  if ( QgsWkbTypes::flatType( parts.first ) != QgsWkbTypes::flatType( wkbType() ) )
659  {
660  qDeleteAll( subtypes );
661  return false;
662  }
663  mWkbType = parts.first;
664 
665  if ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 )
666  return true;
667 
668  QString defChildWkbType = QStringLiteral( "%1%2%3 " ).arg( defaultChildWkbType, is3D() ? QStringLiteral( "Z" ) : QString(), isMeasure() ? QStringLiteral( "M" ) : QString() );
669 
670  const QStringList blocks = QgsGeometryUtils::wktGetChildBlocks( parts.second, defChildWkbType );
671  for ( const QString &childWkt : blocks )
672  {
673  QPair<QgsWkbTypes::Type, QString> childParts = QgsGeometryUtils::wktReadBlock( childWkt );
674 
675  bool success = false;
676  for ( const QgsAbstractGeometry *geom : subtypes )
677  {
678  if ( QgsWkbTypes::flatType( childParts.first ) == QgsWkbTypes::flatType( geom->wkbType() ) )
679  {
680  mGeometries.append( geom->clone() );
681  if ( mGeometries.back()->fromWkt( childWkt ) )
682  {
683  success = true;
684  break;
685  }
686  }
687  }
688  if ( !success )
689  {
690  clear();
691  qDeleteAll( subtypes );
692  return false;
693  }
694  }
695  qDeleteAll( subtypes );
696 
697  //scan through geometries and check if dimensionality of geometries is different to collection.
698  //if so, update the type dimensionality of the collection to match
699  bool hasZ = false;
700  bool hasM = false;
701  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
702  {
703  hasZ = hasZ || geom->is3D();
704  hasM = hasM || geom->isMeasure();
705  if ( hasZ && hasM )
706  break;
707  }
708  if ( hasZ )
709  addZValue( 0 );
710  if ( hasM )
711  addMValue( 0 );
712 
713  return true;
714 }
715 
717 {
718  QVector< QgsAbstractGeometry * >::const_iterator it = mGeometries.constBegin();
719  for ( ; it != mGeometries.constEnd(); ++it )
720  {
721  if ( ( *it )->hasCurvedSegments() )
722  {
723  return true;
724  }
725  }
726  return false;
727 }
728 
730 {
731  std::unique_ptr< QgsAbstractGeometry > geom( QgsGeometryFactory::geomFromWkbType( mWkbType ) );
732  QgsGeometryCollection *geomCollection = qgsgeometry_cast<QgsGeometryCollection *>( geom.get() );
733  if ( !geomCollection )
734  {
735  return clone();
736  }
737 
738  geomCollection->reserve( mGeometries.size() );
739  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
740  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
741  {
742  geomCollection->addGeometry( ( *geomIt )->segmentize( tolerance, toleranceType ) );
743  }
744  return geom.release();
745 }
746 
748 {
749  if ( vertex.part < 0 || vertex.part >= mGeometries.size() )
750  {
751  return 0.0;
752  }
753 
754  QgsAbstractGeometry *geom = mGeometries[vertex.part];
755  if ( !geom )
756  {
757  return 0.0;
758  }
759 
760  return geom->vertexAngle( vertex );
761 }
762 
764 {
765  if ( startVertex.part < 0 || startVertex.part >= mGeometries.size() )
766  {
767  return 0.0;
768  }
769 
770  const QgsAbstractGeometry *geom = mGeometries[startVertex.part];
771  if ( !geom )
772  {
773  return 0.0;
774  }
775 
776  return geom->segmentLength( startVertex );
777 }
778 
779 int QgsGeometryCollection::vertexCount( int part, int ring ) const
780 {
781  if ( part < 0 || part >= mGeometries.size() )
782  {
783  return 0;
784  }
785 
786  return mGeometries[part]->vertexCount( 0, ring );
787 }
788 
789 int QgsGeometryCollection::ringCount( int part ) const
790 {
791  if ( part < 0 || part >= mGeometries.size() )
792  {
793  return 0;
794  }
795 
796  return mGeometries[part]->ringCount();
797 }
798 
800 {
801  return mGeometries.size();
802 }
803 
805 {
806  return mGeometries[id.part]->vertexAt( id );
807 }
808 
809 bool QgsGeometryCollection::isValid( QString &error, int flags ) const
810 {
811  if ( flags == 0 && mHasCachedValidity )
812  {
813  // use cached validity results
814  error = mValidityFailureReason;
815  return error.isEmpty();
816  }
817 
818  QgsGeos geos( this );
819  bool res = geos.isValid( &error, flags & QgsGeometry::FlagAllowSelfTouchingHoles, nullptr );
820  if ( flags == 0 )
821  {
822  mValidityFailureReason = !res ? error : QString();
823  mHasCachedValidity = true;
824  }
825  return res;
826 }
827 
828 bool QgsGeometryCollection::addZValue( double zValue )
829 {
830  if ( QgsWkbTypes::hasZ( mWkbType ) )
831  return false;
832 
834 
835  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
836  {
837  geom->addZValue( zValue );
838  }
839  clearCache();
840  return true;
841 }
842 
843 bool QgsGeometryCollection::addMValue( double mValue )
844 {
845  if ( QgsWkbTypes::hasM( mWkbType ) )
846  return false;
847 
849 
850  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
851  {
852  geom->addMValue( mValue );
853  }
854  clearCache();
855  return true;
856 }
857 
858 
860 {
862  return false;
863 
865  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
866  {
867  geom->dropZValue();
868  }
869  clearCache();
870  return true;
871 }
872 
874 {
876  return false;
877 
879  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
880  {
881  geom->dropMValue();
882  }
883  clearCache();
884  return true;
885 }
886 
887 void QgsGeometryCollection::filterVertices( const std::function<bool ( const QgsPoint & )> &filter )
888 {
889  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
890  {
891  if ( geom )
892  geom->filterVertices( filter );
893  }
894  clearCache();
895 }
896 
897 void QgsGeometryCollection::transformVertices( const std::function<QgsPoint( const QgsPoint & )> &transform )
898 {
899  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
900  {
901  if ( geom )
902  geom->transformVertices( transform );
903  }
904  clearCache();
905 }
906 
908 {
909  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
910  {
911  if ( geom )
912  geom->swapXy();
913  }
914  clearCache();
915 }
916 
918 {
919  std::unique_ptr< QgsGeometryCollection > newCollection( new QgsGeometryCollection() );
920  newCollection->reserve( mGeometries.size() );
921  for ( QgsAbstractGeometry *geom : mGeometries )
922  {
923  newCollection->addGeometry( geom->toCurveType() );
924  }
925  return newCollection.release();
926 }
927 
929 {
930  return false;
931 }
932 
934 {
935  return mGeometries.count();
936 }
937 
939 {
940  if ( index < 0 || index > mGeometries.count() )
941  return nullptr;
942  return mGeometries.at( index );
943 }
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.
QString asKml(int precision=17) const override
Returns a KML representation of 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:1679
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:368
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;. Negative values mean left ...
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.