QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsvectorlayereditutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorlayereditutils.cpp
3  ---------------------
4  begin : Dezember 2012
5  copyright : (C) 2012 by Martin Dobias
6  email : wonder dot sk at gmail 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  ***************************************************************************/
16 
17 #include "qgsvectordataprovider.h"
18 #include "qgsfeatureiterator.h"
20 #include "qgslinestring.h"
21 #include "qgslogger.h"
22 #include "qgspoint.h"
23 #include "qgsgeometryfactory.h"
24 #include "qgis.h"
25 #include "qgswkbtypes.h"
26 #include "qgsvectorlayerutils.h"
27 #include "qgsvectorlayer.h"
28 #include "qgsgeometryoptions.h"
29 #include "qgsabstractgeometry.h"
30 
31 #include <limits>
32 
33 
35  : mLayer( layer )
36 {
37 }
38 
39 bool QgsVectorLayerEditUtils::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
40 {
41  if ( !mLayer->isSpatial() )
42  return false;
43 
44  QgsFeature f;
45  if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setNoAttributes() ).nextFeature( f ) || !f.hasGeometry() )
46  return false; // geometry not found
47 
48  QgsGeometry geometry = f.geometry();
49 
50  geometry.insertVertex( x, y, beforeVertex );
51 
52  mLayer->changeGeometry( atFeatureId, geometry );
53  return true;
54 }
55 
56 bool QgsVectorLayerEditUtils::insertVertex( const QgsPoint &point, QgsFeatureId atFeatureId, int beforeVertex )
57 {
58  if ( !mLayer->isSpatial() )
59  return false;
60 
61  QgsFeature f;
62  if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setNoAttributes() ).nextFeature( f ) || !f.hasGeometry() )
63  return false; // geometry not found
64 
65  QgsGeometry geometry = f.geometry();
66 
67  geometry.insertVertex( point, beforeVertex );
68 
69  mLayer->changeGeometry( atFeatureId, geometry );
70  return true;
71 }
72 
73 bool QgsVectorLayerEditUtils::moveVertex( double x, double y, QgsFeatureId atFeatureId, int atVertex )
74 {
75  QgsPoint p( x, y );
76  return moveVertex( p, atFeatureId, atVertex );
77 }
78 
79 bool QgsVectorLayerEditUtils::moveVertex( const QgsPoint &p, QgsFeatureId atFeatureId, int atVertex )
80 {
81  if ( !mLayer->isSpatial() )
82  return false;
83 
84  QgsFeature f;
85  if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setNoAttributes() ).nextFeature( f ) || !f.hasGeometry() )
86  return false; // geometry not found
87 
88  QgsGeometry geometry = f.geometry();
89 
90  geometry.moveVertex( p, atVertex );
91 
92  mLayer->changeGeometry( atFeatureId, geometry );
93  return true;
94 }
95 
96 
98 {
99  if ( !mLayer->isSpatial() )
101 
102  QgsFeature f;
103  if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setNoAttributes() ).nextFeature( f ) || !f.hasGeometry() )
104  return QgsVectorLayer::FetchFeatureFailed; // geometry not found
105 
106  QgsGeometry geometry = f.geometry();
107 
108  if ( !geometry.deleteVertex( vertex ) )
110 
111  if ( geometry.constGet() && geometry.constGet()->nCoordinates() == 0 )
112  {
113  //last vertex deleted, set geometry to null
114  geometry.set( nullptr );
115  }
116 
117  mLayer->changeGeometry( featureId, geometry );
119 }
120 
121 QgsGeometry::OperationResult QgsVectorLayerEditUtils::addRing( const QVector<QgsPointXY> &ring, const QgsFeatureIds &targetFeatureIds, QgsFeatureId *modifiedFeatureId )
122 {
124  for ( QVector<QgsPointXY>::const_iterator it = ring.constBegin(); it != ring.constEnd(); ++it )
125  {
126  l << QgsPoint( *it );
127  }
128  return addRing( l, targetFeatureIds, modifiedFeatureId );
129 }
130 
132 {
133  QgsLineString *ringLine = new QgsLineString( ring );
134  return addRing( ringLine, targetFeatureIds, modifiedFeatureId );
135 }
136 
138 {
139  if ( !mLayer->isSpatial() )
140  {
141  delete ring;
143  }
144 
145  QgsGeometry::OperationResult addRingReturnCode = QgsGeometry::AddRingNotInExistingFeature; //default: return code for 'ring not inserted'
146  QgsFeature f;
147 
148  QgsFeatureIterator fit;
149  if ( !targetFeatureIds.isEmpty() )
150  {
151  //check only specified features
152  fit = mLayer->getFeatures( QgsFeatureRequest().setFilterFids( targetFeatureIds ) );
153  }
154  else
155  {
156  //check all intersecting features
157  QgsRectangle bBox = ring->boundingBox();
158  fit = mLayer->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
159  }
160 
161  //find first valid feature we can add the ring to
162  while ( fit.nextFeature( f ) )
163  {
164  if ( !f.hasGeometry() )
165  continue;
166 
167  //add ring takes ownership of ring, and deletes it if there's an error
168  QgsGeometry g = f.geometry();
169 
170  addRingReturnCode = g.addRing( static_cast< QgsCurve * >( ring->clone() ) );
171  if ( addRingReturnCode == 0 )
172  if ( addRingReturnCode == QgsGeometry::Success )
173  {
174  mLayer->changeGeometry( f.id(), g );
175  if ( modifiedFeatureId )
176  *modifiedFeatureId = f.id();
177 
178  //setModified( true, true );
179  break;
180  }
181  }
182 
183  delete ring;
184  return addRingReturnCode;
185 }
186 
187 QgsGeometry::OperationResult QgsVectorLayerEditUtils::addPart( const QVector<QgsPointXY> &points, QgsFeatureId featureId )
188 {
190  for ( QVector<QgsPointXY>::const_iterator it = points.constBegin(); it != points.constEnd(); ++it )
191  {
192  l << QgsPoint( *it );
193  }
194  return addPart( l, featureId );
195 }
196 
198 {
199  if ( !mLayer->isSpatial() )
200  return QgsGeometry::OperationResult::AddPartSelectedGeometryNotFound;
201 
202  QgsGeometry geometry;
203  bool firstPart = false;
204  QgsFeature f;
205  if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setNoAttributes() ).nextFeature( f ) )
206  return QgsGeometry::OperationResult::AddPartSelectedGeometryNotFound; //not found
207 
208  if ( !f.hasGeometry() )
209  {
210  //no existing geometry, so adding first part to null geometry
211  firstPart = true;
212  }
213  else
214  {
215  geometry = f.geometry();
216  }
217 
218  QgsGeometry::OperationResult errorCode = geometry.addPart( points, mLayer->geometryType() );
219  if ( errorCode == QgsGeometry::Success )
220  {
221  if ( firstPart && QgsWkbTypes::isSingleType( mLayer->wkbType() )
222  && mLayer->dataProvider()->doesStrictFeatureTypeCheck() )
223  {
224  //convert back to single part if required by layer
225  geometry.convertToSingleType();
226  }
227  mLayer->changeGeometry( featureId, geometry );
228  }
229  return errorCode;
230 }
231 
233 {
234  if ( !mLayer->isSpatial() )
236 
237  QgsGeometry geometry;
238  bool firstPart = false;
239  QgsFeature f;
240  if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setNoAttributes() ).nextFeature( f ) )
242 
243  if ( !f.hasGeometry() )
244  {
245  //no existing geometry, so adding first part to null geometry
246  firstPart = true;
247  }
248  else
249  {
250  geometry = f.geometry();
251  }
252 
253  QgsGeometry::OperationResult errorCode = geometry.addPart( ring, mLayer->geometryType() );
254  if ( errorCode == QgsGeometry::Success )
255  {
256  if ( firstPart && QgsWkbTypes::isSingleType( mLayer->wkbType() )
257  && mLayer->dataProvider()->doesStrictFeatureTypeCheck() )
258  {
259  //convert back to single part if required by layer
260  geometry.convertToSingleType();
261  }
262  mLayer->changeGeometry( featureId, geometry );
263  }
264  return errorCode;
265 }
266 
267 
268 int QgsVectorLayerEditUtils::translateFeature( QgsFeatureId featureId, double dx, double dy )
269 {
270  if ( !mLayer->isSpatial() )
271  return 1;
272 
273  QgsFeature f;
274  if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setNoAttributes() ).nextFeature( f ) || !f.hasGeometry() )
275  return 1; //geometry not found
276 
277  QgsGeometry geometry = f.geometry();
278 
279  int errorCode = geometry.translate( dx, dy );
280  if ( errorCode == 0 )
281  {
282  mLayer->changeGeometry( featureId, geometry );
283  }
284  return errorCode;
285 }
286 
287 QgsGeometry::OperationResult QgsVectorLayerEditUtils::splitFeatures( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
288 {
290  for ( QVector<QgsPointXY>::const_iterator it = splitLine.constBegin(); it != splitLine.constEnd(); ++it )
291  {
292  l << QgsPoint( *it );
293  }
294  return splitFeatures( l, topologicalEditing );
295 }
296 
298 {
299  QgsLineString lineString( splitLine );
300  QgsPointSequence topologyTestPoints;
301  bool preserveCircular = false;
302  return splitFeatures( &lineString, topologyTestPoints, preserveCircular, topologicalEditing );
303 }
304 
305 QgsGeometry::OperationResult QgsVectorLayerEditUtils::splitFeatures( const QgsCurve *curve, QgsPointSequence &topologyTestPoints, bool preserveCircular, bool topologicalEditing )
306 {
307  if ( !mLayer->isSpatial() )
309 
310  QgsRectangle bBox; //bounding box of the split line
311  QgsGeometry::OperationResult returnCode = QgsGeometry::OperationResult::Success;
312  QgsGeometry::OperationResult splitFunctionReturn; //return code of QgsGeometry::splitGeometry
313  int numberOfSplitFeatures = 0;
314 
315  QgsFeatureIterator features;
316  const QgsFeatureIds selectedIds = mLayer->selectedFeatureIds();
317 
318  // deactivate preserving circular if the curve contains only straight segments to avoid transforming Polygon to CurvePolygon
319  preserveCircular &= curve->hasCurvedSegments();
320 
321  if ( !selectedIds.isEmpty() ) //consider only the selected features if there is a selection
322  {
323  features = mLayer->getSelectedFeatures();
324  }
325  else //else consider all the feature that intersect the bounding box of the split line
326  {
327 
328  bBox = curve->boundingBox();
329 
330  if ( bBox.isEmpty() )
331  {
332  //if the bbox is a line, try to make a square out of it
333  if ( bBox.width() == 0.0 && bBox.height() > 0 )
334  {
335  bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
336  bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
337  }
338  else if ( bBox.height() == 0.0 && bBox.width() > 0 )
339  {
340  bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
341  bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
342  }
343  else
344  {
345  //If we have a single point, we still create a non-null box
346  double bufferDistance = 0.000001;
347  if ( mLayer->crs().isGeographic() )
348  bufferDistance = 0.00000001;
349  bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
350  bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
351  bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
352  bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
353  }
354  }
355 
356  features = mLayer->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
357  }
358 
359  QgsFeature feat;
360  while ( features.nextFeature( feat ) )
361  {
362  if ( !feat.hasGeometry() )
363  {
364  continue;
365  }
366  QVector<QgsGeometry> newGeometries;
367  QgsPointSequence featureTopologyTestPoints;
368  QgsGeometry featureGeom = feat.geometry();
369  splitFunctionReturn = featureGeom.splitGeometry( curve, newGeometries, preserveCircular, topologicalEditing, featureTopologyTestPoints );
370  topologyTestPoints.append( featureTopologyTestPoints );
371  if ( splitFunctionReturn == QgsGeometry::OperationResult::Success )
372  {
373  //change this geometry
374  mLayer->changeGeometry( feat.id(), featureGeom );
375 
376  //insert new features
377  QgsAttributeMap attributeMap = feat.attributes().toMap();
378  for ( const QgsGeometry &geom : qgis::as_const( newGeometries ) )
379  {
380  QgsFeature f = QgsVectorLayerUtils::createFeature( mLayer, geom, attributeMap );
381  mLayer->addFeature( f );
382  }
383 
384  if ( topologicalEditing )
385  {
386  QgsPointSequence::const_iterator topol_it = featureTopologyTestPoints.constBegin();
387  for ( ; topol_it != featureTopologyTestPoints.constEnd(); ++topol_it )
388  {
389  addTopologicalPoints( *topol_it );
390  }
391  }
392  ++numberOfSplitFeatures;
393  }
394  else if ( splitFunctionReturn != QgsGeometry::OperationResult::Success && splitFunctionReturn != QgsGeometry::NothingHappened ) // i.e. no split but no error occurred
395  {
396  returnCode = splitFunctionReturn;
397  }
398  }
399 
400  if ( numberOfSplitFeatures == 0 )
401  {
402  returnCode = QgsGeometry::OperationResult::NothingHappened;
403  }
404 
405  return returnCode;
406 }
407 
408 QgsGeometry::OperationResult QgsVectorLayerEditUtils::splitParts( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
409 {
411  for ( QVector<QgsPointXY>::const_iterator it = splitLine.constBegin(); it != splitLine.constEnd(); ++it )
412  {
413  l << QgsPoint( *it );
414  }
415  return splitParts( l, topologicalEditing );
416 }
417 
419 {
420  if ( !mLayer->isSpatial() )
422 
423  double xMin, yMin, xMax, yMax;
424  QgsRectangle bBox; //bounding box of the split line
425  QgsGeometry::OperationResult returnCode = QgsGeometry::OperationResult::Success;
426  QgsGeometry::OperationResult splitFunctionReturn; //return code of QgsGeometry::splitGeometry
427  int numberOfSplitParts = 0;
428 
429  QgsFeatureIterator fit;
430 
431  if ( mLayer->selectedFeatureCount() > 0 ) //consider only the selected features if there is a selection
432  {
433  fit = mLayer->getSelectedFeatures();
434  }
435  else //else consider all the feature that intersect the bounding box of the split line
436  {
437  if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) )
438  {
439  bBox.setXMinimum( xMin );
440  bBox.setYMinimum( yMin );
441  bBox.setXMaximum( xMax );
442  bBox.setYMaximum( yMax );
443  }
444  else
445  {
446  return QgsGeometry::OperationResult::InvalidInputGeometryType;
447  }
448 
449  if ( bBox.isEmpty() )
450  {
451  //if the bbox is a line, try to make a square out of it
452  if ( bBox.width() == 0.0 && bBox.height() > 0 )
453  {
454  bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
455  bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
456  }
457  else if ( bBox.height() == 0.0 && bBox.width() > 0 )
458  {
459  bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
460  bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
461  }
462  else
463  {
464  //If we have a single point, we still create a non-null box
465  double bufferDistance = 0.000001;
466  if ( mLayer->crs().isGeographic() )
467  bufferDistance = 0.00000001;
468  bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
469  bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
470  bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
471  bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
472  }
473  }
474 
475  fit = mLayer->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
476  }
477 
478  QgsFeature feat;
479  while ( fit.nextFeature( feat ) )
480  {
481  QVector<QgsGeometry> newGeometries;
482  QgsPointSequence topologyTestPoints;
483  QgsGeometry featureGeom = feat.geometry();
484  splitFunctionReturn = featureGeom.splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints, false );
485 
486  if ( splitFunctionReturn == QgsGeometry::OperationResult::Success && !newGeometries.isEmpty() )
487  {
488  QgsGeometry newGeom( newGeometries.at( 0 ) );
489  newGeom.convertToMultiType();
490 
491  for ( int i = 1; i < newGeometries.size(); ++i )
492  {
493  QgsGeometry part = newGeometries.at( i );
494  part.convertToSingleType();
495  newGeom.addPart( part );
496  }
497 
498  mLayer->changeGeometry( feat.id(), newGeom );
499 
500  if ( topologicalEditing )
501  {
502  QgsPointSequence::const_iterator topol_it = topologyTestPoints.constBegin();
503  for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
504  {
505  addTopologicalPoints( *topol_it );
506  }
507  }
508  ++numberOfSplitParts;
509  }
510  else if ( splitFunctionReturn != QgsGeometry::OperationResult::Success && splitFunctionReturn != QgsGeometry::OperationResult::NothingHappened )
511  {
512  returnCode = splitFunctionReturn;
513  }
514  }
515 
516  if ( numberOfSplitParts == 0 && mLayer->selectedFeatureCount() > 0 && returnCode == QgsGeometry::Success )
517  {
518  //There is a selection but no feature has been split.
519  //Maybe user forgot that only the selected features are split
520  returnCode = QgsGeometry::OperationResult::NothingHappened;
521  }
522 
523  return returnCode;
524 }
525 
526 
528 {
529  if ( !mLayer->isSpatial() )
530  return 1;
531 
532  if ( geom.isNull() )
533  {
534  return 1;
535  }
536 
537  int returnVal = 0;
538 
540  while ( it != geom.vertices_end() )
541  {
542  if ( addTopologicalPoints( *it ) != 0 )
543  {
544  returnVal = 2;
545  }
546  ++it;
547  }
548 
549  return returnVal;
550 }
551 
553 {
554  if ( !mLayer->isSpatial() )
555  return 1;
556 
557  double segmentSearchEpsilon = mLayer->crs().isGeographic() ? 1e-12 : 1e-8;
558 
559  //work with a tolerance because coordinate projection may introduce some rounding
560  double threshold = mLayer->geometryOptions()->geometryPrecision();
561 
562  if ( qgsDoubleNear( threshold, 0.0 ) )
563  {
564  threshold = 0.0000001;
565 
566  if ( mLayer->crs().mapUnits() == QgsUnitTypes::DistanceMeters )
567  {
568  threshold = 0.001;
569  }
570  else if ( mLayer->crs().mapUnits() == QgsUnitTypes::DistanceFeet )
571  {
572  threshold = 0.0001;
573  }
574  }
575 
576  QgsRectangle searchRect( p.x() - threshold, p.y() - threshold,
577  p.x() + threshold, p.y() + threshold );
578  double sqrSnappingTolerance = threshold * threshold;
579 
580  QgsFeature f;
582  .setFilterRect( searchRect )
584  .setNoAttributes() );
585 
586  QMap<QgsFeatureId, QgsGeometry> features;
587  QMap<QgsFeatureId, int> segments;
588 
589  while ( fit.nextFeature( f ) )
590  {
591  int afterVertex;
592  QgsPointXY snappedPoint;
593  double sqrDistSegmentSnap = f.geometry().closestSegmentWithContext( p, snappedPoint, afterVertex, nullptr, segmentSearchEpsilon );
594  if ( sqrDistSegmentSnap < sqrSnappingTolerance )
595  {
596  segments[f.id()] = afterVertex;
597  features[f.id()] = f.geometry();
598  }
599  }
600 
601  if ( segments.isEmpty() )
602  return 2;
603 
604  bool pointsAdded = false;
605  for ( QMap<QgsFeatureId, int>::const_iterator it = segments.constBegin(); it != segments.constEnd(); ++it )
606  {
607  QgsFeatureId fid = it.key();
608  int segmentAfterVertex = it.value();
609  QgsGeometry geom = features[fid];
610 
611  int atVertex, beforeVertex, afterVertex;
612  double sqrDistVertexSnap;
613  geom.closestVertex( p, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
614 
615  if ( sqrDistVertexSnap < sqrSnappingTolerance )
616  continue; // the vertex already exists - do not insert it
617 
618  if ( !mLayer->insertVertex( p, fid, segmentAfterVertex ) )
619  {
620  QgsDebugMsg( QStringLiteral( "failed to insert topo point" ) );
621  }
622  else
623  {
624  pointsAdded = true;
625  }
626  }
627 
628  return pointsAdded ? 0 : 2;
629 }
630 
632 {
633  if ( !mLayer->isSpatial() )
634  return 1;
635 
636  if ( ps.isEmpty() )
637  {
638  return 1;
639  }
640 
641  bool pointsAdded = false;
642 
643  QgsPointSequence::const_iterator it = ps.constBegin();
644  while ( it != ps.constEnd() )
645  {
646  if ( addTopologicalPoints( *it ) == 0 )
647  {
648  pointsAdded = true;
649  }
650  ++it;
651  }
652 
653  return pointsAdded ? 0 : 2;
654 }
655 
657 {
658  return addTopologicalPoints( QgsPoint( p ) );
659 }
660 
661 
662 bool QgsVectorLayerEditUtils::boundingBoxFromPointList( const QgsPointSequence &list, double &xmin, double &ymin, double &xmax, double &ymax ) const
663 {
664  if ( list.empty() )
665  {
666  return false;
667  }
668 
669  xmin = std::numeric_limits<double>::max();
670  xmax = -std::numeric_limits<double>::max();
671  ymin = std::numeric_limits<double>::max();
672  ymax = -std::numeric_limits<double>::max();
673 
674  for ( QgsPointSequence::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
675  {
676  if ( it->x() < xmin )
677  {
678  xmin = it->x();
679  }
680  if ( it->x() > xmax )
681  {
682  xmax = it->x();
683  }
684  if ( it->y() < ymin )
685  {
686  ymin = it->y();
687  }
688  if ( it->y() > ymax )
689  {
690  ymax = it->y();
691  }
692  }
693 
694  return true;
695 }
QgsCurve
Abstract base class for curved geometry type.
Definition: qgscurve.h:36
QgsGeometry::Success
@ Success
Operation succeeded.
Definition: qgsgeometry.h:137
QgsVectorLayer::getFeatures
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
Definition: qgsvectorlayer.cpp:993
QgsWkbTypes::isSingleType
static bool isSingleType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a single type.
Definition: qgswkbtypes.h:822
QgsMapLayer::crs
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:89
QgsGeometryOptions::geometryPrecision
double geometryPrecision() const
The precision in which geometries on this layer should be saved.
Definition: qgsgeometryoptions.cpp:40
QgsRectangle::height
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:209
QgsFeature::id
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
QgsGeometry::addPart
OperationResult addPart(const QVector< QgsPointXY > &points, QgsWkbTypes::GeometryType geomType=QgsWkbTypes::UnknownGeometry)
Adds a new part to a the geometry.
Definition: qgsgeometry.cpp:699
QgsVectorLayer::wkbType
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
Definition: qgsvectorlayer.cpp:664
QgsCoordinateReferenceSystem::mapUnits
Q_GADGET QgsUnitTypes::DistanceUnit mapUnits
Definition: qgscoordinatereferencesystem.h:209
QgsVectorLayerEditUtils::splitParts
Q_DECL_DEPRECATED QgsGeometry::OperationResult splitParts(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
Definition: qgsvectorlayereditutils.cpp:408
qgslinestring.h
QgsFeatureRequest::ExactIntersect
@ ExactIntersect
Use exact geometry intersection (slower) instead of bounding boxes.
Definition: qgsfeaturerequest.h:83
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:38
QgsVectorLayer::insertVertex
bool insertVertex(double x, double y, QgsFeatureId atFeatureId, int beforeVertex)
Inserts a new vertex before the given vertex number, in the given ring, item (first number is index 0...
Definition: qgsvectorlayer.cpp:1095
qgsgeometryfactory.h
QgsGeometry::isNull
Q_GADGET bool isNull
Definition: qgsgeometry.h:126
QgsGeometry::NothingHappened
@ NothingHappened
Nothing happened, without any error.
Definition: qgsgeometry.h:138
qgsfeatureiterator.h
QgsRectangle::yMinimum
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
QgsVectorLayer::geometryOptions
QgsGeometryOptions * geometryOptions() const
Configuration and logic to apply automatically on any edit happening on this layer.
Definition: qgsvectorlayer.cpp:5595
QgsGeometry::addRing
OperationResult addRing(const QVector< QgsPointXY > &ring)
Adds a new ring to this geometry.
Definition: qgsgeometry.cpp:680
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:67
qgis.h
QgsVectorLayer::isSpatial
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
Definition: qgsvectorlayer.cpp:3599
qgsvectorlayereditutils.h
QgsVectorDataProvider::doesStrictFeatureTypeCheck
virtual bool doesStrictFeatureTypeCheck() const
Returns true if the provider is strict about the type of inserted features (e.g.
Definition: qgsvectordataprovider.h:493
QgsGeometry::OperationResult
OperationResult
Success or failure of a geometry operation.
Definition: qgsgeometry.h:136
qgspoint.h
QgsGeometry::moveVertex
bool moveVertex(double x, double y, int atVertex)
Moves the vertex at the given position number and item (first number is index 0) to the given coordin...
Definition: qgsgeometry.cpp:467
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsLineString
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:44
QgsGeometry::closestVertex
QgsPointXY closestVertex(const QgsPointXY &point, int &atVertex, int &beforeVertex, int &afterVertex, double &sqrDist) const
Returns the vertex closest to the given point, the corresponding vertex index, squared distance snap ...
Definition: qgsgeometry.cpp:386
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QgsVectorLayerEditUtils::addTopologicalPoints
int addTopologicalPoints(const QgsGeometry &geom)
Adds topological points for every vertex of the geometry.
Definition: qgsvectorlayereditutils.cpp:527
QgsGeometry::insertVertex
bool insertVertex(double x, double y, int beforeVertex)
Insert a new vertex before the given vertex index, ring and item (first number is index 0) If the req...
Definition: qgsgeometry.cpp:536
QgsGeometry::AddPartSelectedGeometryNotFound
@ AddPartSelectedGeometryNotFound
The selected geometry cannot be found.
Definition: qgsgeometry.h:146
QgsVectorLayer::changeGeometry
bool changeGeometry(QgsFeatureId fid, QgsGeometry &geometry, bool skipDefaultValue=false)
Changes a feature's geometry within the layer's edit buffer (but does not immediately commit the chan...
Definition: qgsvectorlayer.cpp:2942
QgsRectangle::xMaximum
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:162
QgsPoint::y
double y
Definition: qgspoint.h:42
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:76
QgsCoordinateReferenceSystem::isGeographic
bool isGeographic
Definition: qgscoordinatereferencesystem.h:210
QgsVectorLayer::EmptyGeometry
@ EmptyGeometry
Edit operation resulted in an empty geometry.
Definition: qgsvectorlayer.h:403
QgsVectorLayer::EditFailed
@ EditFailed
Edit operation failed.
Definition: qgsvectorlayer.h:404
QgsVectorLayerEditUtils::addPart
Q_DECL_DEPRECATED QgsGeometry::OperationResult addPart(const QVector< QgsPointXY > &ring, QgsFeatureId featureId)
Adds a new part polygon to a multipart feature.
Definition: qgsvectorlayereditutils.cpp:187
QgsVectorLayerEditUtils::translateFeature
int translateFeature(QgsFeatureId featureId, double dx, double dy)
Translates feature by dx, dy.
Definition: qgsvectorlayereditutils.cpp:268
QgsVectorLayerEditUtils::moveVertex
bool moveVertex(double x, double y, QgsFeatureId atFeatureId, int atVertex)
Moves the vertex at the given position number, ring and item (first number is index 0),...
Definition: qgsvectorlayereditutils.cpp:73
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:315
QgsGeometry::convertToSingleType
bool convertToSingleType()
Converts multi type geometry into single type geometry e.g.
Definition: qgsgeometry.cpp:1485
QgsVectorLayer::selectedFeatureIds
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
Definition: qgsvectorlayer.cpp:3441
QgsGeometry::deleteVertex
bool deleteVertex(int atVertex)
Deletes the vertex at the given position number and item (first number is index 0)
Definition: qgsgeometry.cpp:503
qgsvectordataprovider.h
QgsAttributeMap
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:38
QgsUnitTypes::DistanceFeet
@ DistanceFeet
Imperial feet.
Definition: qgsunittypes.h:71
QgsRectangle::setXMinimum
void setXMinimum(double x) SIP_HOLDGIL
Set the minimum x value.
Definition: qgsrectangle.h:130
QgsPoint::x
Q_GADGET double x
Definition: qgspoint.h:41
qgsvectorlayerutils.h
QgsUnitTypes::DistanceMeters
@ DistanceMeters
Meters.
Definition: qgsunittypes.h:69
QgsAbstractGeometry::nCoordinates
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
Definition: qgsabstractgeometry.cpp:116
QgsAbstractGeometry::hasCurvedSegments
virtual bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
Definition: qgsabstractgeometry.cpp:305
QgsRectangle::xMinimum
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
QgsAttributes::toMap
QgsAttributeMap toMap() const
Returns a QgsAttributeMap of the attribute values.
Definition: qgsattributes.cpp:21
QgsGeometry::splitGeometry
Q_DECL_DEPRECATED OperationResult splitGeometry(const QVector< QgsPointXY > &splitLine, QVector< QgsGeometry > &newGeometries, bool topological, QVector< QgsPointXY > &topologyTestPoints, bool splitFeature=true)
Splits this geometry according to a given line.
Definition: qgsgeometry.cpp:831
QgsGeometry::constGet
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Definition: qgsgeometry.cpp:128
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
QgsFeature::attributes
QgsAttributes attributes
Definition: qgsfeature.h:65
QgsRectangle::setXMaximum
void setXMaximum(double x) SIP_HOLDGIL
Set the maximum x value.
Definition: qgsrectangle.h:135
QgsVectorLayerUtils::createFeature
static QgsFeature createFeature(const QgsVectorLayer *layer, const QgsGeometry &geometry=QgsGeometry(), const QgsAttributeMap &attributes=QgsAttributeMap(), QgsExpressionContext *context=nullptr)
Creates a new feature ready for insertion into a layer.
Definition: qgsvectorlayerutils.cpp:476
QgsVectorLayerEditUtils::splitFeatures
Q_DECL_DEPRECATED QgsGeometry::OperationResult splitFeatures(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
Definition: qgsvectorlayereditutils.cpp:287
qgsvectorlayer.h
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:44
QgsRectangle::setYMaximum
void setYMaximum(double y) SIP_HOLDGIL
Set the maximum y value.
Definition: qgsrectangle.h:145
QgsCurve::clone
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
QgsVectorLayer::getSelectedFeatures
QgsFeatureIterator getSelectedFeatures(QgsFeatureRequest request=QgsFeatureRequest()) const
Returns an iterator of the selected features.
Definition: qgsvectorlayer.cpp:3476
QgsRectangle::yMaximum
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:172
QgsAbstractGeometry::vertex_iterator
The vertex_iterator class provides STL-style iterator for vertices.
Definition: qgsabstractgeometry.h:856
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:374
QgsRectangle::setYMinimum
void setYMinimum(double y) SIP_HOLDGIL
Set the minimum y value.
Definition: qgsrectangle.h:140
QgsPointSequence
QVector< QgsPoint > QgsPointSequence
Definition: qgsabstractgeometry.h:46
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
QgsGeometry::InvalidBaseGeometry
@ InvalidBaseGeometry
The base geometry on which the operation is done is invalid or empty.
Definition: qgsgeometry.h:139
QgsFeature::hasGeometry
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:199
QgsRectangle::width
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:202
QgsVectorLayerEditUtils::insertVertex
bool insertVertex(double x, double y, QgsFeatureId atFeatureId, int beforeVertex)
Insert a new vertex before the given vertex number, in the given ring, item (first number is index 0)...
Definition: qgsvectorlayereditutils.cpp:39
QgsGeometry::convertToMultiType
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
Definition: qgsgeometry.cpp:1453
QgsGeometry::translate
OperationResult translate(double dx, double dy, double dz=0.0, double dm=0.0)
Translates this geometry by dx, dy, dz and dm.
Definition: qgsgeometry.cpp:802
QgsCurve::boundingBox
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
Definition: qgscurve.cpp:202
QgsVectorLayer::dataProvider
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
Definition: qgsvectorlayer.cpp:627
QgsVectorLayer::FetchFeatureFailed
@ FetchFeatureFailed
Unable to fetch requested feature.
Definition: qgsvectorlayer.h:405
QgsVectorLayer::InvalidLayer
@ InvalidLayer
Edit failed due to invalid layer.
Definition: qgsvectorlayer.h:406
QgsVectorLayerEditUtils::QgsVectorLayerEditUtils
QgsVectorLayerEditUtils(QgsVectorLayer *layer)
Definition: qgsvectorlayereditutils.cpp:34
QgsFeature
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
qgsgeometryoptions.h
QgsGeometry::vertices_end
QgsAbstractGeometry::vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
Definition: qgsgeometry.cpp:1843
QgsVectorLayerEditUtils::addRing
Q_DECL_DEPRECATED QgsGeometry::OperationResult addRing(const QVector< QgsPointXY > &ring, const QgsFeatureIds &targetFeatureIds=QgsFeatureIds(), QgsFeatureId *modifiedFeatureId=nullptr)
Adds a ring to polygon/multipolygon features.
Definition: qgsvectorlayereditutils.cpp:121
QgsVectorLayer::selectedFeatureCount
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Definition: qgsvectorlayer.cpp:3436
QgsVectorLayer::EditResult
EditResult
Result of an edit operation.
Definition: qgsvectorlayer.h:401
qgslogger.h
QgsGeometry::vertices_begin
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
Definition: qgsgeometry.cpp:1836
QgsVectorLayer::Success
@ Success
Edit operation was successful.
Definition: qgsvectorlayer.h:402
QgsFeatureIterator
Wrapper for iterator of features from vector data provider or vector layer.
Definition: qgsfeatureiterator.h:265
QgsVectorLayer::geometryType
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
Definition: qgsvectorlayer.cpp:659
QgsVectorLayer::addFeature
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a single feature to the sink.
Definition: qgsvectorlayer.cpp:1011
QgsRectangle::isEmpty
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:437
qgswkbtypes.h
qgsabstractgeometry.h
QgsGeometry::AddRingNotInExistingFeature
@ AddRingNotInExistingFeature
The input ring doesn't have any existing ring to fit into.
Definition: qgsgeometry.h:152
QgsGeometry::set
void set(QgsAbstractGeometry *geometry)
Sets the underlying geometry store.
Definition: qgsgeometry.cpp:139
qgsvectorlayereditbuffer.h
QgsVectorLayerEditUtils::deleteVertex
QgsVectorLayer::EditResult deleteVertex(QgsFeatureId featureId, int vertex)
Deletes a vertex from a feature.
Definition: qgsvectorlayereditutils.cpp:97
QgsGeometry::closestSegmentWithContext
double closestSegmentWithContext(const QgsPointXY &point, QgsPointXY &minDistPoint, int &afterVertex, int *leftOf=nullptr, double epsilon=DEFAULT_SEGMENT_EPSILON) const
Searches for the closest segment of geometry to the given point.
Definition: qgsgeometry.cpp:656
QgsFeatureId
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28