Skip to content
Permalink
Browse files

Fix broken manual rotation anchor point setting via ctrl+click in rot…

…ate 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.
  • Loading branch information
nyalldawson committed Jan 8, 2021
1 parent 0d785c8 commit 378841e5607fc56159ca559fccad5d3675a6f77d
Showing with 78 additions and 9 deletions.
  1. +13 −9 src/app/qgsmaptoolrotatefeature.cpp
  2. +65 −0 tests/src/app/testqgsmaptoolrotatefeature.cpp
@@ -202,7 +202,8 @@ void QgsMapToolRotateFeature::canvasReleaseEvent( QgsMapMouseEvent *e )
{
if ( !mAnchorPoint )
{
return;
mAnchorPoint = qgis::make_unique<QgsVertexMarker>( mCanvas );
mAnchorPoint->setIconType( QgsVertexMarker::ICON_CROSS );
}
mAnchorPoint->setCenter( toMapCoordinates( e->pos() ) );
mStartPointMapCoords = toMapCoordinates( e->pos() );
@@ -233,10 +234,12 @@ void QgsMapToolRotateFeature::canvasReleaseEvent( QgsMapMouseEvent *e )
QgsRectangle selectRect( layerCoords.x() - searchRadius, layerCoords.y() - searchRadius,
layerCoords.x() + searchRadius, layerCoords.y() + searchRadius );

bool autoCalculateAnchorPoint = false;
if ( !mAnchorPoint )
{
mAnchorPoint = qgis::make_unique<QgsVertexMarker>( mCanvas );
mAnchorPoint->setIconType( QgsVertexMarker::ICON_CROSS );
autoCalculateAnchorPoint = true;
}

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

QgsRectangle bound = cf.geometry().boundingBox();
mStartPointMapCoords = toMapCoordinates( vlayer, bound.center() );
mAnchorPoint->setCenter( mStartPointMapCoords );
if ( autoCalculateAnchorPoint )
{
mStartPointMapCoords = toMapCoordinates( vlayer, bound.center() );
mAnchorPoint->setCenter( mStartPointMapCoords );
}
else
{
mStartPointMapCoords = mAnchorPoint->center();
}

mStPoint = toCanvasCoordinates( mStartPointMapCoords );

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

}

double anchorX = a * anchorPoint.x() + b * anchorPoint.y() + c;
double anchorY = d * anchorPoint.x() + ee * anchorPoint.y() + f;

mAnchorPoint->setCenter( QgsPointXY( anchorX, anchorY ) );

deleteRotationWidget();
deleteRubberband();

@@ -44,6 +44,9 @@ class TestQgsMapToolRotateFeature: public QObject
void cleanupTestCase();// will be called after the last testfunction was executed.

void testRotateFeature();
void testRotateFeatureManualAnchor();
void testCancelManualAnchor();
void testRotateFeatureManualAnchorAfterStartRotate();

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

void TestQgsMapToolRotateFeature::testRotateFeatureManualAnchor()
{
// test rotating around a fixed anchor point
TestQgsMapToolUtils utils( mRotateTool );

// set anchor point
utils.mouseClick( 0, 5, Qt::LeftButton, Qt::ControlModifier, true );

utils.mouseClick( 1, 1, Qt::LeftButton, Qt::KeyboardModifiers(), true );
utils.mouseMove( 2, 1 );
utils.mouseClick( 2, 1, Qt::LeftButton, Qt::KeyboardModifiers(), true );

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))" ) );
QCOMPARE( mLayerBase->getFeature( 2 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1.1 0, 1.1 5, 2.1 5, 2.1 0))" ) );

mLayerBase->undoStack()->undo();
}

void TestQgsMapToolRotateFeature::testCancelManualAnchor()
{
// test canceling rotation around a fixed anchor point
TestQgsMapToolUtils utils( mRotateTool );

// set anchor point
utils.mouseClick( 0, 5, Qt::LeftButton, Qt::ControlModifier, true );

// right click = remove anchor point
utils.mouseClick( 10, 15, Qt::RightButton, Qt::KeyboardModifiers(), true );

// now rotate -- should be around feature center, not anchor point
utils.mouseClick( 1, 1, Qt::LeftButton, Qt::KeyboardModifiers(), true );
utils.mouseMove( 2, 1 );
utils.mouseClick( 2, 1, Qt::LeftButton, Qt::KeyboardModifiers(), true );

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))" ) );
QCOMPARE( mLayerBase->getFeature( 2 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1.1 0, 1.1 5, 2.1 5, 2.1 0))" ) );

mLayerBase->undoStack()->undo();
}

void TestQgsMapToolRotateFeature::testRotateFeatureManualAnchorAfterStartRotate()
{
// test rotating around a fixed anchor point, where the fixed anchor point is placed after rotation begins
TestQgsMapToolUtils utils( mRotateTool );

// start rotation
utils.mouseClick( 1, 1, Qt::LeftButton, Qt::KeyboardModifiers(), true );

// set anchor point
utils.mouseMove( 0, 5 );
utils.mouseClick( 0, 5, Qt::LeftButton, Qt::ControlModifier, true );

// complete rotation
utils.mouseMove( 2, 1 );
utils.mouseClick( 2, 1, Qt::LeftButton, Qt::KeyboardModifiers(), true );

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))" ) );
QCOMPARE( mLayerBase->getFeature( 2 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1.1 0, 1.1 5, 2.1 5, 2.1 0))" ) );

mLayerBase->undoStack()->undo();
}


QGSTEST_MAIN( TestQgsMapToolRotateFeature )
#include "testqgsmaptoolrotatefeature.moc"

0 comments on commit 378841e

Please sign in to comment.
You can’t perform that action at this time.