QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 
22 
24  : QgsMapCanvasItem( canvas )
25  , mLockedPen( QPen( QColor( 100, 100, 255, 255 ), .7, Qt::DashLine ) )
26  , mConstruction1Pen( QPen( QColor( 100, 255, 100, 150 ), .7, Qt::DashLine ) )
27  , mConstruction2Pen( QPen( QColor( 100, 255, 100, 255 ), .7, Qt::DashLine ) )
28  , mSnapPen( QPen( QColor( 255, 175, 100, 150 ), 7 ) )
29  , mSnapLinePen( QPen( QColor( 200, 100, 50, 150 ), .7, Qt::DashLine ) )
30  , mCursorPen( QPen( QColor( 100, 255, 100, 255 ), .7 ) )
31  , mAdvancedDigitizingDockWidget( cadDockWidget )
32 {
33 }
34 
36 {
37 }
38 
40 {
41  if ( !mAdvancedDigitizingDockWidget->cadEnabled() )
42  return;
43 
44  QgsRectangle mapRect = mMapCanvas->extent();
45  if ( rect() != mapRect )
46  setRect( mapRect );
47 
48  int nPoints = mAdvancedDigitizingDockWidget->pointsCount();
49  if ( !nPoints )
50  return;
51 
52  bool previousPointExist, penulPointExist;
53  const QgsPoint curPoint = mAdvancedDigitizingDockWidget->currentPoint();
54  const QgsPoint prevPoint = mAdvancedDigitizingDockWidget->previousPoint( &previousPointExist );
55  const QgsPoint penulPoint = mAdvancedDigitizingDockWidget->penultimatePoint( &penulPointExist );
56  const bool snappedToVertex = mAdvancedDigitizingDockWidget->snappedToVertex();
57  const QList<QgsPoint> snappedSegment = mAdvancedDigitizingDockWidget->snappedSegment();
58  const bool hasSnappedSegment = snappedSegment.count() == 2;
59 
60  const bool curPointExist = mapRect.contains( curPoint );
61 
62  const double mupp = mMapCanvas->getCoordinateTransform()->mapUnitsPerPixel();
63  if ( mupp == 0 )
64  return;
65 
66  QPointF curPointPix, prevPointPix, penulPointPix, snapSegmentPix1, snapSegmentPix2;
67 
68  if ( curPointExist )
69  {
70  curPointPix = toCanvasCoordinates( curPoint );
71  }
72  if ( previousPointExist )
73  {
74  prevPointPix = toCanvasCoordinates( prevPoint );
75  }
76  if ( penulPointExist )
77  {
78  penulPointPix = toCanvasCoordinates( penulPoint );
79  }
80  if ( hasSnappedSegment )
81  {
82  snapSegmentPix1 = toCanvasCoordinates( snappedSegment[0] );
83  snapSegmentPix2 = toCanvasCoordinates( snappedSegment[1] );
84  }
85 
86  painter->setRenderHints( QPainter::Antialiasing );
87 
88  // Draw point snap
89  if ( curPointExist && snappedToVertex )
90  {
91  painter->setPen( mSnapPen );
92  painter->drawEllipse( curPointPix, 10, 10 );
93  }
94 
95  // Draw segment snap
96  if ( hasSnappedSegment && !snappedToVertex )
97  {
98  painter->setPen( mSnapPen );
99  painter->drawLine( snapSegmentPix1.x(),
100  snapSegmentPix1.y(),
101  snapSegmentPix2.x(),
102  snapSegmentPix2.y() );
103 
104  if ( curPointExist )
105  {
106  painter->setPen( mSnapLinePen );
107  painter->drawLine( snapSegmentPix1.x(),
108  snapSegmentPix1.y(),
109  curPointPix.x(),
110  curPointPix.y() );
111  }
112  }
113 
114  // Draw segment par/per input
115  if ( mAdvancedDigitizingDockWidget->additionalConstraint() != QgsAdvancedDigitizingDockWidget::NoConstraint && hasSnappedSegment )
116  {
117  painter->setPen( mConstruction2Pen );
118  painter->drawLine( snapSegmentPix1.x(),
119  snapSegmentPix1.y(),
120  snapSegmentPix2.x(),
121  snapSegmentPix2.y() );
122  }
123 
124  // Draw angle
125  if ( nPoints > 1 )
126  {
127  double a0, a;
128  if ( mAdvancedDigitizingDockWidget->constraintAngle()->relative() && nPoints > 2 )
129  {
130  a0 = qAtan2( -( prevPoint.y() - penulPoint.y() ), prevPoint.x() - penulPoint.x() );
131  }
132  else
133  {
134  a0 = 0;
135  }
136  if ( mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() )
137  {
138  a = a0 - mAdvancedDigitizingDockWidget->constraintAngle()->value() * M_PI / 180;
139  }
140  else
141  {
142  a = qAtan2( -( curPoint.y() - prevPoint.y() ), curPoint.x() - prevPoint.x() );
143  }
144  painter->setPen( mConstruction2Pen );
145  painter->drawArc( prevPointPix.x() - 20,
146  prevPointPix.y() - 20,
147  40, 40,
148  ( int )16 * -a0 * 180 / M_PI,
149  ( int )16 * ( a0 - a ) * 180 / M_PI );
150  painter->drawLine( prevPointPix.x(),
151  prevPointPix.y(),
152  prevPointPix.x() + 60*qCos( a0 ),
153  prevPointPix.y() + 60*qSin( a0 ) );
154 
155  if ( mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() )
156  {
157  painter->setPen( mLockedPen );
158  double d = std::max( boundingRect().width(), boundingRect().height() );
159  painter->drawLine( prevPointPix.x() - d*qCos( a ),
160  prevPointPix.y() - d*qSin( a ),
161  prevPointPix.x() + d*qCos( a ),
162  prevPointPix.y() + d*qSin( a ) );
163  }
164  }
165 
166  // Draw distance
167  if ( nPoints > 1 && mAdvancedDigitizingDockWidget->constraintDistance()->isLocked() )
168  {
169  painter->setPen( mLockedPen );
170  double r = mAdvancedDigitizingDockWidget->constraintDistance()->value() / mupp;
171  painter->drawEllipse( prevPointPix, r, r );
172  }
173 
174  // Draw x
175  if ( mAdvancedDigitizingDockWidget->constraintX()->isLocked() )
176  {
177  double x = 0.0;
178  bool draw = true;
179  painter->setPen( mLockedPen );
180  if ( mAdvancedDigitizingDockWidget->constraintX()->relative() )
181  {
182  if ( nPoints > 1 )
183  {
184  x = mAdvancedDigitizingDockWidget->constraintX()->value() / mupp + prevPointPix.x();
185  }
186  else
187  {
188  draw = false;
189  }
190  }
191  else
192  {
193  x = toCanvasCoordinates( QgsPoint( mAdvancedDigitizingDockWidget->constraintX()->value(), 0 ) ).x();
194  }
195  if ( draw )
196  {
197  painter->drawLine( x,
198  0,
199  x,
200  boundingRect().height() );
201  }
202  }
203 
204  // Draw y
205  if ( mAdvancedDigitizingDockWidget->constraintY()->isLocked() )
206  {
207  double y = 0.0;
208  bool draw = true;
209  painter->setPen( mLockedPen );
210  if ( mAdvancedDigitizingDockWidget->constraintY()->relative() )
211  {
212  if ( nPoints > 1 )
213  {
214  // y is reversed!
215  y = -mAdvancedDigitizingDockWidget->constraintY()->value() / mupp + prevPointPix.y();
216  }
217  else
218  {
219  draw = false;
220  }
221  }
222  else
223  {
224  y = toCanvasCoordinates( QgsPoint( 0, mAdvancedDigitizingDockWidget->constraintY()->value() ) ).y();
225  }
226  if ( draw )
227  {
228  painter->drawLine( 0,
229  y,
230  boundingRect().width(),
231  y );
232  }
233  }
234 
235  // Draw constr
236  if ( mAdvancedDigitizingDockWidget->additionalConstraint() == QgsAdvancedDigitizingDockWidget::NoConstraint )
237  {
238  if ( curPointExist && previousPointExist )
239  {
240  painter->setPen( mConstruction2Pen );
241  painter->drawLine( prevPointPix.x(),
242  prevPointPix.y(),
243  curPointPix.x(),
244  curPointPix.y() );
245  }
246 
247  if ( previousPointExist && penulPointExist )
248  {
249  painter->setPen( mConstruction1Pen );
250  painter->drawLine( penulPointPix.x(),
251  penulPointPix.y(),
252  prevPointPix.x(),
253  prevPointPix.y() );
254  }
255  }
256 
257  if ( curPointExist )
258  {
259  painter->setPen( mCursorPen );
260  painter->drawLine( curPointPix.x() - 5,
261  curPointPix.y() - 5,
262  curPointPix.x() + 5,
263  curPointPix.y() + 5 );
264  painter->drawLine( curPointPix.x() - 5,
265  curPointPix.y() + 5,
266  curPointPix.x() + 5,
267  curPointPix.y() - 5 );
268  }
269 
270 }
int pointsCount() const
The number of points in the CAD point helper list.
bool cadEnabled() const
determines if CAD tools are enabled or if map tools behaves "nomally"
const QList< QgsPoint > & snappedSegment() const
Snapped to a segment.
bool contains(const QgsRectangle &rect) const
return true when rectangle contains other rectangle
qreal x() const
qreal y() const
A rectangle specified with double values.
Definition: qgsrectangle.h:35
const CadConstraint * constraintY() const
Constraint on the Y coordinate.
QgsRectangle rect() const
returns canvas item rectangle in map units
const CadConstraint * constraintAngle() const
Constraint on the angle.
An abstract class for items that can be placed on the map canvas.
void paint(QPainter *painter) override
function to be implemented by derived classes
void drawLine(const QLineF &line)
QgsPoint penultimatePoint(bool *exists=nullptr) const
The penultimate point.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:109
double y() const
Get the y value of the point.
Definition: qgspoint.h:193
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
QPointF toCanvasCoordinates(const QgsPoint &point) const
transformation from map coordinates to screen coordinates
int count(const T &value) const
qreal x() const
qreal y() const
virtual QRectF boundingRect() const override
default implementation for canvas items
double value() const
The value of the constraint.
void drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
void setPen(const QColor &color)
void drawEllipse(const QRectF &rectangle)
bool isLocked() const
Is any kind of lock mode enabled.
QgsRectangle extent() const
Returns the current zoom exent of the map canvas.
void setRect(const QgsRectangle &r, bool resetRotation=true)
sets canvas item rectangle in map units
#define M_PI
const CadConstraint * constraintX() const
Constraint on the X coordinate.
AdditionalConstraint additionalConstraint() const
Additional constraints are used to place perpendicular/parallel segments to snapped segments on the c...
double mapUnitsPerPixel() const
Return current map units per pixel.
A class to represent a point.
Definition: qgspoint.h:117
void setRenderHints(QFlags< QPainter::RenderHint > hints, bool on)
const CadConstraint * constraintDistance() const
Constraint on the distance.
bool relative() const
Is the constraint in relative mode.
QgsAdvancedDigitizingCanvasItem(QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget)
QgsMapCanvas * mMapCanvas
pointer to map canvas
bool snappedToVertex() const
Is it snapped to a vertex.
const QgsMapToPixel * getCoordinateTransform()
Get the current coordinate transform.
QgsPoint currentPoint(bool *exists=nullptr) const
The last point.
The QgsAdvancedDigitizingDockWidget class is a dockable widget used to handle the CAD tools on top of...
QgsPoint previousPoint(bool *exists=nullptr) const
The previous point.
double x() const
Get the x value of the point.
Definition: qgspoint.h:185