QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsadvanceddigitizingcanvasitem.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsadvanceddigitizingcanvasitem.cpp - map canvas item for CAD tools
3  ----------------------
4  begin : October 2014
5  copyright : (C) Denis Rouzaud
6  email : [email protected]
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 #include <QPainter>
17 
20 #include "qgsmapcanvas.h"
21 #include "qgscadutils.h"
22 
23 
25  : QgsMapCanvasItem( canvas )
26  , mLockedPen( QPen( QColor( 0, 127, 0, 255 ), 1, Qt::DashLine ) )
27  , mConstruction1Pen( QPen( QColor( 127, 127, 127, 150 ), 1, Qt::DashLine ) )
28  , mConstruction2Pen( QPen( QColor( 127, 127, 127, 255 ), 1, Qt::DashLine ) )
29  , mSnapPen( QPen( QColor( 127, 0, 0, 150 ), 1 ) )
30  , mSnapLinePen( QPen( QColor( 127, 0, 0, 150 ), 1, Qt::DashLine ) )
31  , mCursorPen( QPen( QColor( 127, 127, 127, 255 ), 1 ) )
32  , mAdvancedDigitizingDockWidget( cadDockWidget )
33 {
34 }
35 
36 void QgsAdvancedDigitizingCanvasItem::paint( QPainter *painter )
37 {
38  if ( !mAdvancedDigitizingDockWidget->cadEnabled() )
39  return;
40 
41  // Use visible polygon rather than extent to properly handle rotated maps
42  QPolygonF mapPoly = mMapCanvas->mapSettings().visiblePolygon();
43  const double canvasWidth = QLineF( mapPoly[0], mapPoly[1] ).length();
44  const double canvasHeight = QLineF( mapPoly[0], mapPoly[3] ).length();
45 
46  const int nPoints = mAdvancedDigitizingDockWidget->pointsCount();
47  if ( !nPoints )
48  return;
49 
50  bool previousPointExist, penulPointExist;
51  const QgsPointXY curPoint = mAdvancedDigitizingDockWidget->currentPointV2();
52  const QgsPointXY prevPoint = mAdvancedDigitizingDockWidget->previousPointV2( &previousPointExist );
53  const QgsPointXY penulPoint = mAdvancedDigitizingDockWidget->penultimatePointV2( &penulPointExist );
54  const bool snappedToVertex = mAdvancedDigitizingDockWidget->snappedToVertex();
55  const QList<QgsPointXY> snappedSegment = mAdvancedDigitizingDockWidget->snappedSegment();
56  const bool hasSnappedSegment = snappedSegment.count() == 2;
57 
58  const bool curPointExist = mapPoly.containsPoint( curPoint.toQPointF(), Qt::OddEvenFill );
59 
60  const double mupp = mMapCanvas->getCoordinateTransform()->mapUnitsPerPixel();
61  if ( mupp == 0 )
62  return;
63 
64  const double canvasRotationRad = mMapCanvas->rotation() * M_PI / 180;
65  const double canvasDiagonalDimension = ( canvasWidth + canvasHeight ) / mupp ;
66 
67  QPointF curPointPix, prevPointPix, penulPointPix, snapSegmentPix1, snapSegmentPix2;
68 
69  if ( curPointExist )
70  {
71  curPointPix = toCanvasCoordinates( curPoint );
72  }
73  if ( previousPointExist )
74  {
75  prevPointPix = toCanvasCoordinates( prevPoint );
76  }
77  if ( penulPointExist )
78  {
79  penulPointPix = toCanvasCoordinates( penulPoint );
80  }
81  if ( hasSnappedSegment )
82  {
83  snapSegmentPix1 = toCanvasCoordinates( snappedSegment[0] );
84  snapSegmentPix2 = toCanvasCoordinates( snappedSegment[1] );
85  }
86 
87  painter->setRenderHint( QPainter::Antialiasing );
88  painter->setCompositionMode( QPainter::CompositionMode_Difference );
89 
90  // Draw point snap
91  if ( curPointExist && snappedToVertex )
92  {
93  painter->setPen( mSnapPen );
94  painter->drawEllipse( curPointPix, 10, 10 );
95  }
96 
97  // Draw segment snap
98  if ( hasSnappedSegment && !snappedToVertex )
99  {
100  painter->setPen( mSnapPen );
101  painter->drawLine( snapSegmentPix1, snapSegmentPix2 );
102 
103  if ( curPointExist )
104  {
105  painter->setPen( mSnapLinePen );
106  painter->drawLine( snapSegmentPix1, curPointPix );
107  }
108  }
109 
110  // Draw segment par/per input
111  if ( mAdvancedDigitizingDockWidget->betweenLineConstraint() != Qgis::BetweenLineConstraint::NoConstraint && hasSnappedSegment )
112  {
113  painter->setPen( mConstruction2Pen );
114  painter->drawLine( snapSegmentPix1, snapSegmentPix2 );
115  }
116 
117  // Draw angle
118  if ( nPoints > 1 )
119  {
120  double a0, a;
121  if ( mAdvancedDigitizingDockWidget->constraintAngle()->relative() && nPoints > 2 )
122  {
123  a0 = std::atan2( -( prevPoint.y() - penulPoint.y() ), prevPoint.x() - penulPoint.x() );
124  }
125  else
126  {
127  a0 = 0;
128  }
129  if ( mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() )
130  {
131  a = a0 - mAdvancedDigitizingDockWidget->constraintAngle()->value() * M_PI / 180;
132  }
133  else
134  {
135  a = std::atan2( -( curPoint.y() - prevPoint.y() ), curPoint.x() - prevPoint.x() );
136  }
137 
138  a0 += canvasRotationRad;
139  a += canvasRotationRad;
140 
141  painter->setPen( mConstruction2Pen );
142  painter->drawArc( QRectF( prevPointPix.x() - 20,
143  prevPointPix.y() - 20,
144  40, 40 ),
145  static_cast<int>( 16 * -a0 * 180 / M_PI ),
146  static_cast<int>( 16 * ( a0 - a ) * 180 / M_PI ) );
147  painter->drawLine( prevPointPix,
148  prevPointPix + 60 * QPointF( std::cos( a0 ), std::sin( a0 ) ) );
149 
150 
151  if ( mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() )
152  {
153  painter->setPen( mLockedPen );
154  const double canvasPadding = QLineF( prevPointPix, curPointPix ).length();
155  painter->drawLine( prevPointPix + ( canvasPadding - canvasDiagonalDimension ) * QPointF( std::cos( a ), std::sin( a ) ),
156  prevPointPix + ( canvasPadding + canvasDiagonalDimension ) * QPointF( std::cos( a ), std::sin( a ) ) );
157  }
158  }
159 
160  // Draw distance
161  if ( nPoints > 1 && mAdvancedDigitizingDockWidget->constraintDistance()->isLocked() )
162  {
163  painter->setPen( mLockedPen );
164  const double r = mAdvancedDigitizingDockWidget->constraintDistance()->value() / mupp;
165  painter->drawEllipse( prevPointPix, r, r );
166  }
167 
168  // Draw x
169  if ( mAdvancedDigitizingDockWidget->constraintX()->isLocked() )
170  {
171  double x = 0.0;
172  bool draw = true;
173  painter->setPen( mLockedPen );
174  if ( mAdvancedDigitizingDockWidget->constraintX()->relative() )
175  {
176  if ( nPoints > 1 )
177  {
178  x = mAdvancedDigitizingDockWidget->constraintX()->value() + prevPoint.x();
179  }
180  else
181  {
182  draw = false;
183  }
184  }
185  else
186  {
187  x = mAdvancedDigitizingDockWidget->constraintX()->value();
188  }
189  if ( draw )
190  {
191  painter->drawLine( toCanvasCoordinates( QgsPointXY( x, mapPoly[0].y() ) ) - canvasDiagonalDimension * QPointF( std::sin( -canvasRotationRad ), std::cos( -canvasRotationRad ) ),
192  toCanvasCoordinates( QgsPointXY( x, mapPoly[0].y() ) ) + canvasDiagonalDimension * QPointF( std::sin( -canvasRotationRad ), std::cos( -canvasRotationRad ) ) );
193  }
194  }
195 
196  // Draw y
197  if ( mAdvancedDigitizingDockWidget->constraintY()->isLocked() )
198  {
199  double y = 0.0;
200  bool draw = true;
201  painter->setPen( mLockedPen );
202  if ( mAdvancedDigitizingDockWidget->constraintY()->relative() )
203  {
204  if ( nPoints > 1 )
205  {
206  y = mAdvancedDigitizingDockWidget->constraintY()->value() + prevPoint.y();
207  }
208  else
209  {
210  draw = false;
211  }
212  }
213  else
214  {
215  y = mAdvancedDigitizingDockWidget->constraintY()->value();
216  }
217  if ( draw )
218  {
219  painter->drawLine( toCanvasCoordinates( QgsPointXY( mapPoly[0].x(), y ) ) - canvasDiagonalDimension * QPointF( std::cos( -canvasRotationRad ), -std::sin( -canvasRotationRad ) ),
220  toCanvasCoordinates( QgsPointXY( mapPoly[0].x(), y ) ) + canvasDiagonalDimension * QPointF( std::cos( -canvasRotationRad ), -std::sin( -canvasRotationRad ) ) );
221 
222  }
223  }
224 
225  // Draw constr
226  if ( mAdvancedDigitizingDockWidget->betweenLineConstraint() == Qgis::BetweenLineConstraint::NoConstraint )
227  {
228  if ( curPointExist && previousPointExist )
229  {
230  painter->setPen( mConstruction2Pen );
231  painter->drawLine( prevPointPix, curPointPix );
232  }
233 
234  if ( previousPointExist && penulPointExist )
235  {
236  painter->setPen( mConstruction1Pen );
237  painter->drawLine( penulPointPix, prevPointPix );
238  }
239  }
240 
241  if ( curPointExist )
242  {
243  painter->setPen( mCursorPen );
244  painter->drawLine( curPointPix + QPointF( -5, -5 ),
245  curPointPix + QPointF( +5, +5 ) );
246  painter->drawLine( curPointPix + QPointF( -5, +5 ),
247  curPointPix + QPointF( +5, -5 ) );
248  }
249 
250  auto lineExtensionSide = mAdvancedDigitizingDockWidget->lineExtensionSide();
251  if ( mAdvancedDigitizingDockWidget->constraintLineExtension()->isLocked() &&
252  lineExtensionSide != Qgis::LineExtensionSide::NoVertex &&
253  !mAdvancedDigitizingDockWidget->lockedSnapVertices().isEmpty() )
254  {
255  painter->setPen( mLockedPen );
256 
257  const QgsPointLocator::Match snap = mAdvancedDigitizingDockWidget->lockedSnapVertices().last();
258  const QPointF snappedPoint = toCanvasCoordinates( snap.point() );
259 
260  const QgsFeature feature = snap.layer()->getFeature( snap.featureId() );
261  const QgsGeometry geom = feature.geometry();
262 
263  QgsPoint vertex;
264  if ( lineExtensionSide == Qgis::LineExtensionSide::BeforeVertex )
265  {
266  vertex = geom.vertexAt( snap.vertexIndex() - 1 );
267  }
268  else
269  {
270  vertex = geom.vertexAt( snap.vertexIndex() + 1 );
271  }
272 
273  if ( !vertex.isEmpty() )
274  {
275  const QPointF point = toCanvasCoordinates( vertex );
276  const double angle = std::atan2( snappedPoint.y() - point.y(), snappedPoint.x() - point.x() );
277 
278  const double canvasPadding = QLineF( snappedPoint, curPointPix ).length();
279  painter->drawLine( snappedPoint + ( canvasPadding - canvasDiagonalDimension ) * QPointF( std::cos( angle ), std::sin( angle ) ),
280  snappedPoint + ( canvasPadding + canvasDiagonalDimension ) * QPointF( std::cos( angle ), std::sin( angle ) ) );
281  }
282 
283  }
284 
285  if ( mAdvancedDigitizingDockWidget->constraintXyVertex()->isLocked() )
286  {
287  painter->setPen( mLockedPen );
288 
289  double coordinateExtension = mAdvancedDigitizingDockWidget->softLockX();
290  if ( coordinateExtension != std::numeric_limits<double>::quiet_NaN() )
291  {
292  const QgsPointXY point( coordinateExtension, mapPoly[0].y() );
293  const QPointF rotation( std::sin( -canvasRotationRad ), std::cos( -canvasRotationRad ) );
294  painter->drawLine( toCanvasCoordinates( point ) - canvasDiagonalDimension * rotation,
295  toCanvasCoordinates( point ) + canvasDiagonalDimension * rotation );
296  }
297 
298  coordinateExtension = mAdvancedDigitizingDockWidget->softLockY();
299  if ( coordinateExtension != std::numeric_limits<double>::quiet_NaN() )
300  {
301  const QgsPointXY point( mapPoly[0].x(), coordinateExtension );
302  const QPointF rotation( std::cos( -canvasRotationRad ), -std::sin( -canvasRotationRad ) );
303  painter->drawLine( toCanvasCoordinates( point ) - canvasDiagonalDimension * rotation,
304  toCanvasCoordinates( point ) + canvasDiagonalDimension * rotation );
305  }
306  }
307 
308  painter->setPen( mCursorPen );
309 
310  const QList< QgsPointLocator::Match > lockedSnapVertices = mAdvancedDigitizingDockWidget->lockedSnapVertices();
311  for ( QgsPointLocator::Match snapMatch : lockedSnapVertices )
312  {
313  const QgsPointXY point = snapMatch.point();
314  const QPointF canvasPoint = toCanvasCoordinates( point );
315 
316  painter->drawLine( canvasPoint + QPointF( 5, 5 ),
317  canvasPoint - QPointF( 5, 5 ) );
318  painter->drawLine( canvasPoint + QPointF( -5, 5 ),
319  canvasPoint - QPointF( -5, 5 ) );
320  }
321 
322  if ( !lockedSnapVertices.isEmpty() )
323  {
324  const QgsPointXY point = lockedSnapVertices.last().point();
325  const QPointF canvasPoint = toCanvasCoordinates( point );
326 
327  painter->drawLine( canvasPoint + QPointF( 0, 5 ),
328  canvasPoint - QPointF( 0, 5 ) );
329  painter->drawLine( canvasPoint + QPointF( 5, 0 ),
330  canvasPoint - QPointF( 5, 0 ) );
331  }
332 }
333 
335 {
336  // Use visible polygon rather than extent to properly handle rotated maps
337  QPolygonF mapPoly = mMapCanvas->mapSettings().visiblePolygon();
338  const double canvasWidth = QLineF( mapPoly[0], mapPoly[1] ).length();
339  const double canvasHeight = QLineF( mapPoly[0], mapPoly[3] ).length();
340  const QgsRectangle mapRect = QgsRectangle( mapPoly[0],
341  QgsPointXY(
342  mapPoly[0].x() + canvasWidth,
343  mapPoly[0].y() - canvasHeight
344  )
345  );
346  if ( rect() != mapRect )
347  setRect( mapRect );
348 }
QgsAdvancedDigitizingDockWidget::constraintX
const CadConstraint * constraintX() const
Returns the CadConstraint on the X coordinate.
Definition: qgsadvanceddigitizingdockwidget.h:294
QgsAdvancedDigitizingDockWidget::softLockY
double softLockY() const
Returns the Y value of the Y soft lock. The value is NaN is the constraint isn't magnetized to a line...
Definition: qgsadvanceddigitizingdockwidget.h:325
QgsAdvancedDigitizingDockWidget::penultimatePointV2
QgsPoint penultimatePointV2(bool *exists=nullptr) const
The penultimate point.
Definition: qgsadvanceddigitizingdockwidget.cpp:1851
QgsAdvancedDigitizingCanvasItem::QgsAdvancedDigitizingCanvasItem
QgsAdvancedDigitizingCanvasItem(QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget)
Definition: qgsadvanceddigitizingcanvasitem.cpp:24
QgsAdvancedDigitizingDockWidget::currentPointV2
QgsPoint currentPointV2(bool *exists=nullptr) const
The last point.
Definition: qgsadvanceddigitizingdockwidget.cpp:1818
QgsPointXY::y
double y
Definition: qgspointxy.h:63
QgsAdvancedDigitizingDockWidget::constraintAngle
const CadConstraint * constraintAngle() const
Returns the CadConstraint on the angle.
Definition: qgsadvanceddigitizingdockwidget.h:290
QgsAdvancedDigitizingDockWidget::softLockX
double softLockX() const
Returns the X value of the X soft lock. The value is NaN is the constraint isn't magnetized to a line...
Definition: qgsadvanceddigitizingdockwidget.h:322
QgsMapToPixel::mapUnitsPerPixel
double mapUnitsPerPixel() const
Returns the current map units per pixel.
Definition: qgsmaptopixel.h:229
qgsmapcanvas.h
QgsAdvancedDigitizingDockWidget::pointsCount
int pointsCount() const
The number of points in the CAD point helper list.
Definition: qgsadvanceddigitizingdockwidget.h:430
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:48
QgsMapCanvasItem::mMapCanvas
QgsMapCanvas * mMapCanvas
pointer to map canvas
Definition: qgsmapcanvasitem.h:82
QgsAdvancedDigitizingDockWidget::constraintLineExtension
const CadConstraint * constraintLineExtension() const
Returns the CadConstraint.
Definition: qgsadvanceddigitizingdockwidget.h:313
QgsAdvancedDigitizingDockWidget::snappedToVertex
bool snappedToVertex() const
Is it snapped to a vertex.
Definition: qgsadvanceddigitizingdockwidget.h:435
QgsMapCanvas::mapSettings
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
Definition: qgsmapcanvas.cpp:437
Qgis::LineExtensionSide::BeforeVertex
@ BeforeVertex
Lock to previous vertex.
QgsAdvancedDigitizingDockWidget::CadConstraint::relative
bool relative() const
Is the constraint in relative mode.
Definition: qgsadvanceddigitizingdockwidget.h:142
QgsAdvancedDigitizingDockWidget::constraintXyVertex
const CadConstraint * constraintXyVertex() const
Returns the CadConstraint.
Definition: qgsadvanceddigitizingdockwidget.h:319
QgsMapCanvas
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:89
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
QgsAdvancedDigitizingDockWidget::lockedSnapVertices
QList< QgsPointLocator::Match > lockedSnapVertices() const
Returns the snap matches whose vertices have been locked.
Definition: qgsadvanceddigitizingdockwidget.h:337
QgsPointXY::toQPointF
QPointF toQPointF() const
Converts a point to a QPointF.
Definition: qgspointxy.h:169
QgsAdvancedDigitizingCanvasItem::paint
void paint(QPainter *painter) override
function to be implemented by derived classes
Definition: qgsadvanceddigitizingcanvasitem.cpp:36
QgsAdvancedDigitizingCanvasItem::updatePosition
void updatePosition() override
called on changed extent or resize event to update position of the item
Definition: qgsadvanceddigitizingcanvasitem.cpp:334
QgsPointLocator::Match::point
QgsPointXY point() const
for vertex / edge match coords depending on what class returns it (geom.cache: layer coords,...
Definition: qgspointlocator.h:238
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsAdvancedDigitizingDockWidget::CadConstraint::isLocked
bool isLocked() const
Is any kind of lock mode enabled.
Definition: qgsadvanceddigitizingdockwidget.h:129
QgsMapCanvasItem::setRect
void setRect(const QgsRectangle &r, bool resetRotation=true)
sets canvas item rectangle in map units
Definition: qgsmapcanvasitem.cpp:74
Qgis::BetweenLineConstraint::NoConstraint
@ NoConstraint
No additional constraint.
QgsPointLocator::Match::vertexIndex
int vertexIndex() const
for vertex / edge match (first vertex of the edge)
Definition: qgspointlocator.h:241
QgsMapCanvas::rotation
double rotation() const
Gets the current map canvas rotation in clockwise degrees.
Definition: qgsmapcanvas.cpp:1472
QgsAdvancedDigitizingDockWidget::constraintDistance
const CadConstraint * constraintDistance() const
Returns the CadConstraint on the distance.
Definition: qgsadvanceddigitizingdockwidget.h:292
QgsMapCanvasItem
An abstract class for items that can be placed on the map canvas.
Definition: qgsmapcanvasitem.h:33
QgsAdvancedDigitizingDockWidget::snappedSegment
QList< QgsPointXY > snappedSegment() const
Snapped to a segment.
Definition: qgsadvanceddigitizingdockwidget.h:440
QgsMapCanvasItem::toCanvasCoordinates
QPointF toCanvasCoordinates(const QgsPointXY &point) const
transformation from map coordinates to screen coordinates
Definition: qgsmapcanvasitem.cpp:61
QgsMapSettings::visiblePolygon
QPolygonF visiblePolygon() const
Returns the visible area as a polygon (may be rotated)
Definition: qgsmapsettings.cpp:416
QgsAdvancedDigitizingDockWidget::constraintY
const CadConstraint * constraintY() const
Returns the CadConstraint on the Y coordinate.
Definition: qgsadvanceddigitizingdockwidget.h:296
qgsadvanceddigitizingcanvasitem.h
QgsPointLocator::Match::layer
QgsVectorLayer * layer() const
The vector layer where the snap occurred.
Definition: qgspointlocator.h:247
QgsAdvancedDigitizingDockWidget::betweenLineConstraint
Qgis::BetweenLineConstraint betweenLineConstraint() const
Returns the between line constraints which are used to place perpendicular/parallel segments to snapp...
Definition: qgsadvanceddigitizingdockwidget.h:288
QgsMapCanvas::getCoordinateTransform
const QgsMapToPixel * getCoordinateTransform()
Gets the current coordinate transform.
Definition: qgsmapcanvas.cpp:379
QgsAdvancedDigitizingDockWidget
The QgsAdvancedDigitizingDockWidget class is a dockable widget used to handle the CAD tools on top of...
Definition: qgsadvanceddigitizingdockwidget.h:50
QgsAdvancedDigitizingDockWidget::lineExtensionSide
Qgis::LineExtensionSide lineExtensionSide() const
Returns on which side of the constraint line extension point, the line was created.
Definition: qgsadvanceddigitizingdockwidget.h:316
QgsGeometry::vertexAt
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
Definition: qgsgeometry.cpp:683
QgsPointLocator::Match
Definition: qgspointlocator.h:187
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:58
QgsPointLocator::Match::featureId
QgsFeatureId featureId() const
The id of the feature to which the snapped geometry belongs.
Definition: qgspointlocator.h:252
qgsadvanceddigitizingdockwidget.h
QgsMapCanvasItem::rect
QgsRectangle rect() const
returns canvas item rectangle in map units
Definition: qgsmapcanvasitem.cpp:68
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
qgscadutils.h
QgsPointXY::x
double x
Definition: qgspointxy.h:62
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsPoint::isEmpty
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
Definition: qgspoint.cpp:767
QgsVectorLayer::getFeature
QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.
Definition: qgsvectorlayer.h:1187
QgsAdvancedDigitizingDockWidget::previousPointV2
QgsPoint previousPointV2(bool *exists=nullptr) const
The previous point.
Definition: qgsadvanceddigitizingdockwidget.cpp:1841
QgsAdvancedDigitizingDockWidget::CadConstraint::value
double value() const
The value of the constraint.
Definition: qgsadvanceddigitizingdockwidget.h:147
MathUtils::angle
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
QgsAdvancedDigitizingDockWidget::cadEnabled
bool cadEnabled() const
determines if CAD tools are enabled or if map tools behaves "nomally"
Definition: qgsadvanceddigitizingdockwidget.h:261
Qgis::LineExtensionSide::NoVertex
@ NoVertex
Don't lock to vertex.