QGIS API Documentation 3.27.0-Master (1d7a28cfd2)
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
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
39bool 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
56bool 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
73bool QgsVectorLayerEditUtils::moveVertex( double x, double y, QgsFeatureId atFeatureId, int atVertex )
74{
75 QgsPoint p( x, y );
76 return moveVertex( p, atFeatureId, atVertex );
77}
78
79bool 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 Qgis::VectorEditResult::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
121Qgis::GeometryOperationResult 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 Qgis::GeometryOperationResult addRingReturnCode = Qgis::GeometryOperationResult::AddRingNotInExistingFeature; //default: return code for 'ring not inserted'
146 QgsFeature f;
147
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 == Qgis::GeometryOperationResult::Success )
172 {
173 mLayer->changeGeometry( f.id(), g );
174 if ( modifiedFeatureId )
175 *modifiedFeatureId = f.id();
176
177 //setModified( true, true );
178 break;
179 }
180 }
181
182 delete ring;
183 return addRingReturnCode;
184}
185
187{
189 for ( QVector<QgsPointXY>::const_iterator it = points.constBegin(); it != points.constEnd(); ++it )
190 {
191 l << QgsPoint( *it );
192 }
193 return addPart( l, featureId );
194}
195
197{
198 if ( !mLayer->isSpatial() )
200
201 QgsGeometry geometry;
202 bool firstPart = false;
203 QgsFeature f;
204 if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setNoAttributes() ).nextFeature( f ) )
206
207 if ( !f.hasGeometry() )
208 {
209 //no existing geometry, so adding first part to null geometry
210 firstPart = true;
211 }
212 else
213 {
214 geometry = f.geometry();
215 }
216
217 Qgis::GeometryOperationResult errorCode = geometry.addPart( points, mLayer->geometryType() );
219 {
220 if ( firstPart && QgsWkbTypes::isSingleType( mLayer->wkbType() )
222 {
223 //convert back to single part if required by layer
224 geometry.convertToSingleType();
225 }
226 mLayer->changeGeometry( featureId, geometry );
227 }
228 return errorCode;
229}
230
232{
233 if ( !mLayer->isSpatial() )
235
236 QgsGeometry geometry;
237 bool firstPart = false;
238 QgsFeature f;
239 if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setNoAttributes() ).nextFeature( f ) )
241
242 if ( !f.hasGeometry() )
243 {
244 //no existing geometry, so adding first part to null geometry
245 firstPart = true;
246 }
247 else
248 {
249 geometry = f.geometry();
250 }
251
252 Qgis::GeometryOperationResult errorCode = geometry.addPart( ring, mLayer->geometryType() );
254 {
255 if ( firstPart && QgsWkbTypes::isSingleType( mLayer->wkbType() )
257 {
258 //convert back to single part if required by layer
259 geometry.convertToSingleType();
260 }
261 mLayer->changeGeometry( featureId, geometry );
262 }
263 return errorCode;
264}
265
266// TODO QGIS 4.0 -- this should return Qgis::GeometryOperationResult
267int QgsVectorLayerEditUtils::translateFeature( QgsFeatureId featureId, double dx, double dy )
268{
269 if ( !mLayer->isSpatial() )
270 return 1;
271
272 QgsFeature f;
273 if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setNoAttributes() ).nextFeature( f ) || !f.hasGeometry() )
274 return 1; //geometry not found
275
276 QgsGeometry geometry = f.geometry();
277
278 Qgis::GeometryOperationResult errorCode = geometry.translate( dx, dy );
280 {
281 mLayer->changeGeometry( featureId, geometry );
282 }
283 return errorCode == Qgis::GeometryOperationResult::Success ? 0 : 1;
284}
285
286Qgis::GeometryOperationResult QgsVectorLayerEditUtils::splitFeatures( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
287{
289 for ( QVector<QgsPointXY>::const_iterator it = splitLine.constBegin(); it != splitLine.constEnd(); ++it )
290 {
291 l << QgsPoint( *it );
292 }
293 return splitFeatures( l, topologicalEditing );
294}
295
297{
298 QgsLineString lineString( splitLine );
299 QgsPointSequence topologyTestPoints;
300 bool preserveCircular = false;
301 return splitFeatures( &lineString, topologyTestPoints, preserveCircular, topologicalEditing );
302}
303
304Qgis::GeometryOperationResult QgsVectorLayerEditUtils::splitFeatures( const QgsCurve *curve, QgsPointSequence &topologyTestPoints, bool preserveCircular, bool topologicalEditing )
305{
306 if ( !mLayer->isSpatial() )
308
309 QgsRectangle bBox; //bounding box of the split line
311 Qgis::GeometryOperationResult splitFunctionReturn; //return code of QgsGeometry::splitGeometry
312 int numberOfSplitFeatures = 0;
313
314 QgsFeatureIterator features;
315 const QgsFeatureIds selectedIds = mLayer->selectedFeatureIds();
316
317 // deactivate preserving circular if the curve contains only straight segments to avoid transforming Polygon to CurvePolygon
318 preserveCircular &= curve->hasCurvedSegments();
319
320 if ( !selectedIds.isEmpty() ) //consider only the selected features if there is a selection
321 {
322 features = mLayer->getSelectedFeatures();
323 }
324 else //else consider all the feature that intersect the bounding box of the split line
325 {
326
327 bBox = curve->boundingBox();
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
359
360 QgsFeature feat;
361 while ( features.nextFeature( feat ) )
362 {
363 if ( !feat.hasGeometry() )
364 {
365 continue;
366 }
367 QVector<QgsGeometry> newGeometries;
368 QgsPointSequence featureTopologyTestPoints;
369 QgsGeometry featureGeom = feat.geometry();
370 splitFunctionReturn = featureGeom.splitGeometry( curve, newGeometries, preserveCircular, topologicalEditing, featureTopologyTestPoints );
371 topologyTestPoints.append( featureTopologyTestPoints );
372 if ( splitFunctionReturn == Qgis::GeometryOperationResult::Success )
373 {
374 //change this geometry
375 mLayer->changeGeometry( feat.id(), featureGeom );
376
377 //insert new features
378 QgsAttributeMap attributeMap = feat.attributes().toMap();
379 for ( const QgsGeometry &geom : std::as_const( newGeometries ) )
380 {
381 featuresDataToAdd << QgsVectorLayerUtils::QgsFeatureData( geom, attributeMap );
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 != Qgis::GeometryOperationResult::Success && splitFunctionReturn != Qgis::GeometryOperationResult::NothingHappened ) // i.e. no split but no error occurred
395 {
396 returnCode = splitFunctionReturn;
397 }
398 }
399
400 if ( !featuresDataToAdd.isEmpty() )
401 {
402 // finally create and add all bits of geometries cut off the original geometries
403 // (this is much faster than creating features one by one)
404 QgsFeatureList featuresListToAdd = QgsVectorLayerUtils::createFeatures( mLayer, featuresDataToAdd );
405 mLayer->addFeatures( featuresListToAdd );
406 }
407
408 if ( numberOfSplitFeatures == 0 )
409 {
411 }
412
413 return returnCode;
414}
415
416Qgis::GeometryOperationResult QgsVectorLayerEditUtils::splitParts( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
417{
419 for ( QVector<QgsPointXY>::const_iterator it = splitLine.constBegin(); it != splitLine.constEnd(); ++it )
420 {
421 l << QgsPoint( *it );
422 }
423 return splitParts( l, topologicalEditing );
424}
425
427{
428 if ( !mLayer->isSpatial() )
430
431 double xMin, yMin, xMax, yMax;
432 QgsRectangle bBox; //bounding box of the split line
434 Qgis::GeometryOperationResult splitFunctionReturn; //return code of QgsGeometry::splitGeometry
435 int numberOfSplitParts = 0;
436
438
439 if ( mLayer->selectedFeatureCount() > 0 ) //consider only the selected features if there is a selection
440 {
441 fit = mLayer->getSelectedFeatures();
442 }
443 else //else consider all the feature that intersect the bounding box of the split line
444 {
445 if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) )
446 {
447 bBox.setXMinimum( xMin );
448 bBox.setYMinimum( yMin );
449 bBox.setXMaximum( xMax );
450 bBox.setYMaximum( yMax );
451 }
452 else
453 {
455 }
456
457 if ( bBox.isEmpty() )
458 {
459 //if the bbox is a line, try to make a square out of it
460 if ( bBox.width() == 0.0 && bBox.height() > 0 )
461 {
462 bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
463 bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
464 }
465 else if ( bBox.height() == 0.0 && bBox.width() > 0 )
466 {
467 bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
468 bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
469 }
470 else
471 {
472 //If we have a single point, we still create a non-null box
473 double bufferDistance = 0.000001;
474 if ( mLayer->crs().isGeographic() )
475 bufferDistance = 0.00000001;
476 bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
477 bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
478 bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
479 bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
480 }
481 }
482
483 fit = mLayer->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
484 }
485
486 QgsFeature feat;
487 while ( fit.nextFeature( feat ) )
488 {
489 QVector<QgsGeometry> newGeometries;
490 QgsPointSequence topologyTestPoints;
491 QgsGeometry featureGeom = feat.geometry();
492 splitFunctionReturn = featureGeom.splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints, false );
493
494 if ( splitFunctionReturn == Qgis::GeometryOperationResult::Success && !newGeometries.isEmpty() )
495 {
496 QgsGeometry newGeom( newGeometries.at( 0 ) );
497 newGeom.convertToMultiType();
498
499 for ( int i = 1; i < newGeometries.size(); ++i )
500 {
501 QgsGeometry part = newGeometries.at( i );
502 part.convertToSingleType();
503 newGeom.addPart( part );
504 }
505
506 mLayer->changeGeometry( feat.id(), newGeom );
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 != Qgis::GeometryOperationResult::Success && splitFunctionReturn != Qgis::GeometryOperationResult::NothingHappened )
519 {
520 returnCode = splitFunctionReturn;
521 }
522 }
523
524 if ( numberOfSplitParts == 0 && mLayer->selectedFeatureCount() > 0 && returnCode == Qgis::GeometryOperationResult::Success )
525 {
526 //There is a selection but no feature has been split.
527 //Maybe user forgot that only the selected features are split
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 bool pointsAdded = false;
546
548 while ( it != geom.vertices_end() )
549 {
550 if ( addTopologicalPoints( *it ) == 0 )
551 {
552 pointsAdded = true;
553 }
554 ++it;
555 }
556
557 return pointsAdded ? 0 : 2;
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 bool pointsAdded = false;
613 for ( QMap<QgsFeatureId, int>::const_iterator it = segments.constBegin(); it != segments.constEnd(); ++it )
614 {
615 QgsFeatureId fid = it.key();
616 int segmentAfterVertex = it.value();
617 QgsGeometry geom = features[fid];
618
619 int atVertex, beforeVertex, afterVertex;
620 double sqrDistVertexSnap;
621 geom.closestVertex( p, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
622
623 if ( sqrDistVertexSnap < sqrSnappingTolerance )
624 continue; // the vertex already exists - do not insert it
625
626 if ( !mLayer->insertVertex( p, fid, segmentAfterVertex ) )
627 {
628 QgsDebugMsg( QStringLiteral( "failed to insert topo point" ) );
629 }
630 else
631 {
632 pointsAdded = true;
633 }
634 }
635
636 return pointsAdded ? 0 : 2;
637}
638
640{
641 if ( !mLayer->isSpatial() )
642 return 1;
643
644 if ( ps.isEmpty() )
645 {
646 return 1;
647 }
648
649 bool pointsAdded = false;
650
651 QgsPointSequence::const_iterator it = ps.constBegin();
652 while ( it != ps.constEnd() )
653 {
654 if ( addTopologicalPoints( *it ) == 0 )
655 {
656 pointsAdded = true;
657 }
658 ++it;
659 }
660
661 return pointsAdded ? 0 : 2;
662}
663
665{
666 return addTopologicalPoints( QgsPoint( p ) );
667}
668
669
670bool QgsVectorLayerEditUtils::boundingBoxFromPointList( const QgsPointSequence &list, double &xmin, double &ymin, double &xmax, double &ymax ) const
671{
672 if ( list.empty() )
673 {
674 return false;
675 }
676
677 xmin = std::numeric_limits<double>::max();
678 xmax = -std::numeric_limits<double>::max();
679 ymin = std::numeric_limits<double>::max();
680 ymax = -std::numeric_limits<double>::max();
681
682 for ( QgsPointSequence::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
683 {
684 if ( it->x() < xmin )
685 {
686 xmin = it->x();
687 }
688 if ( it->x() > xmax )
689 {
690 xmax = it->x();
691 }
692 if ( it->y() < ymin )
693 {
694 ymin = it->y();
695 }
696 if ( it->y() > ymax )
697 {
698 ymax = it->y();
699 }
700 }
701
702 return true;
703}
GeometryOperationResult
Success or failure of a geometry operation.
Definition: qgis.h:935
@ AddPartSelectedGeometryNotFound
The selected geometry cannot be found.
@ InvalidInputGeometryType
The input geometry (ring, part, split line, etc.) has not the correct geometry type.
@ Success
Operation succeeded.
@ AddRingNotInExistingFeature
The input ring doesn't have any existing ring to fit into.
@ NothingHappened
Nothing happened, without any error.
@ InvalidBaseGeometry
The base geometry on which the operation is done is invalid or empty.
VectorEditResult
Flags which control feature selection behavior.
Definition: qgis.h:825
@ EmptyGeometry
Edit operation resulted in an empty geometry.
@ Success
Edit operation was successful.
@ FetchFeatureFailed
Unable to fetch requested feature.
@ EditFailed
Edit operation failed.
@ InvalidLayer
Edit failed due to invalid layer.
The vertex_iterator class provides STL-style iterator for vertices.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
virtual bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
CORE_EXPORT QgsAttributeMap toMap() const
Returns a QgsAttributeMap of the attribute values.
Q_GADGET QgsUnitTypes::DistanceUnit mapUnits
Abstract base class for curved geometry type.
Definition: qgscurve.h:36
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
Definition: qgscurve.cpp:238
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
@ ExactIntersect
Use exact geometry intersection (slower) instead of bounding boxes.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsAttributes attributes
Definition: qgsfeature.h:65
QgsGeometry geometry
Definition: qgsfeature.h:67
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:230
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
double geometryPrecision() const
The precision in which geometries on this layer should be saved.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:164
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
bool deleteVertex(int atVertex)
Deletes the vertex at the given position number and item (first number is index 0)
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 ...
Qgis::GeometryOperationResult addPart(const QVector< QgsPointXY > &points, QgsWkbTypes::GeometryType geomType=QgsWkbTypes::UnknownGeometry)
Adds a new part to a the geometry.
Q_GADGET bool isNull
Definition: qgsgeometry.h:166
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 convertToSingleType()
Converts multi type geometry into single type geometry e.g.
Qgis::GeometryOperationResult addRing(const QVector< QgsPointXY > &ring)
Adds a new ring to this geometry.
void set(QgsAbstractGeometry *geometry)
Sets the underlying geometry store.
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
Qgis::GeometryOperationResult translate(double dx, double dy, double dz=0.0, double dm=0.0)
Translates this geometry by dx, dy, dz and dm.
Q_DECL_DEPRECATED Qgis::GeometryOperationResult splitGeometry(const QVector< QgsPointXY > &splitLine, QVector< QgsGeometry > &newGeometries, bool topological, QVector< QgsPointXY > &topologyTestPoints, bool splitFeature=true)
Splits this geometry according to a given line.
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...
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.
QgsAbstractGeometry::vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:45
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:79
A class to represent a 2D point.
Definition: qgspointxy.h:59
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
Q_GADGET double x
Definition: qgspoint.h:52
double y
Definition: qgspoint.h:53
A rectangle specified with double values.
Definition: qgsrectangle.h:42
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
void setYMinimum(double y) SIP_HOLDGIL
Set the minimum y value.
Definition: qgsrectangle.h:161
void setXMaximum(double x) SIP_HOLDGIL
Set the maximum x value.
Definition: qgsrectangle.h:156
void setXMinimum(double x) SIP_HOLDGIL
Set the minimum x value.
Definition: qgsrectangle.h:151
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
void setYMaximum(double y) SIP_HOLDGIL
Set the maximum y value.
Definition: qgsrectangle.h:166
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:469
@ DistanceMeters
Meters.
Definition: qgsunittypes.h:69
@ DistanceFeet
Imperial feet.
Definition: qgsunittypes.h:71
virtual bool doesStrictFeatureTypeCheck() const
Returns true if the provider is strict about the type of inserted features (e.g.
int translateFeature(QgsFeatureId featureId, double dx, double dy)
Translates feature by dx, dy.
QgsVectorLayerEditUtils(QgsVectorLayer *layer)
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)...
Q_DECL_DEPRECATED Qgis::GeometryOperationResult addPart(const QVector< QgsPointXY > &ring, QgsFeatureId featureId)
Adds a new part polygon to a multipart feature.
Qgis::VectorEditResult deleteVertex(QgsFeatureId featureId, int vertex)
Deletes a vertex from a feature.
int addTopologicalPoints(const QgsGeometry &geom)
Adds topological points for every vertex of the geometry.
Q_DECL_DEPRECATED Qgis::GeometryOperationResult splitParts(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
Q_DECL_DEPRECATED Qgis::GeometryOperationResult splitFeatures(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
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),...
Q_DECL_DEPRECATED Qgis::GeometryOperationResult addRing(const QVector< QgsPointXY > &ring, const QgsFeatureIds &targetFeatureIds=QgsFeatureIds(), QgsFeatureId *modifiedFeatureId=nullptr)
Adds a ring to polygon/multipolygon features.
Encapsulate geometry and attributes for new features, to be passed to createFeatures.
QList< QgsVectorLayerUtils::QgsFeatureData > QgsFeaturesDataList
Alias for list of QgsFeatureData.
static QgsFeatureList createFeatures(const QgsVectorLayer *layer, const QgsFeaturesDataList &featuresData, QgsExpressionContext *context=nullptr)
Creates a set of new features ready for insertion into a layer.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
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...
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a list of features to the sink.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QgsGeometryOptions * geometryOptions() const
Configuration and logic to apply automatically on any edit happening on this layer.
QgsFeatureIterator getSelectedFeatures(QgsFeatureRequest request=QgsFeatureRequest()) const
Returns an iterator of the selected features.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
bool changeGeometry(QgsFeatureId fid, QgsGeometry &geometry, bool skipDefaultValue=false)
Changes a feature's geometry within the layer's edit buffer (but does not immediately commit the chan...
static bool isSingleType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a single type.
Definition: qgswkbtypes.h:852
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2507
QVector< QgsPoint > QgsPointSequence
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:42
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:922
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
#define QgsDebugMsg(str)
Definition: qgslogger.h:38