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