1 /***************************************************************************
2     qgsvectorlayereditutils.h
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  ***************************************************************************/
15 #ifndef QGSVECTORLAYEREDITUTILS_H
16 #define QGSVECTORLAYEREDITUTILS_H
17 
18 
19 #include "qgis_core.h"
20 #include "qgis_sip.h"
21 #include "qgsfeatureid.h"
22 #include "qgsvectorlayer.h"
23 
24 class QgsCurve;
25 class QgsGeometry;
26 
27 /**
28  * \ingroup core
29  * \class QgsVectorLayerEditUtils
30  */
31 class CORE_EXPORT QgsVectorLayerEditUtils
32 {
33   public:
34     QgsVectorLayerEditUtils( QgsVectorLayer *layer );
35 
36     /**
37      * Insert a new vertex before the given vertex number,
38      * in the given ring, item (first number is index 0), and feature
39      * Not meaningful for Point geometries
40      */
41     bool insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex );
42 
43     /**
44      * Inserts a new vertex before the given vertex number,
45      * in the given ring, item (first number is index 0), and feature
46      * Not meaningful for Point geometries
47      */
48     bool insertVertex( const QgsPoint &point, QgsFeatureId atFeatureId, int beforeVertex );
49 
50     /**
51      * Moves the vertex at the given position number,
52      * ring and item (first number is index 0), and feature
53      * to the given coordinates
54      */
55     bool moveVertex( double x, double y, QgsFeatureId atFeatureId, int atVertex );
56 
57     /**
58      * Moves the vertex at the given position number,
59      * ring and item (first number is index 0), and feature
60      * to the given coordinates
61      * \note available in Python bindings as moveVertexV2
62      */
63     bool moveVertex( const QgsPoint &p, QgsFeatureId atFeatureId, int atVertex ) SIP_PYNAME( moveVertexV2 );
64 
65     /**
66      * Deletes a vertex from a feature.
67      * \param featureId ID of feature to remove vertex from
68      * \param vertex index of vertex to delete
69      * \since QGIS 2.14
70      */
71     Qgis::VectorEditResult deleteVertex( QgsFeatureId featureId, int vertex );
72 
73     /**
74      * Adds a ring to polygon/multipolygon features
75      * \param ring ring to add
76      * \param targetFeatureIds if specified, only these features will be the candidates for adding a ring. Otherwise
77      * all intersecting features are tested and the ring is added to the first valid feature.
78      * \param modifiedFeatureId if specified, feature ID for feature that ring was added to will be stored in this parameter
79      * \return OperationResult result code: success or reason of failure
80      * \deprecated since QGIS 3.12 - will be removed in QGIS 4.0. Use the variant which accepts QgsPoint objects instead of QgsPointXY.
81      */
82     Q_DECL_DEPRECATED Qgis::GeometryOperationResult addRing( const QVector<QgsPointXY> &ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = nullptr ) SIP_DEPRECATED;
83 
84     /**
85      * Adds a ring to polygon/multipolygon features
86      * \param ring ring to add
87      * \param targetFeatureIds if specified, only these features will be the candidates for adding a ring. Otherwise
88      * all intersecting features are tested and the ring is added to the first valid feature.
89      * \param modifiedFeatureId if specified, feature ID for feature that ring was added to will be stored in this parameter
90      * \return OperationResult result code: success or reason of failure
91      */
92     Qgis::GeometryOperationResult addRing( const QgsPointSequence &ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = nullptr );
93 
94     /**
95      * Adds a ring to polygon/multipolygon features
96      * \param ring ring to add
97      * \param targetFeatureIds if specified, only these features will be the candidates for adding a ring. Otherwise
98      * all intersecting features are tested and the ring is added to the first valid feature.
99      * \param modifiedFeatureId if specified, feature ID for feature that ring was added to will be stored in this parameter
100      * \return OperationResult result code: success or reason of failure
101      * \note available in python bindings as addCurvedRing
102      */
103     Qgis::GeometryOperationResult addRing( QgsCurve *ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = nullptr ) SIP_PYNAME( addCurvedRing );
104 
105     /**
106      * Adds a new part polygon to a multipart feature
107      * \returns - QgsGeometry::Success
108      *
109      * - QgsGeometry::AddPartSelectedGeometryNotFound
110      * - QgsGeometry::AddPartNotMultiGeometry
111      * - QgsGeometry::InvalidBaseGeometry
112      * - QgsGeometry::InvalidInput
113      *
114      * \deprecated since QGIS 3.12 - will be removed in QGIS 4.0. Use the variant which accepts QgsPoint objects instead of QgsPointXY.
115      */
116     Q_DECL_DEPRECATED  Qgis::GeometryOperationResult addPart( const QVector<QgsPointXY> &ring, QgsFeatureId featureId ) SIP_DEPRECATED;
117 
118     /**
119      * Adds a new part polygon to a multipart feature
120      *
121      * \returns - QgsGeometry::Success
122      *
123      * - QgsGeometry::AddPartSelectedGeometryNotFound
124      * - QgsGeometry::AddPartNotMultiGeometry
125      * - QgsGeometry::InvalidBaseGeometry
126      * - QgsGeometry::InvalidInput
127      *
128      * \note available in python bindings as addPartV2
129      */
130     Qgis::GeometryOperationResult addPart( const QgsPointSequence &ring, QgsFeatureId featureId );
131 
132     /**
133      * Adds a new part polygon to a multipart feature
134      *
135      * \returns - QgsGeometry::Success
136      *
137      * - QgsGeometry::AddPartSelectedGeometryNotFound
138      * - QgsGeometry::AddPartNotMultiGeometry
139      * - QgsGeometry::InvalidBaseGeometry
140      * - QgsGeometry::InvalidInput
141      *
142      * \note available in python bindings as addCurvedPart
143      */
144     Qgis::GeometryOperationResult addPart( QgsCurve *ring, QgsFeatureId featureId ) SIP_PYNAME( addCurvedPart );
145 
146     /**
147      * Translates feature by dx, dy
148      * \param featureId id of the feature to translate
149      * \param dx translation of x-coordinate
150      * \param dy translation of y-coordinate
151      * \return 0 in case of success
152      */
153     int translateFeature( QgsFeatureId featureId, double dx, double dy );
154 
155     /**
156      * Splits parts cut by the given line
157      * \param splitLine line that splits the layer feature parts
158      * \param topologicalEditing TRUE if topological editing is enabled
159      * \returns  - QgsGeometry::InvalidBaseGeometry
160      *
161      * - QgsGeometry::Success
162      * - QgsGeometry::InvalidInput
163      * - QgsGeometry::NothingHappened if a selection is present but no feature has been split
164      * - QgsGeometry::InvalidBaseGeometry
165      * - QgsGeometry::GeometryEngineError
166      * - QgsGeometry::SplitCannotSplitPoint
167      *
168      * \deprecated since QGIS 3.12 - will be removed in QGIS 4.0. Use the variant which accepts QgsPoint objects instead of QgsPointXY.
169      */
170     Q_DECL_DEPRECATED  Qgis::GeometryOperationResult splitParts( const QVector<QgsPointXY> &splitLine, bool topologicalEditing = false ) SIP_DEPRECATED;
171 
172     /**
173      * Splits parts cut by the given line
174      * \param splitLine line that splits the layer feature parts
175      * \param topologicalEditing TRUE if topological editing is enabled
176      * \returns  - QgsGeometry::InvalidBaseGeometry
177      *
178      * - QgsGeometry::Success
179      * - QgsGeometry::InvalidInput
180      * - QgsGeometry::NothingHappened if a selection is present but no feature has been split
181      * - QgsGeometry::InvalidBaseGeometry
182      * - QgsGeometry::GeometryEngineError
183      * - QgsGeometry::SplitCannotSplitPoint
184      */
185     Qgis::GeometryOperationResult splitParts( const QgsPointSequence &splitLine, bool topologicalEditing = false );
186 
187     /**
188      * Splits features cut by the given line
189      * \param splitLine line that splits the layer features
190      * \param topologicalEditing TRUE if topological editing is enabled
191      * \returns QgsGeometry::OperationResult
192      * \deprecated since QGIS 3.12 - will be removed in QGIS 4.0. Use the variant which accepts QgsPoint objects instead of QgsPointXY.
193      */
194     Q_DECL_DEPRECATED  Qgis::GeometryOperationResult splitFeatures( const QVector<QgsPointXY> &splitLine, bool topologicalEditing = false ) SIP_DEPRECATED;
195 
196     /**
197      * Splits features cut by the given line
198      * \param splitLine line that splits the layer features
199      * \param topologicalEditing TRUE if topological editing is enabled
200      * \returns QgsGeometry::OperationResult
201      */
202     Qgis::GeometryOperationResult splitFeatures( const QgsPointSequence &splitLine, bool topologicalEditing = false );
203 
204     /**
205      * Splits features cut by the given curve
206      * \param curve line that splits the layer features
207      * \param[out] topologyTestPoints topological points to be tested against other layers
208      * \param preserveCircular whether circular strings are preserved after splitting
209      * \param topologicalEditing TRUE if topological editing is enabled
210      * \returns QgsGeometry::OperationResult
211      * \since QGIS 3.16
212      */
213     Qgis::GeometryOperationResult splitFeatures( const QgsCurve *curve, QgsPointSequence &topologyTestPoints SIP_OUT, bool preserveCircular = false, bool topologicalEditing = false );
214 
215     /**
216      * Adds topological points for every vertex of the geometry.
217      * \param geom the geometry where each vertex is added to segments of other features
218      * \return 0 in case of success
219      * \return 1 in case of error
220      * \return 2 in case no vertices needed to be added
221      * \note geom is not going to be modified by the function
222      */
223     int addTopologicalPoints( const QgsGeometry &geom );
224 
225     /**
226      * Adds a vertex to segments which intersect point \a p but don't
227      * already have a vertex there. If a feature already has a vertex at position p,
228      * no additional vertex is inserted. This method is useful for topological
229      * editing.
230      * \return 0 in case of success
231      * \return 1 in case of error
232      * \return 2 in case no vertices needed to be added
233      */
234     int addTopologicalPoints( const QgsPointXY &p );
235 
236     /**
237      * Adds a vertex to segments which intersect point \a p but don't
238      * already have a vertex there. If a feature already has a vertex at position p,
239      * no additional vertex is inserted. This method is useful for topological
240      * editing.
241      * \return 0 in case of success
242      * \return 1 in case of error
243      * \return 2 in case no vertices needed to be added
244      * \since QGIS 3.10
245      */
246     int addTopologicalPoints( const QgsPoint &p );
247 
248     /**
249      * Adds a vertex to segments which intersect point \a p but don't
250      * already have a vertex there. If a feature already has a vertex at position p,
251      * no additional vertex is inserted. This method is useful for topological
252      * editing.
253      * \return 0 in case of success
254      * \return 1 in case of error
255      * \return 2 in case vertex already exists or point does not intersect segment
256      * \since QGIS 3.16
257      */
258     int addTopologicalPoints( const QgsPointSequence &ps );
259 
260   private:
261 
262     /**
263      * Little helper function that gives bounding box from a list of points.
264      * \returns TRUE in case of success
265      */
266     bool boundingBoxFromPointList( const QgsPointSequence &list, double &xmin, double &ymin, double &xmax, double &ymax ) const;
267 
268     QgsVectorLayer *mLayer = nullptr;
269 };
270 
271 #endif // QGSVECTORLAYEREDITUTILS_H
272