QGIS API Documentation  2.99.0-Master (9caa722)
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.geometry() && geometry.geometry()->nCoordinates() == 0 )
109  {
110  //last vertex deleted, set geometry to null
111  geometry.setGeometry( nullptr );
112  }
113 
114  mLayer->editBuffer()->changeGeometry( featureId, geometry );
116 }
117 
118 QgsGeometry::OperationResult QgsVectorLayerEditUtils::addRing( const QList<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 QList<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  QList<QgsGeometry> newGeometries;
344  QList<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  QList<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 QList<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  QList<QgsGeometry> newGeometries;
451  QList<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  QList<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  QgsPolyline line = geom.asPolyline();
523  QgsPolyline::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  QgsMultiPolyline multiLine = geom.asMultiPolyline();
539  QgsPolyline currentPolyline;
540 
541  for ( int i = 0; i < multiLine.size(); ++i )
542  {
543  QgsPolyline::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  QgsPolygon polygon = geom.asPolygon();
560  QgsPolyline currentRing;
561 
562  for ( int i = 0; i < polygon.size(); ++i )
563  {
564  currentRing = polygon.at( i );
565  QgsPolyline::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  QgsMultiPolygon multiPolygon = geom.asMultiPolygon();
582  QgsPolygon currentPolygon;
583  QgsPolyline 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  QgsPolyline::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 QList<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 ( QList<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 }
QgsPolygon asPolygon() const
Returns contents of the geometry as a polygon if wkbType is WKBPolygon, otherwise an empty list...
QgsFeatureId id
Definition: qgsfeature.h:70
Wrapper for iterator of features from vector data provider or vector layer.
QgsMultiPolyline asMultiPolyline() const
Returns contents of the geometry as a multi linestring if wkbType is WKBMultiLineString, otherwise an empty list.
A rectangle specified with double values.
Definition: qgsrectangle.h:38
The input ring doesn&#39;t have any existing ring to fit into.
Definition: qgsgeometry.h:114
OperationResult splitGeometry(const QList< QgsPointXY > &splitLine, QList< QgsGeometry > &newGeometries, bool topological, QList< QgsPointXY > &topologyTestPoints)
Splits this geometry according to a given line.
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.
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:75
Use exact geometry intersection (slower) instead of bounding boxes.
Nothing happened, without any error.
Definition: qgsgeometry.h:103
QgsGeometry::OperationResult splitFeatures(const QList< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
virtual bool addFeature(QgsFeature &f)
Adds a feature.
OperationResult addPart(const QList< QgsPointXY > &points, QgsWkbTypes::GeometryType geomType=QgsWkbTypes::UnknownGeometry)
Adds a new part to a the geometry.
#define QgsDebugMsg(str)
Definition: qgslogger.h:37
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:519
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
double y
Definition: qgspointxy.h:47
A class to represent a 2D point.
Definition: qgspointxy.h:42
int selectedFeatureCount() const
The number of features that are selected in this layer.
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:92
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:61
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:100
QgsPolyline asPolyline() const
Returns contents of the geometry as a polyline if wkbType is WKBLineString, otherwise an empty list...
QVector< QgsPointXY > QgsPolyline
Polyline is represented as a vector of points.
Definition: qgsgeometry.h:48
The input geometry (ring, part, split line, etc.) has not the correct geometry type.
Definition: qgsgeometry.h:105
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:108
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:66
const QgsFeatureIds & selectedFeatureIds() const
Return reference to identifiers of selected features.
bool convertToSingleType()
Converts multi type geometry into single type geometry e.g.
OperationResult addRing(const QList< QgsPointXY > &ring)
Adds a new ring to this geometry.
bool isEmpty() const
Returns true if the rectangle is empty.
QgsFeatureIterator getSelectedFeatures(QgsFeatureRequest request=QgsFeatureRequest()) const
Get an iterator of the selected features.
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:123
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:80
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 addRing(const QList< QgsPointXY > &ring, const QgsFeatureIds &targetFeatureIds=QgsFeatureIds(), QgsFeatureId *modifiedFeatureId=nullptr)
Adds a ring to polygon/multipolygon features.
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.
QVector< QgsPolygon > QgsMultiPolygon
A collection of QgsPolygons that share a common collection of attributes.
Definition: qgsgeometry.h:72
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:34
QVector< QgsPolyline > QgsPolygon
Polygon: first item of the list is outer ring, inner rings (if any) start from second item...
Definition: qgsgeometry.h:55
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:36
double x
Definition: qgspointxy.h:46
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.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:111
QVector< QgsPolyline > QgsMultiPolyline
A collection of QgsPolylines that share a common collection of attributes.
Definition: qgsgeometry.h:65
static bool isSingleType(Type type)
Returns true if the WKB type is a single type.
Definition: qgswkbtypes.h:541
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:96
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:134
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:104
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:85
QgsMultiPolygon asMultiPolygon() const
Returns contents of the geometry as a multi polygon if wkbType is WKBMultiPolygon, otherwise an empty list.
Edit operation was successful.
void setGeometry(QgsAbstractGeometry *geometry)
Sets the underlying geometry store.
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:40
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:101
qint64 QgsFeatureId
Definition: qgsfeature.h:37
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:106
Edit failed due to invalid layer.
QList< int > QgsAttributeList
Definition: qgsfield.h:27
bool nextFeature(QgsFeature &f)
Operation succeeded.
Definition: qgsgeometry.h:102
QList< QgsPoint > QgsPointSequence
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.
QgsAbstractGeometry * geometry() const
Returns the underlying geometry store.
Unable to fetch requested feature.
QgsAttributes attributes
Definition: qgsfeature.h:71
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:70
QgsGeometry::OperationResult splitParts(const QList< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:130
QgsVectorLayerEditUtils(QgsVectorLayer *layer)