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