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