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