QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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  clearCache();
201  return mGeometries.value( n );
202 }
203 
205 {
206  if ( mGeometries.isEmpty() )
207  return true;
208 
209  for ( QgsAbstractGeometry *geometry : mGeometries )
210  {
211  if ( !geometry->isEmpty() )
212  return false;
213  }
214  return true;
215 }
216 
218 {
219  if ( !g )
220  {
221  return false;
222  }
223 
224  mGeometries.append( g );
225  clearCache(); //set bounding box invalid
226  return true;
227 }
228 
230 {
231  if ( !g )
232  {
233  return false;
234  }
235 
236  index = std::min( mGeometries.count(), index );
237 
238  mGeometries.insert( index, g );
239  clearCache(); //set bounding box invalid
240  return true;
241 }
242 
244 {
245  if ( nr >= mGeometries.size() || nr < 0 )
246  {
247  return false;
248  }
249  delete mGeometries.at( nr );
250  mGeometries.remove( nr );
251  clearCache(); //set bounding box invalid
252  return true;
253 }
254 
256 {
257  int maxDim = 0;
258  QVector< QgsAbstractGeometry * >::const_iterator it = mGeometries.constBegin();
259  for ( ; it != mGeometries.constEnd(); ++it )
260  {
261  int dim = ( *it )->dimension();
262  if ( dim > maxDim )
263  {
264  maxDim = dim;
265  }
266  }
267  return maxDim;
268 }
269 
271 {
272  return QStringLiteral( "GeometryCollection" );
273 }
274 
276 {
277  for ( QgsAbstractGeometry *g : qgis::as_const( mGeometries ) )
278  {
279  g->transform( ct, d, transformZ );
280  }
281  clearCache(); //set bounding box invalid
282 }
283 
284 void QgsGeometryCollection::transform( const QTransform &t, double zTranslate, double zScale, double mTranslate, double mScale )
285 {
286  for ( QgsAbstractGeometry *g : qgis::as_const( mGeometries ) )
287  {
288  g->transform( t, zTranslate, zScale, mTranslate, mScale );
289  }
290  clearCache(); //set bounding box invalid
291 }
292 
293 void QgsGeometryCollection::draw( QPainter &p ) const
294 {
295  QVector< QgsAbstractGeometry * >::const_iterator it = mGeometries.constBegin();
296  for ( ; it != mGeometries.constEnd(); ++it )
297  {
298  ( *it )->draw( p );
299  }
300 }
301 
303 {
304  if ( !wkbPtr )
305  {
306  return false;
307  }
308 
311  return false;
312 
313  mWkbType = wkbType;
314 
315  int nGeometries = 0;
316  wkbPtr >> nGeometries;
317 
318  QVector<QgsAbstractGeometry *> geometryListBackup = mGeometries;
319  mGeometries.clear();
320  for ( int i = 0; i < nGeometries; ++i )
321  {
322  std::unique_ptr< QgsAbstractGeometry > geom( QgsGeometryFactory::geomFromWkb( wkbPtr ) ); // also updates wkbPtr
323  if ( geom )
324  {
325  if ( !addGeometry( geom.release() ) )
326  {
327  qDeleteAll( mGeometries );
328  mGeometries = geometryListBackup;
329  return false;
330  }
331  }
332  }
333  qDeleteAll( geometryListBackup );
334 
335  clearCache(); //set bounding box invalid
336 
337  return true;
338 }
339 
340 bool QgsGeometryCollection::fromWkt( const QString &wkt )
341 {
342  return fromCollectionWkt( wkt, QVector<QgsAbstractGeometry *>() << new QgsPoint << new QgsLineString << new QgsPolygon
343  << new QgsCircularString << new QgsCompoundCurve
344  << new QgsCurvePolygon
345  << new QgsMultiPoint << new QgsMultiLineString
347  << new QgsMultiCurve << new QgsMultiSurface, QStringLiteral( "GeometryCollection" ) );
348 }
349 
351 {
352  int binarySize = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 );
353  QVector<QByteArray> wkbForGeometries;
354  for ( const QgsAbstractGeometry *geom : mGeometries )
355  {
356  if ( geom )
357  {
358  QByteArray wkb( geom->asWkb() );
359  binarySize += wkb.length();
360  wkbForGeometries << wkb;
361  }
362  }
363 
364  QByteArray wkbArray;
365  wkbArray.resize( binarySize );
366  QgsWkbPtr wkb( wkbArray );
367  wkb << static_cast<char>( QgsApplication::endian() );
368  wkb << static_cast<quint32>( wkbType() );
369  wkb << static_cast<quint32>( wkbForGeometries.count() );
370  for ( const QByteArray &wkbForGeometry : qgis::as_const( wkbForGeometries ) )
371  {
372  wkb << wkbForGeometry;
373  }
374  return wkbArray;
375 }
376 
378 {
379  QString wkt = wktTypeStr() + QLatin1String( " (" );
380  for ( const QgsAbstractGeometry *geom : mGeometries )
381  {
382  QString childWkt = geom->asWkt( precision );
383  if ( wktOmitChildType() )
384  {
385  childWkt = childWkt.mid( childWkt.indexOf( '(' ) );
386  }
387  wkt += childWkt + ',';
388  }
389  if ( wkt.endsWith( ',' ) )
390  {
391  wkt.chop( 1 ); // Remove last ','
392  }
393  wkt += ')';
394  return wkt;
395 }
396 
397 QDomElement QgsGeometryCollection::asGml2( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
398 {
399  QDomElement elemMultiGeometry = doc.createElementNS( ns, QStringLiteral( "MultiGeometry" ) );
400  for ( const QgsAbstractGeometry *geom : mGeometries )
401  {
402  QDomElement elemGeometryMember = doc.createElementNS( ns, QStringLiteral( "geometryMember" ) );
403  elemGeometryMember.appendChild( geom->asGml2( doc, precision, ns, axisOrder ) );
404  elemMultiGeometry.appendChild( elemGeometryMember );
405  }
406  return elemMultiGeometry;
407 }
408 
409 QDomElement QgsGeometryCollection::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
410 {
411  QDomElement elemMultiGeometry = doc.createElementNS( ns, QStringLiteral( "MultiGeometry" ) );
412  for ( const QgsAbstractGeometry *geom : mGeometries )
413  {
414  QDomElement elemGeometryMember = doc.createElementNS( ns, QStringLiteral( "geometryMember" ) );
415  elemGeometryMember.appendChild( geom->asGml3( doc, precision, ns, axisOrder ) );
416  elemMultiGeometry.appendChild( elemGeometryMember );
417  }
418  return elemMultiGeometry;
419 }
420 
422 {
423  json coordinates( json::array( ) );
424  for ( const QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
425  {
426  coordinates.push_back( geom->asJsonObject( precision ) );
427  }
428  return
429  {
430  { "type", "GeometryCollection" },
431  { "geometries", coordinates }
432  };
433 }
434 
436 {
437  if ( mBoundingBox.isNull() )
438  {
439  mBoundingBox = calculateBoundingBox();
440  }
441  return mBoundingBox;
442 }
443 
445 {
446  if ( mGeometries.empty() )
447  {
448  return QgsRectangle();
449  }
450 
451  QgsRectangle bbox = mGeometries.at( 0 )->boundingBox();
452  for ( int i = 1; i < mGeometries.size(); ++i )
453  {
454  QgsRectangle geomBox = mGeometries.at( i )->boundingBox();
455  bbox.combineExtentWith( geomBox );
456  }
457  return bbox;
458 }
459 
461 {
462  mBoundingBox = QgsRectangle();
463  mHasCachedValidity = false;
464  mValidityFailureReason.clear();
466 }
467 
469 {
470  QgsCoordinateSequence sequence;
471  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
472  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
473  {
474  QgsCoordinateSequence geomCoords = ( *geomIt )->coordinateSequence();
475 
476  QgsCoordinateSequence::const_iterator cIt = geomCoords.constBegin();
477  for ( ; cIt != geomCoords.constEnd(); ++cIt )
478  {
479  sequence.push_back( *cIt );
480  }
481  }
482 
483  return sequence;
484 }
485 
487 {
488  int count = 0;
489 
490  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
491  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
492  {
493  count += ( *geomIt )->nCoordinates();
494  }
495 
496  return count;
497 }
498 
499 double QgsGeometryCollection::closestSegment( const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon ) const
500 {
501  return QgsGeometryUtils::closestSegmentFromComponents( mGeometries, QgsGeometryUtils::Part, pt, segmentPt, vertexAfter, leftOf, epsilon );
502 }
503 
505 {
506  if ( id.part < 0 )
507  {
508  id.part = 0;
509  id.ring = -1;
510  id.vertex = -1;
511  }
512  if ( mGeometries.isEmpty() )
513  {
514  return false;
515  }
516 
517  if ( id.part >= mGeometries.count() )
518  return false;
519 
520  QgsAbstractGeometry *geom = mGeometries.at( id.part );
521  if ( geom->nextVertex( id, vertex ) )
522  {
523  return true;
524  }
525  if ( ( id.part + 1 ) >= numGeometries() )
526  {
527  return false;
528  }
529  ++id.part;
530  id.ring = -1;
531  id.vertex = -1;
532  return mGeometries.at( id.part )->nextVertex( id, vertex );
533 }
534 
536 {
537  if ( position.part >= mGeometries.size() )
538  {
539  return false;
540  }
541 
542  bool success = mGeometries.at( position.part )->insertVertex( position, vertex );
543  if ( success )
544  {
545  clearCache(); //set bounding box invalid
546  }
547  return success;
548 }
549 
551 {
552  if ( position.part < 0 || position.part >= mGeometries.size() )
553  {
554  return false;
555  }
556 
557  bool success = mGeometries.at( position.part )->moveVertex( position, newPos );
558  if ( success )
559  {
560  clearCache(); //set bounding box invalid
561  }
562  return success;
563 }
564 
566 {
567  if ( position.part < 0 || position.part >= mGeometries.size() )
568  {
569  return false;
570  }
571 
572  QgsAbstractGeometry *geom = mGeometries.at( position.part );
573  if ( !geom )
574  {
575  return false;
576  }
577 
578  bool success = geom->deleteVertex( position );
579 
580  //remove geometry if no vertices left
581  if ( geom->isEmpty() )
582  {
583  removeGeometry( position.part );
584  }
585 
586  if ( success )
587  {
588  clearCache(); //set bounding box invalid
589  }
590  return success;
591 }
592 
594 {
595  double length = 0.0;
596  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
597  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
598  {
599  length += ( *geomIt )->length();
600  }
601  return length;
602 }
603 
605 {
606  double area = 0.0;
607  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
608  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
609  {
610  area += ( *geomIt )->area();
611  }
612  return area;
613 }
614 
616 {
617  double perimeter = 0.0;
618  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
619  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
620  {
621  perimeter += ( *geomIt )->perimeter();
622  }
623  return perimeter;
624 }
625 
626 bool QgsGeometryCollection::fromCollectionWkt( const QString &wkt, const QVector<QgsAbstractGeometry *> &subtypes, const QString &defaultChildWkbType )
627 {
628  clear();
629 
630  QPair<QgsWkbTypes::Type, QString> parts = QgsGeometryUtils::wktReadBlock( wkt );
631 
632  if ( QgsWkbTypes::flatType( parts.first ) != QgsWkbTypes::flatType( wkbType() ) )
633  {
634  qDeleteAll( subtypes );
635  return false;
636  }
637  mWkbType = parts.first;
638 
639  QString defChildWkbType = QStringLiteral( "%1%2%3 " ).arg( defaultChildWkbType, is3D() ? QStringLiteral( "Z" ) : QString(), isMeasure() ? QStringLiteral( "M" ) : QString() );
640 
641  const QStringList blocks = QgsGeometryUtils::wktGetChildBlocks( parts.second, defChildWkbType );
642  for ( const QString &childWkt : blocks )
643  {
644  QPair<QgsWkbTypes::Type, QString> childParts = QgsGeometryUtils::wktReadBlock( childWkt );
645 
646  bool success = false;
647  for ( const QgsAbstractGeometry *geom : subtypes )
648  {
649  if ( QgsWkbTypes::flatType( childParts.first ) == QgsWkbTypes::flatType( geom->wkbType() ) )
650  {
651  mGeometries.append( geom->clone() );
652  if ( mGeometries.back()->fromWkt( childWkt ) )
653  {
654  success = true;
655  break;
656  }
657  }
658  }
659  if ( !success )
660  {
661  clear();
662  qDeleteAll( subtypes );
663  return false;
664  }
665  }
666  qDeleteAll( subtypes );
667 
668  //scan through geometries and check if dimensionality of geometries is different to collection.
669  //if so, update the type dimensionality of the collection to match
670  bool hasZ = false;
671  bool hasM = false;
672  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
673  {
674  hasZ = hasZ || geom->is3D();
675  hasM = hasM || geom->isMeasure();
676  if ( hasZ && hasM )
677  break;
678  }
679  if ( hasZ )
680  addZValue( 0 );
681  if ( hasM )
682  addMValue( 0 );
683 
684  return true;
685 }
686 
688 {
689  QVector< QgsAbstractGeometry * >::const_iterator it = mGeometries.constBegin();
690  for ( ; it != mGeometries.constEnd(); ++it )
691  {
692  if ( ( *it )->hasCurvedSegments() )
693  {
694  return true;
695  }
696  }
697  return false;
698 }
699 
701 {
702  std::unique_ptr< QgsAbstractGeometry > geom( QgsGeometryFactory::geomFromWkbType( mWkbType ) );
703  QgsGeometryCollection *geomCollection = qgsgeometry_cast<QgsGeometryCollection *>( geom.get() );
704  if ( !geomCollection )
705  {
706  return clone();
707  }
708 
709  QVector< QgsAbstractGeometry * >::const_iterator geomIt = mGeometries.constBegin();
710  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
711  {
712  geomCollection->addGeometry( ( *geomIt )->segmentize( tolerance, toleranceType ) );
713  }
714  return geom.release();
715 }
716 
718 {
719  if ( vertex.part < 0 || vertex.part >= mGeometries.size() )
720  {
721  return 0.0;
722  }
723 
724  QgsAbstractGeometry *geom = mGeometries[vertex.part];
725  if ( !geom )
726  {
727  return 0.0;
728  }
729 
730  return geom->vertexAngle( vertex );
731 }
732 
734 {
735  if ( startVertex.part < 0 || startVertex.part >= mGeometries.size() )
736  {
737  return 0.0;
738  }
739 
740  const QgsAbstractGeometry *geom = mGeometries[startVertex.part];
741  if ( !geom )
742  {
743  return 0.0;
744  }
745 
746  return geom->segmentLength( startVertex );
747 }
748 
749 int QgsGeometryCollection::vertexCount( int part, int ring ) const
750 {
751  if ( part < 0 || part >= mGeometries.size() )
752  {
753  return 0;
754  }
755 
756  return mGeometries[part]->vertexCount( 0, ring );
757 }
758 
759 int QgsGeometryCollection::ringCount( int part ) const
760 {
761  if ( part < 0 || part >= mGeometries.size() )
762  {
763  return 0;
764  }
765 
766  return mGeometries[part]->ringCount();
767 }
768 
770 {
771  return mGeometries.size();
772 }
773 
775 {
776  return mGeometries[id.part]->vertexAt( id );
777 }
778 
779 bool QgsGeometryCollection::isValid( QString &error, int flags ) const
780 {
781  if ( flags == 0 && mHasCachedValidity )
782  {
783  // use cached validity results
784  error = mValidityFailureReason;
785  return error.isEmpty();
786  }
787 
788  QgsGeos geos( this );
789  bool res = geos.isValid( &error, flags & QgsGeometry::FlagAllowSelfTouchingHoles, nullptr );
790  if ( flags == 0 )
791  {
792  mValidityFailureReason = !res ? error : QString();
793  mHasCachedValidity = true;
794  }
795  return res;
796 }
797 
798 bool QgsGeometryCollection::addZValue( double zValue )
799 {
800  if ( QgsWkbTypes::hasZ( mWkbType ) )
801  return false;
802 
804 
805  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
806  {
807  geom->addZValue( zValue );
808  }
809  clearCache();
810  return true;
811 }
812 
813 bool QgsGeometryCollection::addMValue( double mValue )
814 {
815  if ( QgsWkbTypes::hasM( mWkbType ) )
816  return false;
817 
819 
820  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
821  {
822  geom->addMValue( mValue );
823  }
824  clearCache();
825  return true;
826 }
827 
828 
830 {
832  return false;
833 
835  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
836  {
837  geom->dropZValue();
838  }
839  clearCache();
840  return true;
841 }
842 
844 {
846  return false;
847 
849  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
850  {
851  geom->dropMValue();
852  }
853  clearCache();
854  return true;
855 }
856 
857 void QgsGeometryCollection::filterVertices( const std::function<bool ( const QgsPoint & )> &filter )
858 {
859  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
860  {
861  if ( geom )
862  geom->filterVertices( filter );
863  }
864  clearCache();
865 }
866 
867 void QgsGeometryCollection::transformVertices( const std::function<QgsPoint( const QgsPoint & )> &transform )
868 {
869  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
870  {
871  if ( geom )
872  geom->transformVertices( transform );
873  }
874  clearCache();
875 }
876 
878 {
879  for ( QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
880  {
881  if ( geom )
882  geom->swapXy();
883  }
884  clearCache();
885 }
886 
888 {
889  std::unique_ptr< QgsGeometryCollection > newCollection( new QgsGeometryCollection() );
890  for ( QgsAbstractGeometry *geom : mGeometries )
891  {
892  newCollection->addGeometry( geom->toCurveType() );
893  }
894  return newCollection.release();
895 }
896 
898 {
899  return false;
900 }
901 
903 {
904  return mGeometries.count();
905 }
906 
908 {
909  if ( index < 0 || index > mGeometries.count() )
910  return nullptr;
911  return mGeometries.at( index );
912 }
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:1661
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:771
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:941
Multi surface geometry collection.
double length() const override
Returns the 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:356
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:892
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 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:867
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.
nlohmann::json json
Definition: qgsjsonutils.h:27
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
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:923
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 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:821
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:430
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.