QGIS API Documentation  2.12.0-Lyon
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
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
An abstract class for items that can be placed on the map canvas.
QgsPoint penultimatePoint(bool *exists=0) const
The penultimate point.
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:107
double x() const
Get the x value of the point.
Definition: qgspoint.h:126
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
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
QgsPoint previousPoint(bool *exists=0) const
The previous point.
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:63
void setRenderHints(QFlags< QPainter::RenderHint > hints, bool on)
QgsPoint currentPoint(bool *exists=0) const
The last point.
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:134
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"