QGIS API Documentation  2.99.0-Master (dcec6bb)
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  : L( layer )
33 {
34 }
35 
36 bool QgsVectorLayerEditUtils::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
37 {
38  if ( !L->isSpatial() )
39  return false;
40 
41  QgsFeature f;
42  if ( !L->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  L->editBuffer()->changeGeometry( atFeatureId, geometry );
50  return true;
51 }
52 
53 bool QgsVectorLayerEditUtils::insertVertex( const QgsPoint &point, QgsFeatureId atFeatureId, int beforeVertex )
54 {
55  if ( !L->isSpatial() )
56  return false;
57 
58  QgsFeature f;
59  if ( !L->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  L->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 ( !L->isSpatial() )
79  return false;
80 
81  QgsFeature f;
82  if ( !L->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  L->editBuffer()->changeGeometry( atFeatureId, geometry );
90  return true;
91 }
92 
93 
95 {
96  if ( !L->isSpatial() )
98 
99  QgsFeature f;
100  if ( !L->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  L->editBuffer()->changeGeometry( featureId, geometry );
116 }
117 
118 int 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 
124 int QgsVectorLayerEditUtils::addRing( QgsCurve *ring, const QgsFeatureIds &targetFeatureIds, QgsFeatureId *modifiedFeatureId )
125 {
126  if ( !L->isSpatial() )
127  {
128  delete ring;
129  return 5;
130  }
131 
132  int addRingReturnCode = 5; //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 = L->getFeatures( QgsFeatureRequest().setFilterFids( targetFeatureIds ) );
140  }
141  else
142  {
143  //check all intersecting features
144  QgsRectangle bBox = ring->boundingBox();
145  fit = L->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  {
160  L->editBuffer()->changeGeometry( f.id(), g );
161  if ( modifiedFeatureId )
162  *modifiedFeatureId = f.id();
163 
164  //setModified( true, true );
165  break;
166  }
167  }
168 
169  delete ring;
170  return addRingReturnCode;
171 }
172 
173 int QgsVectorLayerEditUtils::addPart( const QList<QgsPointXY> &points, QgsFeatureId featureId )
174 {
176  for ( QList<QgsPointXY>::const_iterator it = points.constBegin(); it != points.constEnd(); ++it )
177  {
178  l << QgsPoint( *it );
179  }
180  return addPart( l, featureId );
181 }
182 
184 {
185  if ( !L->isSpatial() )
186  return 6;
187 
188  QgsGeometry geometry;
189  bool firstPart = false;
190  QgsFeature f;
191  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) )
192  return 6; //not found
193 
194  if ( !f.hasGeometry() )
195  {
196  //no existing geometry, so adding first part to null geometry
197  firstPart = true;
198  }
199  else
200  {
201  geometry = f.geometry();
202  }
203 
204  int errorCode = geometry.addPart( points, L->geometryType() ) ;
205  if ( errorCode == 0 )
206  {
207  if ( firstPart && QgsWkbTypes::isSingleType( L->wkbType() )
209  {
210  //convert back to single part if required by layer
211  geometry.convertToSingleType();
212  }
213  L->editBuffer()->changeGeometry( featureId, geometry );
214  }
215  return errorCode;
216 }
217 
219 {
220  if ( !L->isSpatial() )
221  return 6;
222 
223  QgsGeometry geometry;
224  bool firstPart = false;
225  QgsFeature f;
226  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) )
227  return 6; //not found
228 
229  if ( !f.hasGeometry() )
230  {
231  //no existing geometry, so adding first part to null geometry
232  firstPart = true;
233  }
234  else
235  {
236  geometry = f.geometry();
237  }
238 
239  int errorCode = geometry.addPart( ring, L->geometryType() ) ;
240  if ( errorCode == 0 )
241  {
242  if ( firstPart && QgsWkbTypes::isSingleType( L->wkbType() )
244  {
245  //convert back to single part if required by layer
246  geometry.convertToSingleType();
247  }
248  L->editBuffer()->changeGeometry( featureId, geometry );
249  }
250  return errorCode;
251 }
252 
253 
254 int QgsVectorLayerEditUtils::translateFeature( QgsFeatureId featureId, double dx, double dy )
255 {
256  if ( !L->isSpatial() )
257  return 1;
258 
259  QgsFeature f;
260  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.hasGeometry() )
261  return 1; //geometry not found
262 
263  QgsGeometry geometry = f.geometry();
264 
265  int errorCode = geometry.translate( dx, dy );
266  if ( errorCode == 0 )
267  {
268  L->editBuffer()->changeGeometry( featureId, geometry );
269  }
270  return errorCode;
271 }
272 
273 
274 int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPointXY> &splitLine, bool topologicalEditing )
275 {
276  if ( !L->isSpatial() )
277  return 4;
278 
279  QgsFeatureList newFeatures; //store all the newly created features
280  double xMin, yMin, xMax, yMax;
281  QgsRectangle bBox; //bounding box of the split line
282  int returnCode = 0;
283  int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
284  int numberOfSplitFeatures = 0;
285 
286  QgsFeatureIterator features;
287  const QgsFeatureIds selectedIds = L->selectedFeatureIds();
288 
289  if ( !selectedIds.isEmpty() ) //consider only the selected features if there is a selection
290  {
291  features = L->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 ) == 0 )
296  {
297  bBox.setXMinimum( xMin );
298  bBox.setYMinimum( yMin );
299  bBox.setXMaximum( xMax );
300  bBox.setYMaximum( yMax );
301  }
302  else
303  {
304  return 1;
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 ( L->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 = L->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 == 0 )
348  {
349  //change this geometry
350  L->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( L, newGeometries.at( i ), feat.attributes().toMap() );
356  L->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 > 1 ) //1 means no split but also no error
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 = 4;
380  }
381 
382  return returnCode;
383 }
384 
385 int QgsVectorLayerEditUtils::splitParts( const QList<QgsPointXY> &splitLine, bool topologicalEditing )
386 {
387  if ( !L->isSpatial() )
388  return 4;
389 
390  double xMin, yMin, xMax, yMax;
391  QgsRectangle bBox; //bounding box of the split line
392  int returnCode = 0;
393  int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
394  int numberOfSplitParts = 0;
395 
396  QgsFeatureIterator fit;
397 
398  if ( L->selectedFeatureCount() > 0 ) //consider only the selected features if there is a selection
399  {
400  fit = L->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 ) == 0 )
405  {
406  bBox.setXMinimum( xMin );
407  bBox.setYMinimum( yMin );
408  bBox.setXMaximum( xMax );
409  bBox.setYMaximum( yMax );
410  }
411  else
412  {
413  return 1;
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 ( L->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 = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
443  }
444 
445  int addPartRet = 0;
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  L->editBuffer()->changeGeometry( feat.id(), featureGeom );
473  }
474  else
475  {
476  // Test addPartRet
477  switch ( addPartRet )
478  {
479  case 1:
480  QgsDebugMsg( "Not a multipolygon" );
481  break;
482 
483  case 2:
484  QgsDebugMsg( "Not a valid geometry" );
485  break;
486 
487  case 3:
488  QgsDebugMsg( "New polygon ring" );
489  break;
490  }
491  }
492  L->editBuffer()->changeGeometry( feat.id(), featureGeom );
493 
494  if ( topologicalEditing )
495  {
496  QList<QgsPointXY>::const_iterator topol_it = topologyTestPoints.constBegin();
497  for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
498  {
499  addTopologicalPoints( *topol_it );
500  }
501  }
502  ++numberOfSplitParts;
503  }
504  else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
505  {
506  returnCode = splitFunctionReturn;
507  }
508  }
509 
510  if ( numberOfSplitParts == 0 && L->selectedFeatureCount() > 0 && returnCode == 0 )
511  {
512  //There is a selection but no feature has been split.
513  //Maybe user forgot that only the selected features are split
514  returnCode = 4;
515  }
516 
517  return returnCode;
518 }
519 
520 
522 {
523  if ( !L->isSpatial() )
524  return 1;
525 
526  if ( geom.isNull() )
527  {
528  return 1;
529  }
530 
531  int returnVal = 0;
532 
533  QgsWkbTypes::Type wkbType = geom.wkbType();
534 
535  switch ( wkbType )
536  {
537  //line
540  {
541  QgsPolyline line = geom.asPolyline();
542  QgsPolyline::const_iterator line_it = line.constBegin();
543  for ( ; line_it != line.constEnd(); ++line_it )
544  {
545  if ( addTopologicalPoints( *line_it ) != 0 )
546  {
547  returnVal = 2;
548  }
549  }
550  break;
551  }
552 
553  //multiline
556  {
557  QgsMultiPolyline multiLine = geom.asMultiPolyline();
558  QgsPolyline currentPolyline;
559 
560  for ( int i = 0; i < multiLine.size(); ++i )
561  {
562  QgsPolyline::const_iterator line_it = currentPolyline.constBegin();
563  for ( ; line_it != currentPolyline.constEnd(); ++line_it )
564  {
565  if ( addTopologicalPoints( *line_it ) != 0 )
566  {
567  returnVal = 2;
568  }
569  }
570  }
571  break;
572  }
573 
574  //polygon
577  {
578  QgsPolygon polygon = geom.asPolygon();
579  QgsPolyline currentRing;
580 
581  for ( int i = 0; i < polygon.size(); ++i )
582  {
583  currentRing = polygon.at( i );
584  QgsPolyline::const_iterator line_it = currentRing.constBegin();
585  for ( ; line_it != currentRing.constEnd(); ++line_it )
586  {
587  if ( addTopologicalPoints( *line_it ) != 0 )
588  {
589  returnVal = 2;
590  }
591  }
592  }
593  break;
594  }
595 
596  //multipolygon
599  {
600  QgsMultiPolygon multiPolygon = geom.asMultiPolygon();
601  QgsPolygon currentPolygon;
602  QgsPolyline currentRing;
603 
604  for ( int i = 0; i < multiPolygon.size(); ++i )
605  {
606  currentPolygon = multiPolygon.at( i );
607  for ( int j = 0; j < currentPolygon.size(); ++j )
608  {
609  currentRing = currentPolygon.at( j );
610  QgsPolyline::const_iterator line_it = currentRing.constBegin();
611  for ( ; line_it != currentRing.constEnd(); ++line_it )
612  {
613  if ( addTopologicalPoints( *line_it ) != 0 )
614  {
615  returnVal = 2;
616  }
617  }
618  }
619  }
620  break;
621  }
622  default:
623  break;
624  }
625  return returnVal;
626 }
627 
628 
630 {
631  if ( !L->isSpatial() )
632  return 1;
633 
634  double segmentSearchEpsilon = L->crs().isGeographic() ? 1e-12 : 1e-8;
635 
636  //work with a tolerance because coordinate projection may introduce some rounding
637  double threshold = 0.0000001;
638  if ( L->crs().mapUnits() == QgsUnitTypes::DistanceMeters )
639  {
640  threshold = 0.001;
641  }
642  else if ( L->crs().mapUnits() == QgsUnitTypes::DistanceFeet )
643  {
644  threshold = 0.0001;
645  }
646 
647  QgsRectangle searchRect( p.x() - threshold, p.y() - threshold,
648  p.x() + threshold, p.y() + threshold );
649  double sqrSnappingTolerance = threshold * threshold;
650 
651  QgsFeature f;
653  .setFilterRect( searchRect )
655  .setSubsetOfAttributes( QgsAttributeList() ) );
656 
657  QMap<QgsFeatureId, QgsGeometry> features;
658  QMap<QgsFeatureId, int> segments;
659 
660  while ( fit.nextFeature( f ) )
661  {
662  int afterVertex;
663  QgsPointXY snappedPoint;
664  double sqrDistSegmentSnap = f.geometry().closestSegmentWithContext( p, snappedPoint, afterVertex, nullptr, segmentSearchEpsilon );
665  if ( sqrDistSegmentSnap < sqrSnappingTolerance )
666  {
667  segments[f.id()] = afterVertex;
668  features[f.id()] = f.geometry();
669  }
670  }
671 
672  if ( segments.isEmpty() )
673  return 2;
674 
675  for ( QMap<QgsFeatureId, int>::const_iterator it = segments.constBegin(); it != segments.constEnd(); ++it )
676  {
677  QgsFeatureId fid = it.key();
678  int segmentAfterVertex = it.value();
679  QgsGeometry geom = features[fid];
680 
681  int atVertex, beforeVertex, afterVertex;
682  double sqrDistVertexSnap;
683  geom.closestVertex( p, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
684 
685  if ( sqrDistVertexSnap < sqrSnappingTolerance )
686  continue; // the vertex already exists - do not insert it
687 
688  if ( !L->insertVertex( p.x(), p.y(), fid, segmentAfterVertex ) )
689  {
690  QgsDebugMsg( "failed to insert topo point" );
691  }
692  }
693 
694  return 0;
695 }
696 
697 
698 int QgsVectorLayerEditUtils::boundingBoxFromPointList( const QList<QgsPointXY> &list, double &xmin, double &ymin, double &xmax, double &ymax ) const
699 {
700  if ( list.size() < 1 )
701  {
702  return 1;
703  }
704 
709 
710  for ( QList<QgsPointXY>::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
711  {
712  if ( it->x() < xmin )
713  {
714  xmin = it->x();
715  }
716  if ( it->x() > xmax )
717  {
718  xmax = it->x();
719  }
720  if ( it->y() < ymin )
721  {
722  ymin = it->y();
723  }
724  if ( it->y() > ymax )
725  {
726  ymax = it->y();
727  }
728  }
729 
730  return 0;
731 }
QgsPolygon asPolygon() const
Return 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
Return 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
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.
int addPart(const QList< 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:70
Use exact geometry intersection (slower) instead of bounding boxes.
virtual bool addFeature(QgsFeature &f)
Adds a feature.
#define QgsDebugMsg(str)
Definition: qgslogger.h:37
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:519
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:524
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:96
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)...
QgsPolyline asPolyline() const
Return 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
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.
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.
int splitParts(const QList< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
bool isEmpty() const
Returns true if the rectangle is empty.
QgsFeatureIterator getSelectedFeatures(QgsFeatureRequest request=QgsFeatureRequest()) const
Get an iterator of the selected features.
int splitFeatures(const QList< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
int boundingBoxFromPointList(const QList< QgsPointXY > &list, double &xmin, double &ymin, double &xmax, double &ymax) const
Little helper function that gives bounding box from a list of points.
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:118
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:75
bool deleteVertex(int atVertex)
Deletes the vertex at the given position number and item (first number is index 0) Returns false if a...
virtual QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
QgsWkbTypes::Type wkbType() const override
Returns the WKBType or WKBUnknown in case of error.
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:76
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 ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
Definition: MathUtils.cc:437
int translate(double dx, double dy)
Translate this geometry by dx, dy.
double x
Definition: qgspointxy.h:46
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:106
QVector< QgsPolyline > QgsMultiPolyline
A collection of QgsPolylines that share a common collection of attributes.
Definition: qgsgeometry.h:69
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:91
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)...
virtual QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
Definition: qgscurve.cpp:129
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
int addRing(const QList< QgsPointXY > &ring, const QgsFeatureIds &targetFeatureIds=QgsFeatureIds(), QgsFeatureId *modifiedFeatureId=nullptr)
Adds a ring to polygon/multipolygon features.
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:80
int addPart(const QList< QgsPointXY > &ring, QgsFeatureId featureId)
Adds a new part polygon to a multipart feature.
QgsMultiPolygon asMultiPolygon() const
Return contents of the geometry as a multi polygon if wkbType is WKBMultiPolygon, otherwise an empty ...
Edit operation was successful.
int splitGeometry(const QList< QgsPointXY > &splitLine, QList< QgsGeometry > &newGeometries, bool topological, QList< QgsPointXY > &topologyTestPoints)
Splits this geometry according to a given line.
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:96
qint64 QgsFeatureId
Definition: qgsfeature.h:37
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:101
Edit failed due to invalid layer.
QList< int > QgsAttributeList
Definition: qgsfield.h:27
bool nextFeature(QgsFeature &f)
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.
int addRing(const QList< QgsPointXY > &ring)
Adds a new ring to this geometry.
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:65
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:125
QgsVectorLayerEditUtils(QgsVectorLayer *layer)