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