Skip to content

Commit 378841e

Browse files
committedJan 8, 2021
Fix broken manual rotation anchor point setting via ctrl+click in rotate features tool
Ctrl+clicking to set the manual rotation point had no effect, and the selected rotation point was always reset as soon as the rotation action started. Apparently this has been broken for some time (confirmed broken since 3.4 at least!). Also add tests.
1 parent 0d785c8 commit 378841e

File tree

2 files changed

+78
-9
lines changed

2 files changed

+78
-9
lines changed
 

‎src/app/qgsmaptoolrotatefeature.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@ void QgsMapToolRotateFeature::canvasReleaseEvent( QgsMapMouseEvent *e )
202202
{
203203
if ( !mAnchorPoint )
204204
{
205-
return;
205+
mAnchorPoint = qgis::make_unique<QgsVertexMarker>( mCanvas );
206+
mAnchorPoint->setIconType( QgsVertexMarker::ICON_CROSS );
206207
}
207208
mAnchorPoint->setCenter( toMapCoordinates( e->pos() ) );
208209
mStartPointMapCoords = toMapCoordinates( e->pos() );
@@ -233,10 +234,12 @@ void QgsMapToolRotateFeature::canvasReleaseEvent( QgsMapMouseEvent *e )
233234
QgsRectangle selectRect( layerCoords.x() - searchRadius, layerCoords.y() - searchRadius,
234235
layerCoords.x() + searchRadius, layerCoords.y() + searchRadius );
235236

237+
bool autoCalculateAnchorPoint = false;
236238
if ( !mAnchorPoint )
237239
{
238240
mAnchorPoint = qgis::make_unique<QgsVertexMarker>( mCanvas );
239241
mAnchorPoint->setIconType( QgsVertexMarker::ICON_CROSS );
242+
autoCalculateAnchorPoint = true;
240243
}
241244

242245
if ( vlayer->selectedFeatureCount() == 0 )
@@ -274,8 +277,15 @@ void QgsMapToolRotateFeature::canvasReleaseEvent( QgsMapMouseEvent *e )
274277
}
275278

276279
QgsRectangle bound = cf.geometry().boundingBox();
277-
mStartPointMapCoords = toMapCoordinates( vlayer, bound.center() );
278-
mAnchorPoint->setCenter( mStartPointMapCoords );
280+
if ( autoCalculateAnchorPoint )
281+
{
282+
mStartPointMapCoords = toMapCoordinates( vlayer, bound.center() );
283+
mAnchorPoint->setCenter( mStartPointMapCoords );
284+
}
285+
else
286+
{
287+
mStartPointMapCoords = mAnchorPoint->center();
288+
}
279289

280290
mStPoint = toCanvasCoordinates( mStartPointMapCoords );
281291

@@ -407,14 +417,8 @@ void QgsMapToolRotateFeature::applyRotation( double rotation )
407417
i = i + 1;
408418
vertex = geom.vertexAt( i );
409419
}
410-
411420
}
412421

413-
double anchorX = a * anchorPoint.x() + b * anchorPoint.y() + c;
414-
double anchorY = d * anchorPoint.x() + ee * anchorPoint.y() + f;
415-
416-
mAnchorPoint->setCenter( QgsPointXY( anchorX, anchorY ) );
417-
418422
deleteRotationWidget();
419423
deleteRubberband();
420424

‎tests/src/app/testqgsmaptoolrotatefeature.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ class TestQgsMapToolRotateFeature: public QObject
4444
void cleanupTestCase();// will be called after the last testfunction was executed.
4545

4646
void testRotateFeature();
47+
void testRotateFeatureManualAnchor();
48+
void testCancelManualAnchor();
49+
void testRotateFeatureManualAnchorAfterStartRotate();
4750

4851
private:
4952
QgisApp *mQgisApp = nullptr;
@@ -140,6 +143,68 @@ void TestQgsMapToolRotateFeature::testRotateFeature()
140143
mLayerBase->undoStack()->undo();
141144
}
142145

146+
void TestQgsMapToolRotateFeature::testRotateFeatureManualAnchor()
147+
{
148+
// test rotating around a fixed anchor point
149+
TestQgsMapToolUtils utils( mRotateTool );
150+
151+
// set anchor point
152+
utils.mouseClick( 0, 5, Qt::LeftButton, Qt::ControlModifier, true );
153+
154+
utils.mouseClick( 1, 1, Qt::LeftButton, Qt::KeyboardModifiers(), true );
155+
utils.mouseMove( 2, 1 );
156+
utils.mouseClick( 2, 1, Qt::LeftButton, Qt::KeyboardModifiers(), true );
157+
158+
QCOMPARE( mLayerBase->getFeature( 1 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((2.06 0.34, 0.87 1.1, 1.84 1.31, 2.06 0.34))" ) );
159+
QCOMPARE( mLayerBase->getFeature( 2 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1.1 0, 1.1 5, 2.1 5, 2.1 0))" ) );
160+
161+
mLayerBase->undoStack()->undo();
162+
}
163+
164+
void TestQgsMapToolRotateFeature::testCancelManualAnchor()
165+
{
166+
// test canceling rotation around a fixed anchor point
167+
TestQgsMapToolUtils utils( mRotateTool );
168+
169+
// set anchor point
170+
utils.mouseClick( 0, 5, Qt::LeftButton, Qt::ControlModifier, true );
171+
172+
// right click = remove anchor point
173+
utils.mouseClick( 10, 15, Qt::RightButton, Qt::KeyboardModifiers(), true );
174+
175+
// now rotate -- should be around feature center, not anchor point
176+
utils.mouseClick( 1, 1, Qt::LeftButton, Qt::KeyboardModifiers(), true );
177+
utils.mouseMove( 2, 1 );
178+
utils.mouseClick( 2, 1, Qt::LeftButton, Qt::KeyboardModifiers(), true );
179+
180+
QCOMPARE( mLayerBase->getFeature( 1 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((0.72 -0.17, 0.28 1.17, 1.17 0.72, 0.72 -0.17))" ) );
181+
QCOMPARE( mLayerBase->getFeature( 2 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1.1 0, 1.1 5, 2.1 5, 2.1 0))" ) );
182+
183+
mLayerBase->undoStack()->undo();
184+
}
185+
186+
void TestQgsMapToolRotateFeature::testRotateFeatureManualAnchorAfterStartRotate()
187+
{
188+
// test rotating around a fixed anchor point, where the fixed anchor point is placed after rotation begins
189+
TestQgsMapToolUtils utils( mRotateTool );
190+
191+
// start rotation
192+
utils.mouseClick( 1, 1, Qt::LeftButton, Qt::KeyboardModifiers(), true );
193+
194+
// set anchor point
195+
utils.mouseMove( 0, 5 );
196+
utils.mouseClick( 0, 5, Qt::LeftButton, Qt::ControlModifier, true );
197+
198+
// complete rotation
199+
utils.mouseMove( 2, 1 );
200+
utils.mouseClick( 2, 1, Qt::LeftButton, Qt::KeyboardModifiers(), true );
201+
202+
QCOMPARE( mLayerBase->getFeature( 1 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((-5.06 5.63, -3.79 6.26, -4.11 5.32, -5.06 5.63))" ) );
203+
QCOMPARE( mLayerBase->getFeature( 2 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1.1 0, 1.1 5, 2.1 5, 2.1 0))" ) );
204+
205+
mLayerBase->undoStack()->undo();
206+
}
207+
143208

144209
QGSTEST_MAIN( TestQgsMapToolRotateFeature )
145210
#include "testqgsmaptoolrotatefeature.moc"

0 commit comments

Comments
 (0)
Please sign in to comment.