QGIS API Documentation  3.13.0-Master (b73bd58cfb)
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  if ( !mLayer->isSpatial() )
301 
302  double xMin, yMin, xMax, yMax;
303  QgsRectangle bBox; //bounding box of the split line
304  QgsGeometry::OperationResult returnCode = QgsGeometry::OperationResult::Success;
305  QgsGeometry::OperationResult splitFunctionReturn; //return code of QgsGeometry::splitGeometry
306  int numberOfSplitFeatures = 0;
307 
308  QgsFeatureIterator features;
309  const QgsFeatureIds selectedIds = mLayer->selectedFeatureIds();
310 
311  if ( !selectedIds.isEmpty() ) //consider only the selected features if there is a selection
312  {
313  features = mLayer->getSelectedFeatures();
314  }
315  else //else consider all the feature that intersect the bounding box of the split line
316  {
317  if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) )
318  {
319  bBox.setXMinimum( xMin );
320  bBox.setYMinimum( yMin );
321  bBox.setXMaximum( xMax );
322  bBox.setYMaximum( yMax );
323  }
324  else
325  {
326  return QgsGeometry::OperationResult::InvalidInputGeometryType;
327  }
328 
329  if ( bBox.isEmpty() )
330  {
331  //if the bbox is a line, try to make a square out of it
332  if ( bBox.width() == 0.0 && bBox.height() > 0 )
333  {
334  bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
335  bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
336  }
337  else if ( bBox.height() == 0.0 && bBox.width() > 0 )
338  {
339  bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
340  bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
341  }
342  else
343  {
344  //If we have a single point, we still create a non-null box
345  double bufferDistance = 0.000001;
346  if ( mLayer->crs().isGeographic() )
347  bufferDistance = 0.00000001;
348  bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
349  bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
350  bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
351  bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
352  }
353  }
354 
355  features = mLayer->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
356  }
357 
358  QgsFeature feat;
359  while ( features.nextFeature( feat ) )
360  {
361  if ( !feat.hasGeometry() )
362  {
363  continue;
364  }
365  QVector<QgsGeometry> newGeometries;
366  QgsPointSequence topologyTestPoints;
367  QgsGeometry featureGeom = feat.geometry();
368  splitFunctionReturn = featureGeom.splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
369  if ( splitFunctionReturn == QgsGeometry::OperationResult::Success )
370  {
371  //change this geometry
372  mLayer->changeGeometry( feat.id(), featureGeom );
373 
374  //insert new features
375  QgsAttributeMap attributeMap = feat.attributes().toMap();
376  for ( const QgsGeometry &geom : qgis::as_const( newGeometries ) )
377  {
378  QgsFeature f = QgsVectorLayerUtils::createFeature( mLayer, geom, attributeMap );
379  mLayer->addFeature( f );
380  }
381 
382  if ( topologicalEditing )
383  {
384  QgsPointSequence::const_iterator topol_it = topologyTestPoints.constBegin();
385  for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
386  {
387  addTopologicalPoints( *topol_it );
388  }
389  }
390  ++numberOfSplitFeatures;
391  }
392  else if ( splitFunctionReturn != QgsGeometry::OperationResult::Success && splitFunctionReturn != QgsGeometry::NothingHappened ) // i.e. no split but no error occurred
393  {
394  returnCode = splitFunctionReturn;
395  }
396  }
397 
398  if ( numberOfSplitFeatures == 0 && !selectedIds.isEmpty() )
399  {
400  //There is a selection but no feature has been split.
401  //Maybe user forgot that only the selected features are split
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  for ( QMap<QgsFeatureId, int>::const_iterator it = segments.constBegin(); it != segments.constEnd(); ++it )
605  {
606  QgsFeatureId fid = it.key();
607  int segmentAfterVertex = it.value();
608  QgsGeometry geom = features[fid];
609 
610  int atVertex, beforeVertex, afterVertex;
611  double sqrDistVertexSnap;
612  geom.closestVertex( p, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
613 
614  if ( sqrDistVertexSnap < sqrSnappingTolerance )
615  continue; // the vertex already exists - do not insert it
616 
617  if ( !mLayer->insertVertex( p, fid, segmentAfterVertex ) )
618  {
619  QgsDebugMsg( QStringLiteral( "failed to insert topo point" ) );
620  }
621  }
622 
623  return 0;
624 }
625 
627 {
628  return addTopologicalPoints( QgsPoint( p ) );
629 }
630 
631 
632 bool QgsVectorLayerEditUtils::boundingBoxFromPointList( const QgsPointSequence &list, double &xmin, double &ymin, double &xmax, double &ymax ) const
633 {
634  if ( list.empty() )
635  {
636  return false;
637  }
638 
639  xmin = std::numeric_limits<double>::max();
640  xmax = -std::numeric_limits<double>::max();
641  ymin = std::numeric_limits<double>::max();
642  ymax = -std::numeric_limits<double>::max();
643 
644  for ( QgsPointSequence::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
645  {
646  if ( it->x() < xmin )
647  {
648  xmin = it->x();
649  }
650  if ( it->x() > xmax )
651  {
652  xmax = it->x();
653  }
654  if ( it->y() < ymin )
655  {
656  ymin = it->y();
657  }
658  if ( it->y() > ymax )
659  {
660  ymax = it->y();
661  }
662  }
663 
664  return true;
665 }
QgsGeometryOptions * geometryOptions() const
Configuration and logic to apply automatically on any edit happening on this layer.
QgsFeatureId id
Definition: qgsfeature.h:64
Wrapper for iterator of features from vector data provider or vector layer.
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.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
Q_DECL_DEPRECATED QgsGeometry::OperationResult splitParts(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
double y
Definition: qgspoint.h:42
The input ring doesn&#39;t have any existing ring to fit into.
Definition: qgsgeometry.h:151
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:34
OperationResult addPart(const QVector< QgsPointXY > &points, QgsWkbTypes::GeometryType geomType=QgsWkbTypes::UnknownGeometry)
Adds a new part to a the geometry.
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:135
Use exact geometry intersection (slower) instead of bounding boxes.
Nothing happened, without any error.
Definition: qgsgeometry.h:137
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
A class to represent a 2D point.
Definition: qgspointxy.h:43
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
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
double geometryPrecision() const
The precision in which geometries on this layer should be saved.
qint64 QgsFeatureId
Definition: qgsfeatureid.h:25
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...
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:122
OperationResult addRing(const QVector< QgsPointXY > &ring)
Adds a new ring to this geometry.
Edit operation resulted in an empty geometry.
int addTopologicalPoints(const QgsGeometry &geom)
Adds topological points for every vertex of the geometry.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
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...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
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...
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
OperationResult
Success or failure of a geometry operation.
Definition: qgsgeometry.h:134
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 ...
virtual bool doesStrictFeatureTypeCheck() const
Returns true if the provider is strict about the type of inserted features (e.g.
The selected geometry cannot be found.
Definition: qgsgeometry.h:145
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
bool changeGeometry(QgsFeatureId fid, QgsGeometry &geometry, bool skipDefaultValue=false)
Changes a feature&#39;s geometry within the layer&#39;s edit buffer (but does not immediately commit the chan...
bool convertToSingleType()
Converts multi type geometry into single type geometry e.g.
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:437
QgsFeatureIterator getSelectedFeatures(QgsFeatureRequest request=QgsFeatureRequest()) const
Returns an iterator of the selected features.
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:202
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:140
bool deleteVertex(int atVertex)
Deletes the vertex at the given position number and item (first number is index 0) ...
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.
Q_DECL_DEPRECATED QgsGeometry::OperationResult addPart(const QVector< QgsPointXY > &ring, QgsFeatureId featureId)
Adds a new part polygon to a multipart feature.
Q_DECL_DEPRECATED QgsGeometry::OperationResult splitFeatures(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:38
int translateFeature(QgsFeatureId featureId, double dx, double dy)
Translates feature by dx, dy.
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)...
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QgsAttributeMap toMap() const
Returns a QgsAttributeMap of the attribute values.
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
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.
Edit operation failed.
The vertex_iterator class provides STL-style iterator for vertices.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
static bool isSingleType(Type type)
Returns true if the WKB type is a single type.
Definition: qgswkbtypes.h:696
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:162
QVector< QgsPoint > QgsPointSequence
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)...
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
Definition: qgscurve.cpp:195
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
The base geometry on which the operation is done is invalid or empty.
Definition: qgsgeometry.h:138
Q_DECL_DEPRECATED QgsGeometry::OperationResult addRing(const QVector< QgsPointXY > &ring, const QgsFeatureIds &targetFeatureIds=QgsFeatureIds(), QgsFeatureId *modifiedFeatureId=nullptr)
Adds a ring to polygon/multipolygon features.
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:145
Edit operation was successful.
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:43
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=nullptr) FINAL
Adds a single feature to the sink.
QgsVectorLayer::EditResult deleteVertex(QgsFeatureId featureId, int vertex)
Deletes a vertex from a feature.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
OperationResult translate(double dx, double dy, double dz=0.0, double dm=0.0)
Translates this geometry by dx, dy, dz and dm.
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:172
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsGeometry geometry
Definition: qgsfeature.h:67
Edit failed due to invalid layer.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer&#39;s data provider, it may be nullptr.
bool nextFeature(QgsFeature &f)
Operation succeeded.
Definition: qgsgeometry.h:136
void set(QgsAbstractGeometry *geometry)
Sets the underlying geometry store.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
Represents a vector layer which manages a vector based data sets.
QgsAbstractGeometry::vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry...
EditResult
Result of an edit operation.
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
Unable to fetch requested feature.
QgsAttributes attributes
Definition: qgsfeature.h:65
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:130
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:88
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:209
QgsVectorLayerEditUtils(QgsVectorLayer *layer)
double x
Definition: qgspoint.h:41