QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
qgscadutils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgscadutils.cpp
3 -------------------
4 begin : September 2017
5 copyright : (C) 2017 by Martin Dobias
6 email : wonder dot sk at gmail dot com
7 ***************************************************************************/
8/***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17#include "qgscadutils.h"
18
19#include "qgscurvepolygon.h"
21#include "qgsgeometryutils.h"
22#include "qgslogger.h"
23#include "qgssnappingutils.h"
24
25#include <QQueue>
26#include <QString>
27
28using namespace Qt::StringLiterals;
29
30// tolerances for soft constraints (last values, and common angles)
31// for angles, both tolerance in pixels and degrees are used for better performance
32static const double SOFT_CONSTRAINT_TOLERANCE_PIXEL = 15;
33static const double SOFT_CONSTRAINT_TOLERANCE_DEGREES = 10;
34
35
37struct EdgesOnlyFilter : public QgsPointLocator::MatchFilter
38{
39 bool acceptMatch( const QgsPointLocator::Match &m ) override { return m.hasEdge(); }
40};
42
43
45{
47 res.valid = true;
48 res.softLockCommonAngle = -1;
49
51 res.softLockX = std::numeric_limits<double>::quiet_NaN();
52 res.softLockY = std::numeric_limits<double>::quiet_NaN();
53
54 // try to snap to project layer(s) as well as visible construction guides
55 QgsPointLocator::Match snapMatch = ctx.snappingUtils->snapToMap( originalMapPoint, nullptr, true );
56 res.snapMatch = snapMatch;
57 QgsPointXY point = snapMatch.isValid() ? snapMatch.point() : originalMapPoint;
58 QgsPointXY edgePt0, edgePt1;
59 if ( snapMatch.hasEdge() )
60 {
61 snapMatch.edgePoints( edgePt0, edgePt1 );
62 // note : res.edgeMatch should be removed, as we can just check snapMatch.hasEdge()
63 res.edgeMatch = snapMatch;
64 }
65 else
66 {
68 }
69
70 int numberOfHardLock = 0;
71 if ( ctx.xConstraint.locked ) ++numberOfHardLock;
72 if ( ctx.yConstraint.locked ) ++numberOfHardLock;
73 if ( ctx.angleConstraint.locked ) ++numberOfHardLock;
74 if ( ctx.distanceConstraint.locked ) ++numberOfHardLock;
75
76 QgsPointXY previousPt, penultimatePt;
77 if ( ctx.cadPoints().count() >= 2 )
78 previousPt = ctx.cadPoint( 1 );
79 if ( ctx.cadPoints().count() >= 3 )
80 penultimatePt = ctx.cadPoint( 2 );
81
82 // *****************************
83 // ---- X constraint
84 if ( ctx.xConstraint.locked )
85 {
86 if ( !ctx.xConstraint.relative )
87 {
88 point.setX( ctx.xConstraint.value );
89 }
90 else if ( ctx.cadPoints().count() >= 2 )
91 {
92 point.setX( previousPt.x() + ctx.xConstraint.value );
93 }
94 if ( snapMatch.hasEdge() && !ctx.yConstraint.locked )
95 {
96 // intersect with snapped segment line at X coordinate
97 const double dx = edgePt1.x() - edgePt0.x();
98 if ( dx == 0 )
99 {
100 point.setY( edgePt0.y() );
101 }
102 else
103 {
104 const double dy = edgePt1.y() - edgePt0.y();
105 point.setY( edgePt0.y() + ( dy * ( point.x() - edgePt0.x() ) ) / dx );
106 }
107 }
108 }
109 else if ( numberOfHardLock < 2 && ctx.xyVertexConstraint.locked )
110 {
111 for ( QgsPointLocator::Match snapMatch : ctx.lockedSnapVertices() )
112 {
113 const QgsPointXY vertex = snapMatch.point();
114 if ( vertex.isEmpty() )
115 continue;
116
117 if ( std::abs( point.x() - vertex.x() ) / ctx.mapUnitsPerPixel < SOFT_CONSTRAINT_TOLERANCE_PIXEL )
118 {
119 point.setX( vertex.x() );
120 res.softLockX = vertex.x();
121 }
122 }
123 }
124
125 // *****************************
126 // ---- Y constraint
127 if ( ctx.yConstraint.locked )
128 {
129 if ( !ctx.yConstraint.relative )
130 {
131 point.setY( ctx.yConstraint.value );
132 }
133 else if ( ctx.cadPoints().count() >= 2 )
134 {
135 point.setY( previousPt.y() + ctx.yConstraint.value );
136 }
137 if ( snapMatch.hasEdge() && !ctx.xConstraint.locked )
138 {
139 // intersect with snapped segment line at Y coordinate
140 const double dy = edgePt1.y() - edgePt0.y();
141 if ( dy == 0 )
142 {
143 point.setX( edgePt0.x() );
144 }
145 else
146 {
147 const double dx = edgePt1.x() - edgePt0.x();
148 point.setX( edgePt0.x() + ( dx * ( point.y() - edgePt0.y() ) ) / dy );
149 }
150 }
151 }
152 else if ( numberOfHardLock < 2 && ctx.xyVertexConstraint.locked )
153 {
154 for ( QgsPointLocator::Match snapMatch : ctx.lockedSnapVertices() )
155 {
156 const QgsPointXY vertex = snapMatch.point();
157 if ( vertex.isEmpty() )
158 continue;
159
160 if ( std::abs( point.y() - vertex.y() ) / ctx.mapUnitsPerPixel < SOFT_CONSTRAINT_TOLERANCE_PIXEL )
161 {
162 point.setY( vertex.y() );
163 res.softLockY = vertex.y();
164 }
165 }
166 }
167
168 // *****************************
169 // ---- Common Angle constraint
170 if ( numberOfHardLock < 2 && !ctx.angleConstraint.locked && ctx.cadPoints().count() >= 2 && ctx.commonAngleConstraint.locked && ctx.commonAngleConstraint.value != 0
171 // Skip common angle constraint if the snapping to features has priority
172 && ( ! snapMatch.isValid() || ! ctx.snappingToFeaturesOverridesCommonAngle )
173 )
174 {
175 const double commonAngle = ctx.commonAngleConstraint.value * M_PI / 180;
176 // see if soft common angle constraint should be performed
177 // only if not in HardLock mode
178 double softAngle = std::atan2( point.y() - previousPt.y(),
179 point.x() - previousPt.x() );
180 double deltaAngle = 0;
181 if ( ctx.commonAngleConstraint.relative && ctx.cadPoints().count() >= 3 )
182 {
183 // compute the angle relative to the last segment (0° is aligned with last segment)
184 deltaAngle = std::atan2( previousPt.y() - penultimatePt.y(),
185 previousPt.x() - penultimatePt.x() );
186 softAngle -= deltaAngle;
187 }
188 const int quo = std::round( softAngle / commonAngle );
189 if ( std::fabs( softAngle - quo * commonAngle ) * 180.0 * M_1_PI <= SOFT_CONSTRAINT_TOLERANCE_DEGREES )
190 {
191 // also check the distance in pixel to the line, otherwise it's too sticky at long ranges
192 softAngle = quo * commonAngle;
193 // http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
194 // use the direction vector (cos(a),sin(a)) from previous point. |x2-x1|=1 since sin2+cos2=1
195 const double dist = std::fabs( std::cos( softAngle + deltaAngle ) * ( previousPt.y() - point.y() )
196 - std::sin( softAngle + deltaAngle ) * ( previousPt.x() - point.x() ) );
197 if ( dist / ctx.mapUnitsPerPixel < SOFT_CONSTRAINT_TOLERANCE_PIXEL )
198 {
199 res.softLockCommonAngle = 180.0 / M_PI * softAngle;
200 }
201 }
202 }
203
204 // angle can be locked in one of the two ways:
205 // 1. "hard" lock defined by the user
206 // 2. "soft" lock from common angle (e.g. 45 degrees)
207 bool angleLocked = false, angleRelative = false;
208 double angleValueDeg = 0;
209 if ( ctx.angleConstraint.locked )
210 {
211 angleLocked = true;
212 angleRelative = ctx.angleConstraint.relative;
213 angleValueDeg = ctx.angleConstraint.value;
214 }
215 else if ( res.softLockCommonAngle != -1 )
216 {
217 angleLocked = true;
218 angleRelative = ctx.commonAngleConstraint.relative;
219 angleValueDeg = res.softLockCommonAngle;
220 }
221
222 // *****************************
223 // ---- Angle constraint
224 // input angles are in degrees
225 if ( angleLocked )
226 {
227 double angleValue = angleValueDeg * M_PI / 180;
228 if ( angleRelative && ctx.cadPoints().count() >= 3 )
229 {
230 // compute the angle relative to the last segment (0° is aligned with last segment)
231 angleValue += std::atan2( previousPt.y() - penultimatePt.y(),
232 previousPt.x() - penultimatePt.x() );
233 }
234
235 const double cosa = std::cos( angleValue );
236 const double sina = std::sin( angleValue );
237 const double v = ( point.x() - previousPt.x() ) * cosa + ( point.y() - previousPt.y() ) * sina;
238 if ( ctx.xConstraint.locked && ctx.yConstraint.locked )
239 {
240 // do nothing if both X,Y are already locked
241 }
242 else if ( ctx.xConstraint.locked || !std::isnan( res.softLockX ) )
243 {
244 if ( qgsDoubleNear( cosa, 0.0 ) )
245 {
246 res.valid = false;
247 }
248 else
249 {
250 double x = ctx.xConstraint.value;
251 if ( !ctx.xConstraint.relative )
252 {
253 x -= previousPt.x();
254 }
255 point.setY( previousPt.y() + x * sina / cosa );
256 }
257 }
258 else if ( ctx.yConstraint.locked || !std::isnan( res.softLockY ) )
259 {
260 if ( qgsDoubleNear( sina, 0.0 ) )
261 {
262 res.valid = false;
263 }
264 else
265 {
266 double y = ctx.yConstraint.value;
267 if ( !ctx.yConstraint.relative )
268 {
269 y -= previousPt.y();
270 }
271 point.setX( previousPt.x() + y * cosa / sina );
272 }
273 }
274 else
275 {
276 point.setX( previousPt.x() + cosa * v );
277 point.setY( previousPt.y() + sina * v );
278 }
279
280 if ( snapMatch.hasEdge() && !ctx.distanceConstraint.locked )
281 {
282 // magnetize to the intersection of the snapped segment and the lockedAngle
283
284 // line of previous point + locked angle
285 const double x1 = previousPt.x();
286 const double y1 = previousPt.y();
287 const double x2 = previousPt.x() + cosa;
288 const double y2 = previousPt.y() + sina;
289 // line of snapped segment
290 const double x3 = edgePt0.x();
291 const double y3 = edgePt0.y();
292 const double x4 = edgePt1.x();
293 const double y4 = edgePt1.y();
294
295 const double d = ( x1 - x2 ) * ( y3 - y4 ) - ( y1 - y2 ) * ( x3 - x4 );
296
297 // do not compute intersection if lines are almost parallel
298 // this threshold might be adapted
299 if ( std::fabs( d ) > 0.01 )
300 {
301 point.setX( ( ( x3 - x4 ) * ( x1 * y2 - y1 * x2 ) - ( x1 - x2 ) * ( x3 * y4 - y3 * x4 ) ) / d );
302 point.setY( ( ( y3 - y4 ) * ( x1 * y2 - y1 * x2 ) - ( y1 - y2 ) * ( x3 * y4 - y3 * x4 ) ) / d );
303 }
304 }
305 }
306
307 // *****************************
308 // ---- Line Extension Constraint
309
310 QgsPointXY lineExtensionPt1;
311 QgsPointXY lineExtensionPt2;
312 if ( numberOfHardLock < 2 && ctx.lineExtensionConstraint.locked && ctx.lockedSnapVertices().length() != 0 )
313 {
314 const QgsPointLocator::Match snap = ctx.lockedSnapVertices().last();
315 const QgsPointXY extensionPoint = snap.point();
316
317 if ( snap.layer() && !extensionPoint.isEmpty() )
318 {
319 auto checkLineExtension = [&]( QgsPoint vertex )
320 {
321 if ( vertex.isEmpty() )
322 {
323 return false;
324 }
325
326 const double distance = QgsGeometryUtils::distToInfiniteLine(
327 QgsPoint( point ), QgsPoint( extensionPoint ), vertex );
328
329 if ( distance / ctx.mapUnitsPerPixel < SOFT_CONSTRAINT_TOLERANCE_PIXEL )
330 {
331 if ( ctx.xConstraint.locked || !std::isnan( res.softLockX ) )
332 {
333 QgsPoint intersection;
334 const bool intersect = QgsGeometryUtils::lineIntersection(
335 QgsPoint( point ), QgsVector( 0, 1 ),
336 QgsPoint( extensionPoint ), QgsPoint( extensionPoint ) - vertex,
337 intersection
338 );
339 if ( intersect )
340 {
341 point = QgsPointXY( intersection );
342 }
343 }
344 else if ( ctx.yConstraint.locked || !std::isnan( res.softLockY ) )
345 {
346 QgsPoint intersection;
347 const bool intersect = QgsGeometryUtils::lineIntersection(
348 QgsPoint( point ), QgsVector( 1, 0 ),
349 QgsPoint( extensionPoint ), QgsPoint( extensionPoint ) - vertex,
350 intersection
351 );
352 if ( intersect )
353 {
354 point = QgsPointXY( intersection );
355 }
356 }
357 else if ( angleLocked )
358 {
359 const double angleValue = angleValueDeg * M_PI / 180;
360 const double cosa = std::cos( angleValue );
361 const double sina = std::sin( angleValue );
362
363 QgsPoint intersection;
365 QgsPoint( previousPt ), QgsVector( cosa, sina ),
366 QgsPoint( extensionPoint ), QgsPoint( extensionPoint ) - vertex,
367 intersection
368 );
369 point = QgsPointXY( intersection );
370 }
371 else
372 {
373 double angleValue = std::atan2( extensionPoint.y() - vertex.y(),
374 extensionPoint.x() - vertex.x() );
375
376 const double cosa = std::cos( angleValue );
377 const double sina = std::sin( angleValue );
378 const double v = ( point.x() - extensionPoint.x() ) * cosa + ( point.y() - extensionPoint.y() ) * sina;
379
380 point.setX( extensionPoint.x() + cosa * v );
381 point.setY( extensionPoint.y() + sina * v );
382 }
383
384 return true;
385 }
386 return false;
387 };
388
390 req.setFilterFid( snap.featureId() );
391 req.setNoAttributes();
393 QgsFeatureIterator featureIt = snap.layer()->getFeatures( req );
394
395 QgsFeature feature;
396 featureIt.nextFeature( feature );
397
398 const QgsGeometry geometry = feature.geometry();
399 const QgsAbstractGeometry *geom = geometry.constGet();
400
401 QgsVertexId vertexId;
402 if ( geometry.vertexIdFromVertexNr( snap.vertexIndex(), vertexId ) && vertexId.isValid() )
403 {
404 QgsVertexId previousVertexId;
405 QgsVertexId nextVertexId;
406 geom->adjacentVertices( vertexId, previousVertexId, nextVertexId );
407
408 bool checked = checkLineExtension( geom->vertexAt( previousVertexId ) );
409 if ( checked )
410 {
412 lineExtensionPt1 = snap.point();
413 lineExtensionPt2 = QgsPointXY( geom->vertexAt( previousVertexId ) );
414 }
415
416 checked = checkLineExtension( geom->vertexAt( nextVertexId ) );
417 if ( checked )
418 {
420 lineExtensionPt1 = snap.point();
421 lineExtensionPt2 = QgsPointXY( geom->vertexAt( nextVertexId ) );
422 }
423 }
424 }
425 }
426
427 // *****************************
428 // ---- Distance constraint
429 if ( ctx.distanceConstraint.locked && ctx.cadPoints().count() >= 2 )
430 {
431 if ( ctx.xConstraint.locked || ctx.yConstraint.locked
432 || !std::isnan( res.softLockX ) || !std::isnan( res.softLockY ) )
433 {
434 // perform both to detect errors in constraints
435 if ( ctx.xConstraint.locked || !std::isnan( res.softLockX ) )
436 {
437 const QgsPointXY verticalPt0( point.x(), point.y() );
438 const QgsPointXY verticalPt1( point.x(), point.y() + 1 );
439 const bool intersect = QgsGeometryUtils::lineCircleIntersection( previousPt, ctx.distanceConstraint.value, verticalPt0, verticalPt1, point );
440
441 if ( ctx.xConstraint.locked )
442 {
443 res.valid &= intersect;
444 }
445 else if ( !intersect )
446 {
447 res.softLockX = std::numeric_limits<double>::quiet_NaN();
448 res.softLockY = std::numeric_limits<double>::quiet_NaN(); // in the case of the 2 soft locks are activated
449 res.valid &= QgsGeometryUtils::lineCircleIntersection( previousPt, ctx.distanceConstraint.value, previousPt, point, point );
450 }
451 }
452 if ( ctx.yConstraint.locked || !std::isnan( res.softLockY ) )
453 {
454 const QgsPointXY horizontalPt0( point.x(), point.y() );
455 const QgsPointXY horizontalPt1( point.x() + 1, point.y() );
456 const bool intersect = QgsGeometryUtils::lineCircleIntersection( previousPt, ctx.distanceConstraint.value, horizontalPt0, horizontalPt1, point );
457
458 if ( ctx.yConstraint.locked )
459 {
460 res.valid &= intersect;
461 }
462 else if ( !intersect )
463 {
464 res.softLockY = std::numeric_limits<double>::quiet_NaN();
465 res.valid &= QgsGeometryUtils::lineCircleIntersection( previousPt, ctx.distanceConstraint.value, previousPt, point, point );
466 }
467 }
468 }
470 {
471 const bool intersect = QgsGeometryUtils::lineCircleIntersection( previousPt, ctx.distanceConstraint.value, lineExtensionPt1, lineExtensionPt2, point );
472 if ( !intersect )
473 {
475 res.valid &= QgsGeometryUtils::lineCircleIntersection( previousPt, ctx.distanceConstraint.value, previousPt, point, point );
476 }
477 }
478 else
479 {
480 const double dist = std::sqrt( point.sqrDist( previousPt ) );
481 if ( dist == 0 )
482 {
483 // handle case where mouse is over origin and distance constraint is enabled
484 // take arbitrary horizontal line
485 point.set( previousPt.x() + ctx.distanceConstraint.value, previousPt.y() );
486 }
487 else
488 {
489 const double vP = ctx.distanceConstraint.value / dist;
490 point.set( previousPt.x() + ( point.x() - previousPt.x() ) * vP,
491 previousPt.y() + ( point.y() - previousPt.y() ) * vP );
492 }
493
494 if ( snapMatch.hasEdge() && !ctx.angleConstraint.locked )
495 {
496 // we will magnietize to the intersection of that segment and the lockedDistance !
497 res.valid &= QgsGeometryUtils::lineCircleIntersection( previousPt, ctx.distanceConstraint.value, edgePt0, edgePt1, point );
498 }
499 }
500 }
501
502 // *****************************
503 // ---- calculate CAD values
504 QgsDebugMsgLevel( u"point: %1 %2"_s.arg( point.x() ).arg( point.y() ), 4 );
505 QgsDebugMsgLevel( u"previous point: %1 %2"_s.arg( previousPt.x() ).arg( previousPt.y() ), 4 );
506 QgsDebugMsgLevel( u"penultimate point: %1 %2"_s.arg( penultimatePt.x() ).arg( penultimatePt.y() ), 4 );
507 //QgsDebugMsgLevel( u"dx: %1 dy: %2"_s.arg( point.x() - previousPt.x() ).arg( point.y() - previousPt.y() ), 4 );
508 //QgsDebugMsgLevel( u"ddx: %1 ddy: %2"_s.arg( previousPt.x() - penultimatePt.x() ).arg( previousPt.y() - penultimatePt.y() ), 4 );
509
510 res.finalMapPoint = point;
511
512 return res;
513}
514
516{
517 QgsDebugMsgLevel( u"Constraints (locked / relative / value"_s, 1 );
518 QgsDebugMsgLevel( u"Angle: %1 %2 %3"_s.arg( angleConstraint.locked ).arg( angleConstraint.relative ).arg( angleConstraint.value ), 1 );
519 QgsDebugMsgLevel( u"Distance: %1 %2 %3"_s.arg( distanceConstraint.locked ).arg( distanceConstraint.relative ).arg( distanceConstraint.value ), 1 );
520 QgsDebugMsgLevel( u"X: %1 %2 %3"_s.arg( xConstraint.locked ).arg( xConstraint.relative ).arg( xConstraint.value ), 1 );
521 QgsDebugMsgLevel( u"Y: %1 %2 %3"_s.arg( yConstraint.locked ).arg( yConstraint.relative ).arg( yConstraint.value ), 1 );
522}
@ AfterVertex
Lock to next vertex.
Definition qgis.h:4122
@ NoVertex
Don't lock to vertex.
Definition qgis.h:4123
@ BeforeVertex
Lock to previous vertex.
Definition qgis.h:4121
Abstract base class for all geometries.
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
virtual void adjacentVertices(QgsVertexId vertex, QgsVertexId &previousVertex, QgsVertexId &nextVertex) const =0
Returns the vertices adjacent to a specified vertex within a geometry.
bool locked
Whether the constraint is active, i.e. should be considered.
Definition qgscadutils.h:54
double value
Numeric value of the constraint (coordinate/distance in map units or angle in degrees).
Definition qgscadutils.h:58
bool relative
Whether the value is relative to previous value.
Definition qgscadutils.h:56
Defines constraints for the QgsCadUtils::alignMapPoint() method.
Definition qgscadutils.h:99
QgsCadUtils::AlignMapPointConstraint xyVertexConstraint
QgsCadUtils::AlignMapPointConstraint yConstraint
Constraint for Y coordinate.
QgsCadUtils::AlignMapPointConstraint xConstraint
Constraint for X coordinate.
double mapUnitsPerPixel
Map units/pixel ratio from map canvas.
QgsPoint cadPoint(int index) const
Returns the recent CAD point at the specified index (in map coordinates).
QgsCadUtils::AlignMapPointConstraint distanceConstraint
Constraint for distance.
bool snappingToFeaturesOverridesCommonAngle
Flag to set snapping to features priority over common angle.
QgsSnappingUtils * snappingUtils
Snapping utils that will be used to snap point to map. Must not be nullptr.
QgsCadUtils::AlignMapPointConstraint commonAngleConstraint
Constraint for soft lock to a common angle.
QQueue< QgsPointLocator::Match > lockedSnapVertices() const
Returns the queue of point locator matches that contain the locked vertices.
QgsCadUtils::AlignMapPointConstraint lineExtensionConstraint
QList< QgsPoint > cadPoints() const
Returns the list of recent CAD points in map coordinates.
void dump() const
Dumps the context's properties, for debugging.
QgsCadUtils::AlignMapPointConstraint angleConstraint
Constraint for angle.
Structure returned from alignMapPoint() method.
Definition qgscadutils.h:66
Qgis::LineExtensionSide softLockLineExtension
Definition qgscadutils.h:89
QgsPointXY finalMapPoint
map point aligned according to the constraints
Definition qgscadutils.h:72
bool valid
Whether the combination of constraints is actually valid.
Definition qgscadutils.h:69
QgsPointLocator::Match snapMatch
Snapped point - only valid if actually used for something.
Definition qgscadutils.h:78
QgsPointLocator::Match edgeMatch
Snapped segment - only valid if actually used for something.
Definition qgscadutils.h:84
double softLockCommonAngle
Angle (in degrees) to which we have soft-locked ourselves (if not set it is -1).
Definition qgscadutils.h:87
static QgsCadUtils::AlignMapPointOutput alignMapPoint(const QgsPointXY &originalMapPoint, const QgsCadUtils::AlignMapPointContext &ctx)
Applies X/Y/angle/distance constraints from the given context to a map point.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setDestinationCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets the destination crs for feature's geometries.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Sets the feature ID that should be fetched.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
QgsGeometry geometry
Definition qgsfeature.h:71
static bool lineIntersection(const QgsPoint &p1, QgsVector v1, const QgsPoint &p2, QgsVector v2, QgsPoint &intersection)
Computes the intersection between two lines.
static bool lineCircleIntersection(const QgsPointXY &center, double radius, const QgsPointXY &linePoint1, const QgsPointXY &linePoint2, QgsPointXY &intersection)
Compute the intersection of a line and a circle.
static double distToInfiniteLine(const QgsPoint &point, const QgsPoint &linePoint1, const QgsPoint &linePoint2, double epsilon=1e-7)
Returns the distance between a point and an infinite line.
A geometry is the spatial representation of a feature.
bool vertexIdFromVertexNr(int number, QgsVertexId &id) const
Calculates the vertex ID from a vertex number.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
Represents a 2D point.
Definition qgspointxy.h:62
double sqrDist(double x, double y) const
Returns the squared distance between this point a specified x, y coordinate.
Definition qgspointxy.h:188
void setY(double y)
Sets the y value of the point.
Definition qgspointxy.h:131
void set(double x, double y)
Sets the x and y value of the point.
Definition qgspointxy.h:138
double y
Definition qgspointxy.h:66
double x
Definition qgspointxy.h:65
void setX(double x)
Sets the x value of the point.
Definition qgspointxy.h:121
bool isEmpty() const
Returns true if the geometry is empty.
Definition qgspointxy.h:244
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:53
QgsMapSettings mapSettings() const
QgsPointLocator::Match snapToMap(QPoint point, QgsPointLocator::MatchFilter *filter=nullptr, bool relaxed=false)
Snap to map according to the current configuration.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const final
Queries the layer for features specified in request.
Represent a 2-dimensional vector.
Definition qgsvector.h:34
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6900
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63
Interface that allows rejection of some matches in intersection queries (e.g.
virtual bool acceptMatch(const QgsPointLocator::Match &match)=0
QgsFeatureId featureId() const
The id of the feature to which the snapped geometry belongs.
QgsVectorLayer * layer() const
The vector layer where the snap occurred.
QgsPointXY point() const
for vertex / edge match coords depending on what class returns it (geom.cache: layer coords,...
bool hasEdge() const
Returns true if the Match is an edge.
void edgePoints(QgsPointXY &pt1, QgsPointXY &pt2) const
Only for a valid edge match - obtain endpoints of the edge.
int vertexIndex() const
for vertex / edge match (first vertex of the edge)
Utility class for identifying a unique vertex within a geometry.
Definition qgsvertexid.h:34
bool isValid() const
Returns true if the vertex id is valid.
Definition qgsvertexid.h:49