QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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->setRenderHint( 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, snapSegmentPix2 );
97 
98  if ( curPointExist )
99  {
100  painter->setPen( mSnapLinePen );
101  painter->drawLine( snapSegmentPix1, curPointPix );
102  }
103  }
104 
105  // Draw segment par/per input
106  if ( mAdvancedDigitizingDockWidget->additionalConstraint() != QgsAdvancedDigitizingDockWidget::NoConstraint && hasSnappedSegment )
107  {
108  painter->setPen( mConstruction2Pen );
109  painter->drawLine( snapSegmentPix1, snapSegmentPix2 );
110  }
111 
112  // Draw angle
113  if ( nPoints > 1 )
114  {
115  double a0, a;
116  if ( mAdvancedDigitizingDockWidget->constraintAngle()->relative() && nPoints > 2 )
117  {
118  a0 = std::atan2( -( prevPoint.y() - penulPoint.y() ), prevPoint.x() - penulPoint.x() );
119  }
120  else
121  {
122  a0 = 0;
123  }
124  if ( mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() )
125  {
126  a = a0 - mAdvancedDigitizingDockWidget->constraintAngle()->value() * M_PI / 180;
127  }
128  else
129  {
130  a = std::atan2( -( curPoint.y() - prevPoint.y() ), curPoint.x() - prevPoint.x() );
131  }
132  painter->setPen( mConstruction2Pen );
133  painter->drawArc( QRectF( prevPointPix.x() - 20,
134  prevPointPix.y() - 20,
135  40, 40 ),
136  static_cast<int>( 16 * -a0 * 180 / M_PI ),
137  static_cast<int>( 16 * ( a0 - a ) * 180 / M_PI ) );
138  painter->drawLine( prevPointPix,
139  prevPointPix + 60 * QPointF( std::cos( a0 ), std::sin( a0 ) ) );
140 
141 
142  if ( mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() )
143  {
144  painter->setPen( mLockedPen );
145  double d = std::max( boundingRect().width(), boundingRect().height() );
146  painter->drawLine( prevPointPix - d * QPointF( std::cos( a ), std::sin( a ) ),
147  prevPointPix + d * QPointF( std::cos( a ), std::sin( a ) ) );
148  }
149  }
150 
151  // Draw distance
152  if ( nPoints > 1 && mAdvancedDigitizingDockWidget->constraintDistance()->isLocked() )
153  {
154  painter->setPen( mLockedPen );
155  double r = mAdvancedDigitizingDockWidget->constraintDistance()->value() / mupp;
156  painter->drawEllipse( prevPointPix, r, r );
157  }
158 
159  // Draw x
160  if ( mAdvancedDigitizingDockWidget->constraintX()->isLocked() )
161  {
162  double x = 0.0;
163  bool draw = true;
164  painter->setPen( mLockedPen );
165  if ( mAdvancedDigitizingDockWidget->constraintX()->relative() )
166  {
167  if ( nPoints > 1 )
168  {
169  x = mAdvancedDigitizingDockWidget->constraintX()->value() / mupp + prevPointPix.x();
170  }
171  else
172  {
173  draw = false;
174  }
175  }
176  else
177  {
178  x = toCanvasCoordinates( QgsPointXY( mAdvancedDigitizingDockWidget->constraintX()->value(), 0 ) ).x();
179  }
180  if ( draw )
181  {
182  painter->drawLine( QPointF( x, 0 ),
183  QPointF( x, boundingRect().height() ) );
184  }
185  }
186 
187  // Draw y
188  if ( mAdvancedDigitizingDockWidget->constraintY()->isLocked() )
189  {
190  double y = 0.0;
191  bool draw = true;
192  painter->setPen( mLockedPen );
193  if ( mAdvancedDigitizingDockWidget->constraintY()->relative() )
194  {
195  if ( nPoints > 1 )
196  {
197  // y is reversed!
198  y = -mAdvancedDigitizingDockWidget->constraintY()->value() / mupp + prevPointPix.y();
199  }
200  else
201  {
202  draw = false;
203  }
204  }
205  else
206  {
207  y = toCanvasCoordinates( QgsPointXY( 0, mAdvancedDigitizingDockWidget->constraintY()->value() ) ).y();
208  }
209  if ( draw )
210  {
211  painter->drawLine( QPointF( 0, y ),
212  QPointF( boundingRect().width(), y ) );
213  }
214  }
215 
216  // Draw constr
217  if ( mAdvancedDigitizingDockWidget->additionalConstraint() == QgsAdvancedDigitizingDockWidget::NoConstraint )
218  {
219  if ( curPointExist && previousPointExist )
220  {
221  painter->setPen( mConstruction2Pen );
222  painter->drawLine( prevPointPix, curPointPix );
223  }
224 
225  if ( previousPointExist && penulPointExist )
226  {
227  painter->setPen( mConstruction1Pen );
228  painter->drawLine( penulPointPix, prevPointPix );
229  }
230  }
231 
232  if ( curPointExist )
233  {
234  painter->setPen( mCursorPen );
235  painter->drawLine( curPointPix + QPointF( -5, -5 ),
236  curPointPix + QPointF( +5, +5 ) );
237  painter->drawLine( curPointPix + QPointF( -5, +5 ),
238  curPointPix + QPointF( +5, -5 ) );
239  }
240 }
bool isLocked() const
Is any kind of lock mode enabled.
A rectangle specified with double values.
Definition: qgsrectangle.h:40
QgsPointXY currentPoint(bool *exists=nullptr) const
The last point.
bool relative() const
Is the constraint in relative mode.
double y
Definition: qgspointxy.h:48
A class to represent a 2D point.
Definition: qgspointxy.h:43
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
Definition: qgsrectangle.h:341
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
QgsRectangle rect() const
returns canvas item rectangle in map units
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:74
int pointsCount() const
The number of points in the CAD point helper list.
const CadConstraint * constraintDistance() const
Returns the CadConstraint on the distance.
QRectF boundingRect() const override
bool snappedToVertex() const
Is it snapped to a vertex.
const CadConstraint * constraintY() const
Returns the CadConstraint on the Y coordinate.
void setRect(const QgsRectangle &r, bool resetRotation=true)
sets canvas item rectangle in map units
QgsPointXY penultimatePoint(bool *exists=nullptr) const
The penultimate point.
double mapUnitsPerPixel() const
Returns current map units per pixel.
AdditionalConstraint additionalConstraint() const
Returns the additional constraints which are used to place perpendicular/parallel segments to snapped...
double x
Definition: qgspointxy.h:47
const CadConstraint * constraintX() const
Returns the CadConstraint on the X coordinate.
QgsPointXY previousPoint(bool *exists=nullptr) const
The previous point.
QgsAdvancedDigitizingCanvasItem(QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget)
QList< QgsPointXY > snappedSegment() const
Snapped to a segment.
QgsMapCanvas * mMapCanvas
pointer to map canvas
const QgsMapToPixel * getCoordinateTransform()
Gets the current coordinate transform.
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
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...
const CadConstraint * constraintAngle() const
Returns the CadConstraint 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"