37 if ( !mAdvancedDigitizingDockWidget->cadEnabled() )
40 painter->setRenderHint( QPainter::Antialiasing );
41 painter->setCompositionMode( QPainter::CompositionMode_Difference );
44 if ( mAdvancedDigitizingDockWidget->showConstructionGuides() )
46 if (
QgsVectorLayer *constructionGuidesLayer = mAdvancedDigitizingDockWidget->constructionGuidesLayer() )
50 painter->setPen( mConstructionGuidesPen );
56 painter->drawPolyline( polygon );
65 tool->paint( painter );
70 QPolygonF mapPoly =
mMapCanvas->mapSettings().visiblePolygon();
71 const double canvasWidth = QLineF( mapPoly[0], mapPoly[1] ).length();
72 const double canvasHeight = QLineF( mapPoly[0], mapPoly[3] ).length();
74 const int nPoints = mAdvancedDigitizingDockWidget->pointsCount();
78 bool previousPointExist, penulPointExist;
79 const QgsPointXY curPoint = mAdvancedDigitizingDockWidget->currentPointV2();
80 const QgsPointXY prevPoint = mAdvancedDigitizingDockWidget->previousPointV2( &previousPointExist );
81 const QgsPointXY penulPoint = mAdvancedDigitizingDockWidget->penultimatePointV2( &penulPointExist );
82 const bool snappedToVertex = mAdvancedDigitizingDockWidget->snappedToVertex();
83 const QList<QgsPointXY> snappedSegment = mAdvancedDigitizingDockWidget->snappedSegment();
84 const bool hasSnappedSegment = snappedSegment.count() == 2;
86 const bool curPointExist = mapPoly.containsPoint( curPoint.
toQPointF(), Qt::OddEvenFill );
88 const double mupp =
mMapCanvas->getCoordinateTransform()->mapUnitsPerPixel();
92 const double canvasRotationRad =
mMapCanvas->rotation() * M_PI / 180;
93 const double canvasDiagonalDimension = ( canvasWidth + canvasHeight ) / mupp;
95 QPointF curPointPix, prevPointPix, penulPointPix, snapSegmentPix1, snapSegmentPix2;
101 if ( previousPointExist )
105 if ( penulPointExist )
109 if ( hasSnappedSegment )
116 if ( curPointExist && snappedToVertex )
118 painter->setPen( mSnapPen );
119 painter->drawEllipse( curPointPix, 10, 10 );
123 if ( hasSnappedSegment && !snappedToVertex )
125 painter->setPen( mSnapPen );
126 painter->drawLine( snapSegmentPix1, snapSegmentPix2 );
130 painter->setPen( mSnapLinePen );
131 painter->drawLine( snapSegmentPix1, curPointPix );
138 painter->setPen( mConstruction2Pen );
139 painter->drawLine( snapSegmentPix1, snapSegmentPix2 );
146 if ( mAdvancedDigitizingDockWidget->constraintAngle()->relative() && nPoints > 2 )
148 a0 = std::atan2( -( prevPoint.
y() - penulPoint.
y() ), prevPoint.
x() - penulPoint.
x() );
154 if ( mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() )
156 a = a0 - mAdvancedDigitizingDockWidget->constraintAngle()->value() * M_PI / 180;
160 a = std::atan2( -( curPoint.
y() - prevPoint.
y() ), curPoint.
x() - prevPoint.
x() );
163 a0 += canvasRotationRad;
164 a += canvasRotationRad;
166 painter->setPen( mConstruction2Pen );
167 painter->drawArc( QRectF( prevPointPix.x() - 20, prevPointPix.y() - 20, 40, 40 ),
static_cast<int>( 16 * -a0 * 180 / M_PI ),
static_cast<int>( 16 * ( a0 - a ) * 180 / M_PI ) );
168 painter->drawLine( prevPointPix, prevPointPix + 60 * QPointF( std::cos( a0 ), std::sin( a0 ) ) );
171 if ( mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() )
173 painter->setPen( mLockedPen );
174 const double canvasPadding = QLineF( prevPointPix, curPointPix ).length();
176 ->drawLine( prevPointPix + ( canvasPadding - canvasDiagonalDimension ) * QPointF( std::cos( a ), std::sin( a ) ), prevPointPix + ( canvasPadding + canvasDiagonalDimension ) * QPointF( std::cos( a ), std::sin( a ) ) );
181 if ( nPoints > 1 && mAdvancedDigitizingDockWidget->constraintDistance()->isLocked() )
183 painter->setPen( mLockedPen );
184 const double r = mAdvancedDigitizingDockWidget->constraintDistance()->value() / mupp;
185 QPainterPath ellipsePath;
186 ellipsePath.addEllipse( prevPointPix, r, r );
187 const double a = std::atan2( -( curPoint.
y() - prevPoint.
y() ), curPoint.
x() - prevPoint.
x() ) + canvasRotationRad;
188 const QTransform t = QTransform().translate( prevPointPix.x(), prevPointPix.y() ).rotateRadians( a ).translate( -prevPointPix.x(), -prevPointPix.y() );
189 const QPolygonF ellipsePoly = ellipsePath.toFillPolygon( t );
190 painter->drawPolygon( ellipsePoly );
194 if ( mAdvancedDigitizingDockWidget->constraintX()->isLocked() )
198 painter->setPen( mLockedPen );
199 if ( mAdvancedDigitizingDockWidget->constraintX()->relative() )
203 x = mAdvancedDigitizingDockWidget->constraintX()->value() + prevPoint.
x();
212 x = mAdvancedDigitizingDockWidget->constraintX()->value();
217 toCanvasCoordinates(
QgsPointXY( x, mapPoly[0].y() ) ) - canvasDiagonalDimension * QPointF( std::sin( -canvasRotationRad ), std::cos( -canvasRotationRad ) ),
218 toCanvasCoordinates(
QgsPointXY( x, mapPoly[0].y() ) ) + canvasDiagonalDimension * QPointF( std::sin( -canvasRotationRad ), std::cos( -canvasRotationRad ) )
224 if ( mAdvancedDigitizingDockWidget->constraintY()->isLocked() )
228 painter->setPen( mLockedPen );
229 if ( mAdvancedDigitizingDockWidget->constraintY()->relative() )
233 y = mAdvancedDigitizingDockWidget->constraintY()->value() + prevPoint.
y();
242 y = mAdvancedDigitizingDockWidget->constraintY()->value();
247 toCanvasCoordinates(
QgsPointXY( mapPoly[0].x(), y ) ) - canvasDiagonalDimension * QPointF( std::cos( -canvasRotationRad ), -std::sin( -canvasRotationRad ) ),
248 toCanvasCoordinates(
QgsPointXY( mapPoly[0].x(), y ) ) + canvasDiagonalDimension * QPointF( std::cos( -canvasRotationRad ), -std::sin( -canvasRotationRad ) )
256 if ( curPointExist && previousPointExist )
258 painter->setPen( mConstruction2Pen );
259 painter->drawLine( prevPointPix, curPointPix );
262 if ( previousPointExist && penulPointExist )
264 painter->setPen( mConstruction1Pen );
265 painter->drawLine( penulPointPix, prevPointPix );
271 painter->setPen( mCursorPen );
272 painter->drawLine( curPointPix + QPointF( -5, -5 ), curPointPix + QPointF( +5, +5 ) );
273 painter->drawLine( curPointPix + QPointF( -5, +5 ), curPointPix + QPointF( +5, -5 ) );
276 auto lineExtensionSide = mAdvancedDigitizingDockWidget->lineExtensionSide();
277 if ( mAdvancedDigitizingDockWidget->constraintLineExtension()->isLocked() && lineExtensionSide !=
Qgis::LineExtensionSide::NoVertex && !mAdvancedDigitizingDockWidget->lockedSnapVertices().isEmpty() )
279 painter->setPen( mLockedPen );
307 vertex = geom->
vertexAt( previousVertexId );
311 vertex = geom->
vertexAt( nextVertexId );
318 const double angle = std::atan2( snappedPoint.y() - point.y(), snappedPoint.x() - point.x() );
320 const double canvasPadding = QLineF( snappedPoint, curPointPix ).length();
322 ->drawLine( snappedPoint + ( canvasPadding - canvasDiagonalDimension ) * QPointF( std::cos( angle ), std::sin( angle ) ), snappedPoint + ( canvasPadding + canvasDiagonalDimension ) * QPointF( std::cos( angle ), std::sin( angle ) ) );
326 if ( mAdvancedDigitizingDockWidget->constraintXyVertex()->isLocked() )
328 painter->setPen( mLockedPen );
330 double coordinateExtension = mAdvancedDigitizingDockWidget->softLockX();
331 if ( coordinateExtension != std::numeric_limits<double>::quiet_NaN() )
333 const QgsPointXY point( coordinateExtension, mapPoly[0].y() );
334 const QPointF rotation( std::sin( -canvasRotationRad ), std::cos( -canvasRotationRad ) );
338 coordinateExtension = mAdvancedDigitizingDockWidget->softLockY();
339 if ( coordinateExtension != std::numeric_limits<double>::quiet_NaN() )
341 const QgsPointXY point( mapPoly[0].x(), coordinateExtension );
342 const QPointF rotation( std::cos( -canvasRotationRad ), -std::sin( -canvasRotationRad ) );
347 painter->setPen( mCursorPen );
349 const QList<QgsPointLocator::Match> lockedSnapVertices = mAdvancedDigitizingDockWidget->lockedSnapVertices();
355 painter->drawLine( canvasPoint + QPointF( 5, 5 ), canvasPoint - QPointF( 5, 5 ) );
356 painter->drawLine( canvasPoint + QPointF( -5, 5 ), canvasPoint - QPointF( -5, 5 ) );
359 if ( !lockedSnapVertices.isEmpty() )
361 const QgsPointXY point = lockedSnapVertices.last().point();
364 painter->drawLine( canvasPoint + QPointF( 0, 5 ), canvasPoint - QPointF( 0, 5 ) );
365 painter->drawLine( canvasPoint + QPointF( 5, 0 ), canvasPoint - QPointF( 5, 0 ) );