Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsgeometryengine.h
3 : : -------------------------------------------------------------------
4 : : Date : 22 Sept 2014
5 : : Copyright : (C) 2014 by Marco Hugentobler
6 : : email : marco.hugentobler at sourcepole 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 : :
16 : : #ifndef QGSGEOMETRYENGINE_H
17 : : #define QGSGEOMETRYENGINE_H
18 : :
19 : : #include "qgis_core.h"
20 : : #include "qgslinestring.h"
21 : : #include "qgsgeometry.h"
22 : : #include "qgslogger.h"
23 : :
24 : : #include <QVector>
25 : :
26 : : class QgsAbstractGeometry;
27 : :
28 : : /**
29 : : * \ingroup core
30 : : * \class QgsGeometryEngine
31 : : * \brief Contains geometry relation and modification algorithms.
32 : : * \since QGIS 2.10
33 : : */
34 : : class CORE_EXPORT QgsGeometryEngine
35 : : {
36 : : public:
37 : :
38 : : /**
39 : : * Success or failure of a geometry operation.
40 : : * This gives details about cause of failure.
41 : : */
42 : : enum EngineOperationResult
43 : : {
44 : : Success = 0, //!< Operation succeeded
45 : : NothingHappened = 1000, //!< Nothing happened, without any error
46 : : MethodNotImplemented, //!< Method not implemented in geometry engine
47 : : EngineError, //!< Error occurred in the geometry engine
48 : : NodedGeometryError, //!< Error occurred while creating a noded geometry
49 : : InvalidBaseGeometry, //!< The geometry on which the operation occurs is not valid
50 : : InvalidInput, //!< The input is not valid
51 : : /* split */
52 : : SplitCannotSplitPoint, //!< Points cannot be split
53 : : };
54 : :
55 : 30456 : virtual ~QgsGeometryEngine() = default;
56 : :
57 : : /**
58 : : * Should be called whenever the geometry associated with the engine
59 : : * has been modified and the engine must be updated to suit.
60 : : */
61 : : virtual void geometryChanged() = 0;
62 : :
63 : : /**
64 : : * Prepares the geometry, so that subsequent calls to spatial relation methods
65 : : * are much faster.
66 : : *
67 : : * This should be called for any geometry which is used for multiple relation
68 : : * tests against other geometries.
69 : : *
70 : : * \see geometryChanged()
71 : : */
72 : : virtual void prepareGeometry() = 0;
73 : :
74 : : /**
75 : : * Calculate the intersection of this and \a geom.
76 : : *
77 : : * \since QGIS 3.0 \a geom is a pointer
78 : : */
79 : : virtual QgsAbstractGeometry *intersection( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;
80 : :
81 : : /**
82 : : * Calculate the difference of this and \a geom.
83 : : *
84 : : * \since QGIS 3.0 \a geom is a pointer
85 : : */
86 : : virtual QgsAbstractGeometry *difference( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;
87 : :
88 : : /**
89 : : * Calculate the combination of this and \a geom.
90 : : *
91 : : * \since QGIS 3.0 \a geom is a pointer
92 : : */
93 : : virtual QgsAbstractGeometry *combine( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;
94 : :
95 : : /**
96 : : * Calculate the combination of this and \a geometries.
97 : : *
98 : : * \since QGIS 3.0 \a geom is a pointer
99 : : */
100 : : virtual QgsAbstractGeometry *combine( const QVector<QgsAbstractGeometry *> &geomList, QString *errorMsg ) const = 0 SIP_FACTORY;
101 : :
102 : : /**
103 : : * Calculate the combination of this and \a geometries.
104 : : *
105 : : * \since QGIS 3.0 \a geom is a pointer
106 : : */
107 : : virtual QgsAbstractGeometry *combine( const QVector< QgsGeometry > &geometries, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;
108 : :
109 : : /**
110 : : * Calculate the symmetric difference of this and \a geom.
111 : : *
112 : : * \since QGIS 3.0 \a geom is a pointer
113 : : */
114 : : virtual QgsAbstractGeometry *symDifference( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;
115 : : virtual QgsAbstractGeometry *buffer( double distance, int segments, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;
116 : : virtual QgsAbstractGeometry *buffer( double distance, int segments, int endCapStyle, int joinStyle, double miterLimit, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;
117 : : virtual QgsAbstractGeometry *simplify( double tolerance, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;
118 : : virtual QgsAbstractGeometry *interpolate( double distance, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;
119 : : virtual QgsAbstractGeometry *envelope( QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;
120 : :
121 : : /**
122 : : * Calculates the centroid of this.
123 : : * May return a `NULLPTR`.
124 : : *
125 : : * \since QGIS 3.0 the centroid is returned
126 : : */
127 : : virtual QgsPoint *centroid( QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;
128 : :
129 : : /**
130 : : * Calculate a point that is guaranteed to be on the surface of this.
131 : : * May return a `NULLPTR`.
132 : : *
133 : : * \since QGIS 3.0 the centroid is returned
134 : : */
135 : : virtual QgsPoint *pointOnSurface( QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;
136 : :
137 : : /**
138 : : * Calculate the convex hull of this.
139 : : */
140 : : virtual QgsAbstractGeometry *convexHull( QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;
141 : :
142 : : /**
143 : : * Calculates the distance between this and \a geom.
144 : : *
145 : : * \since QGIS 3.0 \a geom is a pointer
146 : : */
147 : : virtual double distance( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0;
148 : :
149 : : /**
150 : : * Checks if \a geom intersects this.
151 : : *
152 : : * \since QGIS 3.0 \a geom is a pointer
153 : : */
154 : : virtual bool intersects( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0;
155 : :
156 : : /**
157 : : * Checks if \a geom touches this.
158 : : *
159 : : * \since QGIS 3.0 \a geom is a pointer
160 : : */
161 : : virtual bool touches( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0;
162 : :
163 : : /**
164 : : * Checks if \a geom crosses this.
165 : : *
166 : : * \since QGIS 3.0 \a geom is a pointer
167 : : */
168 : : virtual bool crosses( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0;
169 : :
170 : : /**
171 : : * Checks if \a geom is within this.
172 : : *
173 : : * \since QGIS 3.0 \a geom is a pointer
174 : : */
175 : : virtual bool within( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0;
176 : :
177 : : /**
178 : : * Checks if \a geom overlaps this.
179 : : *
180 : : * \since QGIS 3.0 \a geom is a pointer
181 : : */
182 : : virtual bool overlaps( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0;
183 : :
184 : : /**
185 : : * Checks if \a geom contains this.
186 : : *
187 : : * \since QGIS 3.0 \a geom is a pointer
188 : : */
189 : : virtual bool contains( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0;
190 : :
191 : : /**
192 : : * Checks if \a geom is disjoint from this.
193 : : *
194 : : * \since QGIS 3.0 \a geom is a pointer
195 : : */
196 : : virtual bool disjoint( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0;
197 : :
198 : : /**
199 : : * Returns the Dimensional Extended 9 Intersection Model (DE-9IM) representation of the
200 : : * relationship between the geometries.
201 : : * \param geom geometry to relate to
202 : : * \param errorMsg destination storage for any error message
203 : : * \returns DE-9IM string for relationship, or an empty string if an error occurred
204 : : * \since QGIS 2.12
205 : : */
206 : : virtual QString relate( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0;
207 : :
208 : : /**
209 : : * Tests whether two geometries are related by a specified Dimensional Extended 9 Intersection Model (DE-9IM)
210 : : * pattern.
211 : : * \param geom geometry to relate to
212 : : * \param pattern DE-9IM pattern for match
213 : : * \param errorMsg destination storage for any error message
214 : : * \returns TRUE if geometry relationship matches with pattern
215 : : * \since QGIS 2.14
216 : : */
217 : : virtual bool relatePattern( const QgsAbstractGeometry *geom, const QString &pattern, QString *errorMsg = nullptr ) const = 0;
218 : :
219 : : virtual double area( QString *errorMsg = nullptr ) const = 0;
220 : : virtual double length( QString *errorMsg = nullptr ) const = 0;
221 : :
222 : : /**
223 : : * Returns TRUE if the geometry is valid.
224 : : *
225 : : * If the geometry is invalid, \a errorMsg will be filled with the reported geometry error.
226 : : *
227 : : * The \a allowSelfTouchingHoles argument specifies whether self-touching holes are permitted.
228 : : * OGC validity states that self-touching holes are NOT permitted, whilst other vendor
229 : : * validity checks (e.g. ESRI) permit self-touching holes.
230 : : *
231 : : * If \a errorLoc is specified, it will be set to the geometry of the error location.
232 : : */
233 : : virtual bool isValid( QString *errorMsg = nullptr, bool allowSelfTouchingHoles = false, QgsGeometry *errorLoc = nullptr ) const = 0;
234 : :
235 : : /**
236 : : * Checks if this is equal to \a geom.
237 : : * If both are Null geometries, `FALSE` is returned.
238 : : *
239 : : * \since QGIS 3.0 \a geom is a pointer
240 : : */
241 : : virtual bool isEqual( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0;
242 : : virtual bool isEmpty( QString *errorMsg ) const = 0;
243 : :
244 : : /**
245 : : * Determines whether the geometry is simple (according to OGC definition).
246 : : * \since QGIS 3.0
247 : : */
248 : : virtual bool isSimple( QString *errorMsg = nullptr ) const = 0;
249 : :
250 : : /**
251 : : * Splits this geometry according to a given line.
252 : : * \param splitLine the line that splits the geometry
253 : : * \param[out] newGeometries list of new geometries that have been created with the split
254 : : * \param topological TRUE if topological editing is enabled
255 : : * \param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
256 : : * \param[out] errorMsg error messages emitted, if any
257 : : * \param skipIntersectionCheck set to TRUE to skip the potentially expensive initial intersection check. Only set this flag if an intersection
258 : : * test has already been performed by the caller!
259 : : * \returns 0 in case of success, 1 if geometry has not been split, error else
260 : : */
261 : 0 : virtual QgsGeometryEngine::EngineOperationResult splitGeometry( const QgsLineString &splitLine,
262 : : QVector<QgsGeometry > &newGeometries SIP_OUT,
263 : : bool topological,
264 : : QgsPointSequence &topologyTestPoints, QString *errorMsg = nullptr, bool skipIntersectionCheck = false ) const
265 : : {
266 : 0 : Q_UNUSED( splitLine )
267 : 0 : Q_UNUSED( newGeometries )
268 : : Q_UNUSED( topological )
269 : 0 : Q_UNUSED( topologyTestPoints )
270 : : Q_UNUSED( errorMsg )
271 : : Q_UNUSED( skipIntersectionCheck )
272 : 0 : return MethodNotImplemented;
273 : : }
274 : :
275 : : virtual QgsAbstractGeometry *offsetCurve( double distance, int segments, int joinStyle, double miterLimit, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;
276 : :
277 : : /**
278 : : * Sets whether warnings and errors encountered during the geometry operations should be logged.
279 : : *
280 : : * By default these errors are logged to the console and in the QGIS UI. But for some operations errors are expected and logging
281 : : * these just results in noise. In this case setting \a enabled to FALSE will avoid the automatic error reporting.
282 : : *
283 : : * \since QGIS 3.16
284 : : */
285 : : void setLogErrors( bool enabled ) { mLogErrors = enabled; }
286 : :
287 : : protected:
288 : : const QgsAbstractGeometry *mGeometry = nullptr;
289 : 30456 : bool mLogErrors = true;
290 : :
291 : : /**
292 : : * Logs an error \a message encountered during an operation.
293 : : *
294 : : * \see setLogErrors()
295 : : *
296 : : * \since QGIS 3.16
297 : : */
298 : 4 : void logError( const QString &engineName, const QString &message ) const
299 : : {
300 : 4 : if ( mLogErrors )
301 : : {
302 : 4 : QgsDebugMsg( QStringLiteral( "%1 notice: %2" ).arg( engineName, message ) );
303 : 4 : qWarning( "%s exception: %s", engineName.toLocal8Bit().constData(), message.toLocal8Bit().constData() );
304 : 4 : }
305 : 4 : }
306 : :
307 : 30456 : QgsGeometryEngine( const QgsAbstractGeometry *geometry )
308 : 30456 : : mGeometry( geometry )
309 : 60912 : {}
310 : : };
311 : :
312 : : #endif // QGSGEOMETRYENGINE_H
313 : :
|