QGIS API Documentation  2.99.0-Master (cd0ba91)
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 
28 #include <limits>
29 
30 
32  : mLayer( layer )
33 {
34 }
35 
36 bool QgsVectorLayerEditUtils::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
37 {
38  if ( !mLayer->isSpatial() )
39  return false;
40 
41  QgsFeature f;
42  if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.hasGeometry() )
43  return false; // geometry not found
44 
45  QgsGeometry geometry = f.geometry();
46 
47  geometry.insertVertex( x, y, beforeVertex );
48 
49  mLayer->editBuffer()->changeGeometry( atFeatureId, geometry );
50  return true;
51 }
52 
53 bool QgsVectorLayerEditUtils::insertVertex( const QgsPoint &point, QgsFeatureId atFeatureId, int beforeVertex )
54 {
55  if ( !mLayer->isSpatial() )
56  return false;
57 
58  QgsFeature f;
59  if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.hasGeometry() )
60  return false; // geometry not found
61 
62  QgsGeometry geometry = f.geometry();
63 
64  geometry.insertVertex( point, beforeVertex );
65 
66  mLayer->editBuffer()->changeGeometry( atFeatureId, geometry );
67  return true;
68 }
69 
70 bool QgsVectorLayerEditUtils::moveVertex( double x, double y, QgsFeatureId atFeatureId, int atVertex )
71 {
72  QgsPoint p( x, y );
73  return moveVertex( p, atFeatureId, atVertex );
74 }
75 
76 bool QgsVectorLayerEditUtils::moveVertex( const QgsPoint &p, QgsFeatureId atFeatureId, int atVertex )
77 {
78  if ( !mLayer->isSpatial() )
79  return false;
80 
81  QgsFeature f;
82  if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.hasGeometry() )
83  return false; // geometry not found
84 
85  QgsGeometry geometry = f.geometry();
86 
87  geometry.moveVertex( p, atVertex );
88 
89  mLayer->editBuffer()->changeGeometry( atFeatureId, geometry );
90  return true;
91 }
92 
93 
95 {
96  if ( !mLayer->isSpatial() )
98 
99  QgsFeature f;
100  if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.hasGeometry() )
101  return QgsVectorLayer::FetchFeatureFailed; // geometry not found
102 
103  QgsGeometry geometry = f.geometry();
104 
105  if ( !geometry.deleteVertex( vertex ) )
107 
108  if ( geometry.constGet() && geometry.constGet()->nCoordinates() == 0 )
109  {
110  //last vertex deleted, set geometry to null
111  geometry.set( nullptr );
112  }
113 
114  mLayer->editBuffer()->changeGeometry( featureId, geometry );
116 }
117 
118 QgsGeometry::OperationResult QgsVectorLayerEditUtils::addRing( const QVector<QgsPointXY> &ring, const QgsFeatureIds &targetFeatureIds, QgsFeatureId *modifiedFeatureId )
119 {
120  QgsLineString *ringLine = new QgsLineString( ring );
121  return addRing( ringLine, targetFeatureIds, modifiedFeatureId );
122 }
123 
125 {
126  if ( !mLayer->isSpatial() )
127  {
128  delete ring;
130  }
131 
132  QgsGeometry::OperationResult addRingReturnCode = QgsGeometry::AddRingNotInExistingFeature; //default: return code for 'ring not inserted'
133  QgsFeature f;
134 
135  QgsFeatureIterator fit;
136  if ( !targetFeatureIds.isEmpty() )
137  {
138  //check only specified features
139  fit = mLayer->getFeatures( QgsFeatureRequest().setFilterFids( targetFeatureIds ) );
140  }
141  else
142  {
143  //check all intersecting features
144  QgsRectangle bBox = ring->boundingBox();
145  fit = mLayer->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
146  }
147 
148  //find first valid feature we can add the ring to
149  while ( fit.nextFeature( f ) )
150  {
151  if ( !f.hasGeometry() )
152  continue;
153 
154  //add ring takes ownership of ring, and deletes it if there's an error
155  QgsGeometry g = f.geometry();
156 
157  addRingReturnCode = g.addRing( static_cast< QgsCurve * >( ring->clone() ) );
158  if ( addRingReturnCode == 0 )
159  if ( addRingReturnCode == QgsGeometry::Success )
160  {
161  mLayer->editBuffer()->changeGeometry( f.id(), g );
162  if ( modifiedFeatureId )
163  *modifiedFeatureId = f.id();
164 
165  //setModified( true, true );
166  break;
167  }
168  }
169 
170  delete ring;
171  return addRingReturnCode;
172 }
173 
175 {
177  for ( QList<QgsPointXY>::const_iterator it = points.constBegin(); it != points.constEnd(); ++it )
178  {
179  l << QgsPoint( *it );
180  }
181  return addPart( l, featureId );
182 }
183 
185 {
186  if ( !mLayer->isSpatial() )
188 
189  QgsGeometry geometry;
190  bool firstPart = false;
191  QgsFeature f;
192  if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) )
194 
195  if ( !f.hasGeometry() )
196  {
197  //no existing geometry, so adding first part to null geometry
198  firstPart = true;
199  }
200  else
201  {
202  geometry = f.geometry();
203  }
204 
205  QgsGeometry::OperationResult errorCode = geometry.addPart( points, mLayer->geometryType() );
206  if ( errorCode == QgsGeometry::Success )
207  {
208  if ( firstPart && QgsWkbTypes::isSingleType( mLayer->wkbType() )
209  && mLayer->dataProvider()->doesStrictFeatureTypeCheck() )
210  {
211  //convert back to single part if required by layer
212  geometry.convertToSingleType();
213  }
214  mLayer->editBuffer()->changeGeometry( featureId, geometry );
215  }
216  return errorCode;
217 }
218 
220 {
221  if ( !mLayer->isSpatial() )
223 
224  QgsGeometry geometry;
225  bool firstPart = false;
226  QgsFeature f;
227  if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) )
229 
230  if ( !f.hasGeometry() )
231  {
232  //no existing geometry, so adding first part to null geometry
233  firstPart = true;
234  }
235  else
236  {
237  geometry = f.geometry();
238  }
239 
240  QgsGeometry::OperationResult errorCode = geometry.addPart( ring, mLayer->geometryType() );
241  if ( errorCode == QgsGeometry::Success )
242  {
243  if ( firstPart && QgsWkbTypes::isSingleType( mLayer->wkbType() )
244  && mLayer->dataProvider()->doesStrictFeatureTypeCheck() )
245  {
246  //convert back to single part if required by layer
247  geometry.convertToSingleType();
248  }
249  mLayer->editBuffer()->changeGeometry( featureId, geometry );
250  }
251  return errorCode;
252 }
253 
254 
255 int QgsVectorLayerEditUtils::translateFeature( QgsFeatureId featureId, double dx, double dy )
256 {
257  if ( !mLayer->isSpatial() )
258  return 1;
259 
260  QgsFeature f;
261  if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.hasGeometry() )
262  return 1; //geometry not found
263 
264  QgsGeometry geometry = f.geometry();
265 
266  int errorCode = geometry.translate( dx, dy );
267  if ( errorCode == 0 )
268  {
269  mLayer->editBuffer()->changeGeometry( featureId, geometry );
270  }
271  return errorCode;
272 }
273 
274 
275 QgsGeometry::OperationResult QgsVectorLayerEditUtils::splitFeatures( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
276 {
277  if ( !mLayer->isSpatial() )
279 
280  double xMin, yMin, xMax, yMax;
281  QgsRectangle bBox; //bounding box of the split line
283  QgsGeometry::OperationResult splitFunctionReturn; //return code of QgsGeometry::splitGeometry
284  int numberOfSplitFeatures = 0;
285 
286  QgsFeatureIterator features;
287  const QgsFeatureIds selectedIds = mLayer->selectedFeatureIds();
288 
289  if ( !selectedIds.isEmpty() ) //consider only the selected features if there is a selection
290  {
291  features = mLayer->getSelectedFeatures();
292  }
293  else //else consider all the feature that intersect the bounding box of the split line
294  {
295  if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) )
296  {
297  bBox.setXMinimum( xMin );
298  bBox.setYMinimum( yMin );
299  bBox.setXMaximum( xMax );
300  bBox.setYMaximum( yMax );
301  }
302  else
303  {
305  }
306 
307  if ( bBox.isEmpty() )
308  {
309  //if the bbox is a line, try to make a square out of it
310  if ( bBox.width() == 0.0 && bBox.height() > 0 )
311  {
312  bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
313  bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
314  }
315  else if ( bBox.height() == 0.0 && bBox.width() > 0 )
316  {
317  bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
318  bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
319  }
320  else
321  {
322  //If we have a single point, we still create a non-null box
323  double bufferDistance = 0.000001;
324  if ( mLayer->crs().isGeographic() )
325  bufferDistance = 0.00000001;
326  bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
327  bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
328  bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
329  bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
330  }
331  }
332 
333  features = mLayer->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
334  }
335 
336  QgsFeature feat;
337  while ( features.nextFeature( feat ) )
338  {
339  if ( !feat.hasGeometry() )
340  {
341  continue;
342  }
343  QVector<QgsGeometry> newGeometries;
344  QVector<QgsPointXY> topologyTestPoints;
345  QgsGeometry featureGeom = feat.geometry();
346  splitFunctionReturn = featureGeom.splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
347  if ( splitFunctionReturn == QgsGeometry::Success )
348  {
349  //change this geometry
350  mLayer->editBuffer()->changeGeometry( feat.id(), featureGeom );
351 
352  //insert new features
353  for ( int i = 0; i < newGeometries.size(); ++i )
354  {
355  QgsFeature f = QgsVectorLayerUtils::createFeature( mLayer, newGeometries.at( i ), feat.attributes().toMap() );
356  mLayer->editBuffer()->addFeature( f );
357  }
358 
359  if ( topologicalEditing )
360  {
361  QVector<QgsPointXY>::const_iterator topol_it = topologyTestPoints.constBegin();
362  for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
363  {
364  addTopologicalPoints( *topol_it );
365  }
366  }
367  ++numberOfSplitFeatures;
368  }
369  else if ( splitFunctionReturn != QgsGeometry::Success && splitFunctionReturn != QgsGeometry::NothingHappened ) // i.e. no split but no error occurred
370  {
371  returnCode = splitFunctionReturn;
372  }
373  }
374 
375  if ( numberOfSplitFeatures == 0 && !selectedIds.isEmpty() )
376  {
377  //There is a selection but no feature has been split.
378  //Maybe user forgot that only the selected features are split
379  returnCode = QgsGeometry::NothingHappened;
380  }
381 
382  return returnCode;
383 }
384 
385 QgsGeometry::OperationResult QgsVectorLayerEditUtils::splitParts( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
386 {
387  if ( !mLayer->isSpatial() )
389 
390  double xMin, yMin, xMax, yMax;
391  QgsRectangle bBox; //bounding box of the split line
393  QgsGeometry::OperationResult splitFunctionReturn; //return code of QgsGeometry::splitGeometry
394  int numberOfSplitParts = 0;
395 
396  QgsFeatureIterator fit;
397 
398  if ( mLayer->selectedFeatureCount() > 0 ) //consider only the selected features if there is a selection
399  {
400  fit = mLayer->getSelectedFeatures();
401  }
402  else //else consider all the feature that intersect the bounding box of the split line
403  {
404  if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) )
405  {
406  bBox.setXMinimum( xMin );
407  bBox.setYMinimum( yMin );
408  bBox.setXMaximum( xMax );
409  bBox.setYMaximum( yMax );
410  }
411  else
412  {
414  }
415 
416  if ( bBox.isEmpty() )
417  {
418  //if the bbox is a line, try to make a square out of it
419  if ( bBox.width() == 0.0 && bBox.height() > 0 )
420  {
421  bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
422  bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
423  }
424  else if ( bBox.height() == 0.0 && bBox.width() > 0 )
425  {
426  bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
427  bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
428  }
429  else
430  {
431  //If we have a single point, we still create a non-null box
432  double bufferDistance = 0.000001;
433  if ( mLayer->crs().isGeographic() )
434  bufferDistance = 0.00000001;
435  bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
436  bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
437  bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
438  bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
439  }
440  }
441 
442  fit = mLayer->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
443  }
444 
446 
447  QgsFeature feat;
448  while ( fit.nextFeature( feat ) )
449  {
450  QVector<QgsGeometry> newGeometries;
451  QVector<QgsPointXY> topologyTestPoints;
452  QgsGeometry featureGeom = feat.geometry();
453  splitFunctionReturn = featureGeom.splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
454  if ( splitFunctionReturn == 0 )
455  {
456  //add new parts
457  if ( !newGeometries.isEmpty() )
458  featureGeom.convertToMultiType();
459 
460  for ( int i = 0; i < newGeometries.size(); ++i )
461  {
462  addPartRet = featureGeom.addPart( newGeometries.at( i ) );
463  if ( addPartRet )
464  break;
465  }
466 
467  // For test only: Exception already thrown here...
468  // feat.geometry()->asWkb();
469 
470  if ( !addPartRet )
471  {
472  mLayer->editBuffer()->changeGeometry( feat.id(), featureGeom );
473  }
474 
475  if ( topologicalEditing )
476  {
477  QVector<QgsPointXY>::const_iterator topol_it = topologyTestPoints.constBegin();
478  for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
479  {
480  addTopologicalPoints( *topol_it );
481  }
482  }
483  ++numberOfSplitParts;
484  }
485  else if ( splitFunctionReturn != QgsGeometry::Success && splitFunctionReturn != QgsGeometry::NothingHappened )
486  {
487  returnCode = splitFunctionReturn;
488  }
489  }
490 
491  if ( numberOfSplitParts == 0 && mLayer->selectedFeatureCount() > 0 && returnCode == QgsGeometry::Success )
492  {
493  //There is a selection but no feature has been split.
494  //Maybe user forgot that only the selected features are split
495  returnCode = QgsGeometry::NothingHappened;
496  }
497 
498  return returnCode;
499 }
500 
501 
503 {
504  if ( !mLayer->isSpatial() )
505  return 1;
506 
507  if ( geom.isNull() )
508  {
509  return 1;
510  }
511 
512  int returnVal = 0;
513 
514  QgsWkbTypes::Type wkbType = geom.wkbType();
515 
516  switch ( wkbType )
517  {
518  //line
521  {
522  QgsPolylineXY line = geom.asPolyline();
523  QgsPolylineXY::const_iterator line_it = line.constBegin();
524  for ( ; line_it != line.constEnd(); ++line_it )
525  {
526  if ( addTopologicalPoints( *line_it ) != 0 )
527  {
528  returnVal = 2;
529  }
530  }
531  break;
532  }
533 
534  //multiline
537  {
538  QgsMultiPolylineXY multiLine = geom.asMultiPolyline();
539  QgsPolylineXY currentPolyline;
540 
541  for ( int i = 0; i < multiLine.size(); ++i )
542  {
543  QgsPolylineXY::const_iterator line_it = currentPolyline.constBegin();
544  for ( ; line_it != currentPolyline.constEnd(); ++line_it )
545  {
546  if ( addTopologicalPoints( *line_it ) != 0 )
547  {
548  returnVal = 2;
549  }
550  }
551  }
552  break;
553  }
554 
555  //polygon
558  {
559  QgsPolygonXY polygon = geom.asPolygon();
560  QgsPolylineXY currentRing;
561 
562  for ( int i = 0; i < polygon.size(); ++i )
563  {
564  currentRing = polygon.at( i );
565  QgsPolylineXY::const_iterator line_it = currentRing.constBegin();
566  for ( ; line_it != currentRing.constEnd(); ++line_it )
567  {
568  if ( addTopologicalPoints( *line_it ) != 0 )
569  {
570  returnVal = 2;
571  }
572  }
573  }
574  break;
575  }
576 
577  //multipolygon
580  {
581  QgsMultiPolygonXY multiPolygon = geom.asMultiPolygon();
582  QgsPolygonXY currentPolygon;
583  QgsPolylineXY currentRing;
584 
585  for ( int i = 0; i < multiPolygon.size(); ++i )
586  {
587  currentPolygon = multiPolygon.at( i );
588  for ( int j = 0; j < currentPolygon.size(); ++j )
589  {
590  currentRing = currentPolygon.at( j );
591  QgsPolylineXY::const_iterator line_it = currentRing.constBegin();
592  for ( ; line_it != currentRing.constEnd(); ++line_it )
593  {
594  if ( addTopologicalPoints( *line_it ) != 0 )
595  {
596  returnVal = 2;
597  }
598  }
599  }
600  }
601  break;
602  }
603  default:
604  break;
605  }
606  return returnVal;
607 }
608 
609 
611 {
612  if ( !mLayer->isSpatial() )
613  return 1;
614 
615  double segmentSearchEpsilon = mLayer->crs().isGeographic() ? 1e-12 : 1e-8;
616 
617  //work with a tolerance because coordinate projection may introduce some rounding
618  double threshold = 0.0000001;
619  if ( mLayer->crs().mapUnits() == QgsUnitTypes::DistanceMeters )
620  {
621  threshold = 0.001;
622  }
623  else if ( mLayer->crs().mapUnits() == QgsUnitTypes::DistanceFeet )
624  {
625  threshold = 0.0001;
626  }
627 
628  QgsRectangle searchRect( p.x() - threshold, p.y() - threshold,
629  p.x() + threshold, p.y() + threshold );
630  double sqrSnappingTolerance = threshold * threshold;
631 
632  QgsFeature f;
634  .setFilterRect( searchRect )
636  .setSubsetOfAttributes( QgsAttributeList() ) );
637 
638  QMap<QgsFeatureId, QgsGeometry> features;
639  QMap<QgsFeatureId, int> segments;
640 
641  while ( fit.nextFeature( f ) )
642  {
643  int afterVertex;
644  QgsPointXY snappedPoint;
645  double sqrDistSegmentSnap = f.geometry().closestSegmentWithContext( p, snappedPoint, afterVertex, nullptr, segmentSearchEpsilon );
646  if ( sqrDistSegmentSnap < sqrSnappingTolerance )
647  {
648  segments[f.id()] = afterVertex;
649  features[f.id()] = f.geometry();
650  }
651  }
652 
653  if ( segments.isEmpty() )
654  return 2;
655 
656  for ( QMap<QgsFeatureId, int>::const_iterator it = segments.constBegin(); it != segments.constEnd(); ++it )
657  {
658  QgsFeatureId fid = it.key();
659  int segmentAfterVertex = it.value();
660  QgsGeometry geom = features[fid];
661 
662  int atVertex, beforeVertex, afterVertex;
663  double sqrDistVertexSnap;
664  geom.closestVertex( p, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
665 
666  if ( sqrDistVertexSnap < sqrSnappingTolerance )
667  continue; // the vertex already exists - do not insert it
668 
669  if ( !mLayer->insertVertex( p.x(), p.y(), fid, segmentAfterVertex ) )
670  {
671  QgsDebugMsg( "failed to insert topo point" );
672  }
673  }
674 
675  return 0;
676 }
677 
678 
679 bool QgsVectorLayerEditUtils::boundingBoxFromPointList( const QVector<QgsPointXY> &list, double &xmin, double &ymin, double &xmax, double &ymax ) const
680 {
681  if ( list.empty() )
682  {
683  return false;
684  }
685 
686  xmin = std::numeric_limits<double>::max();
687  xmax = -std::numeric_limits<double>::max();
688  ymin = std::numeric_limits<double>::max();
689  ymax = -std::numeric_limits<double>::max();
690 
691  for ( QVector<QgsPointXY>::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
692  {
693  if ( it->x() < xmin )
694  {
695  xmin = it->x();
696  }
697  if ( it->x() > xmax )
698  {
699  xmax = it->x();
700  }
701  if ( it->y() < ymin )
702  {
703  ymin = it->y();
704  }
705  if ( it->y() > ymax )
706  {
707  ymax = it->y();
708  }
709  }
710 
711  return true;
712 }
QgsFeatureId id
Definition: qgsfeature.h:71
Wrapper for iterator of features from vector data provider or vector layer.
A rectangle specified with double values.
Definition: qgsrectangle.h:39
QgsGeometry::OperationResult splitParts(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
The input ring doesn&#39;t have any existing ring to fit into.
Definition: qgsgeometry.h:133
static QgsFeature createFeature(QgsVectorLayer *layer, const QgsGeometry &geometry=QgsGeometry(), const QgsAttributeMap &attributes=QgsAttributeMap(), QgsExpressionContext *context=nullptr)
Creates a new feature ready for insertion into a layer.
OperationResult addPart(const QVector< QgsPointXY > &points, QgsWkbTypes::GeometryType geomType=QgsWkbTypes::UnknownGeometry)
Adds a new part to a the geometry.
bool isNull() const
Returns true if the geometry is null (ie, contains no underlying geometry accessible via geometry() )...
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:90
Use exact geometry intersection (slower) instead of bounding boxes.
Nothing happened, without any error.
Definition: qgsgeometry.h:122
virtual bool addFeature(QgsFeature &f)
Adds a feature.
#define QgsDebugMsg(str)
Definition: qgslogger.h:37
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:544
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
double y
Definition: qgspointxy.h:48
A class to represent a 2D point.
Definition: qgspointxy.h:43
int selectedFeatureCount() const
The number of features that are selected in this layer.
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item...
Definition: qgsgeometry.h:73
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...
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:111
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:62
double closestSegmentWithContext(const QgsPointXY &point, QgsPointXY &minDistPoint, int &afterVertex, double *leftOf=nullptr, double epsilon=DEFAULT_SEGMENT_EPSILON) const
Searches for the closest segment of geometry to the given point.
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:190
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)...
OperationResult
Success or failure of a geometry operation.
Definition: qgsgeometry.h:119
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
Definition: qgsgeometry.h:90
The input geometry (ring, part, split line, etc.) has not the correct geometry type.
Definition: qgsgeometry.h:124
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 ...
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
Definition: qgsgeometry.h:83
QgsMultiPolylineXY asMultiPolyline() const
Returns contents of the geometry as a multi linestring if wkbType is WKBMultiLineString, otherwise an empty list.
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:127
QgsVectorLayerEditBuffer * editBuffer()
Buffer with uncommitted editing operations. Only valid after editing has been turned on...
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:67
const QgsFeatureIds & selectedFeatureIds() const
Return reference to identifiers of selected features.
bool convertToSingleType()
Converts multi type geometry into single type geometry e.g.
bool isEmpty() const
Returns true if the rectangle is empty.
QgsFeatureIterator getSelectedFeatures(QgsFeatureRequest request=QgsFeatureRequest()) const
Get an iterator of the selected features.
QgsPolygonXY asPolygon() const
Returns contents of the geometry as a polygon if wkbType is WKBPolygon, otherwise an empty list...
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:138
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:95
bool deleteVertex(int atVertex)
Deletes the vertex at the given position number and item (first number is index 0) ...
OperationResult translate(double dx, double dy)
Translates this geometry by dx, dy.
QgsWkbTypes::Type wkbType() const override
Returns the WKBType or WKBUnknown in case of error.
QgsGeometry::OperationResult splitFeatures(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
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)...
virtual bool changeGeometry(QgsFeatureId fid, const QgsGeometry &geom)
Change feature&#39;s geometry.
virtual bool isSpatial() const override
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
QgsCoordinateReferenceSystem crs() const
Returns the layer&#39;s spatial reference system.
QgsAttributeMap toMap() const
Returns a QgsAttributeMap of the attribute values.
bool isGeographic() const
Returns whether the CRS is a geographic CRS (using lat/lon coordinates)
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
Edit operation failed.
QgsGeometry geometry() const
Returns the geometry associated with this feature.
Definition: qgsfeature.cpp:101
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
double x
Definition: qgspointxy.h:47
QgsGeometry::OperationResult addPart(const QList< QgsPointXY > &ring, QgsFeatureId featureId)
Adds a new part polygon to a multipart feature.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const override
Query the layer for features specified in request.
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:126
static bool isSingleType(Type type)
Returns true if the WKB type is a single type.
Definition: qgswkbtypes.h:547
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:111
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:168
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
Definition: qgsgeometry.h:49
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:123
QgsGeometry::OperationResult addRing(const QVector< QgsPointXY > &ring, const QgsFeatureIds &targetFeatureIds=QgsFeatureIds(), QgsFeatureId *modifiedFeatureId=nullptr)
Adds a ring to polygon/multipolygon features.
OperationResult splitGeometry(const QVector< QgsPointXY > &splitLine, QVector< QgsGeometry > &newGeometries, bool topological, QVector< QgsPointXY > &topologyTestPoints)
Splits this geometry according to a given line.
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:100
Edit operation was successful.
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:41
QgsVectorDataProvider * dataProvider() override
Returns the layer&#39;s data provider.
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:116
qint64 QgsFeatureId
Definition: qgsfeature.h:37
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:121
QgsPolylineXY asPolyline() const
Returns contents of the geometry as a polyline if wkbType is WKBLineString, otherwise an empty list...
Edit failed due to invalid layer.
QList< int > QgsAttributeList
Definition: qgsfield.h:27
bool nextFeature(QgsFeature &f)
Operation succeeded.
Definition: qgsgeometry.h:121
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.
EditResult
Result of an edit operation.
QgsMultiPolygonXY asMultiPolygon() const
Returns contents of the geometry as a multi polygon if wkbType is WKBMultiPolygon, otherwise an empty list.
Unable to fetch requested feature.
QgsAttributes attributes
Definition: qgsfeature.h:72
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:85
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:145
QgsVectorLayerEditUtils(QgsVectorLayer *layer)