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