Skip to content

Commit 68e7b01

Browse files
vinayanmhugent
vinayan
authored andcommittedJan 12, 2013
Added Rotate Map Tool
1 parent a3f5cea commit 68e7b01

File tree

6 files changed

+373
-1
lines changed

6 files changed

+373
-1
lines changed
 

‎src/app/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ SET(QGIS_APP_SRCS
6969
qgsmaptoolmovevertex.cpp
7070
qgsmaptooloffsetcurve.cpp
7171
qgsmaptoolreshape.cpp
72+
qgsmaptoolrotatefeature.cpp
7273
qgsmaptoolrotatelabel.cpp
7374
qgsmaptoolrotatepointsymbols.cpp
7475
qgsmaptoolselect.cpp
@@ -226,6 +227,7 @@ SET (QGIS_APP_MOC_HDRS
226227
qgsmaptoolmovevertex.h
227228
qgsmaptooloffsetcurve.h
228229
qgsmaptoolreshape.h
230+
qgsmaptoolrotatefeature.h
229231
qgsmaptoolrotatelabel.h
230232
qgsmaptoolrotatepointsymbols.h
231233
qgsmaptoolselectfreehand.h

‎src/app/qgisapp.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@
226226
#include "qgsmaptoolidentify.h"
227227
#include "qgsmaptoolmeasureangle.h"
228228
#include "qgsmaptoolmovefeature.h"
229+
#include "qgsmaptoolrotatefeature.h"
229230
#include "qgsmaptoolmovevertex.h"
230231
#include "qgsmaptooloffsetcurve.h"
231232
#include "qgsmaptoolpan.h"
@@ -747,6 +748,7 @@ QgisApp::~QgisApp()
747748
delete mMapTools.mPinLabels;
748749
delete mMapTools.mShowHideLabels;
749750
delete mMapTools.mMoveLabel;
751+
delete mMapTools.mRotateFeature;
750752
delete mMapTools.mRotateLabel;
751753
delete mMapTools.mChangeLabelProperties;
752754
delete mMapTools.mOffsetCurve;
@@ -883,6 +885,8 @@ void QgisApp::createActions()
883885
connect( mActionPasteStyle, SIGNAL( triggered() ), this, SLOT( pasteStyle() ) );
884886
connect( mActionAddFeature, SIGNAL( triggered() ), this, SLOT( addFeature() ) );
885887
connect( mActionMoveFeature, SIGNAL( triggered() ), this, SLOT( moveFeature() ) );
888+
connect( mActionRotateFeature, SIGNAL( triggered() ), this, SLOT( rotateFeature() ) );
889+
886890
connect( mActionReshapeFeatures, SIGNAL( triggered() ), this, SLOT( reshapeFeatures() ) );
887891
connect( mActionSplitFeatures, SIGNAL( triggered() ), this, SLOT( splitFeatures() ) );
888892
connect( mActionDeleteSelected, SIGNAL( triggered() ), this, SLOT( deleteSelected() ) );
@@ -1142,6 +1146,7 @@ void QgisApp::createActionGroups()
11421146
mMapToolGroup->addAction( mActionMeasureAngle );
11431147
mMapToolGroup->addAction( mActionAddFeature );
11441148
mMapToolGroup->addAction( mActionMoveFeature );
1149+
mMapToolGroup->addAction( mActionRotateFeature );
11451150
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
11461151
((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)))
11471152
mMapToolGroup->addAction( mActionOffsetCurve );
@@ -1696,6 +1701,7 @@ void QgisApp::setTheme( QString theThemeName )
16961701
mActionPasteFeatures->setIcon( QgsApplication::getThemeIcon( "/mActionEditPaste.png" ) );
16971702
mActionAddFeature->setIcon( QgsApplication::getThemeIcon( "/mActionCapturePoint.png" ) );
16981703
mActionMoveFeature->setIcon( QgsApplication::getThemeIcon( "/mActionMoveFeature.png" ) );
1704+
//mActionRotateFeature->setIcon( QgsApplication::getThemeIcon( "/mActionRotateFeature.png" ) );
16991705
mActionReshapeFeatures->setIcon( QgsApplication::getThemeIcon( "/mActionReshape.png" ) );
17001706
mActionSplitFeatures->setIcon( QgsApplication::getThemeIcon( "/mActionSplitFeatures.svg" ) );
17011707
mActionDeleteSelected->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteSelected.png" ) );
@@ -1885,6 +1891,8 @@ void QgisApp::createCanvasTools()
18851891
mMapTools.mAddFeature->setAction( mActionAddFeature );
18861892
mMapTools.mMoveFeature = new QgsMapToolMoveFeature( mMapCanvas );
18871893
mMapTools.mMoveFeature->setAction( mActionMoveFeature );
1894+
mMapTools.mRotateFeature = new QgsMapToolRotateFeature( mMapCanvas);
1895+
mMapTools.mRotateFeature->setAction(mActionRotateFeature);
18881896
//need at least geos 3.3 for OffsetCurve tool
18891897
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
18901898
((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)))
@@ -1928,6 +1936,7 @@ void QgisApp::createCanvasTools()
19281936
mMapTools.mShowHideLabels->setAction( mActionShowHideLabels );
19291937
mMapTools.mMoveLabel = new QgsMapToolMoveLabel( mMapCanvas );
19301938
mMapTools.mMoveLabel->setAction( mActionMoveLabel );
1939+
19311940
mMapTools.mRotateLabel = new QgsMapToolRotateLabel( mMapCanvas );
19321941
mMapTools.mRotateLabel->setAction( mActionRotateLabel );
19331942
mMapTools.mChangeLabelProperties = new QgsMapToolChangeLabelProperties( mMapCanvas );
@@ -4592,6 +4601,11 @@ void QgisApp::moveLabel()
45924601
mMapCanvas->setMapTool( mMapTools.mMoveLabel );
45934602
}
45944603

4604+
void QgisApp::rotateFeature()
4605+
{
4606+
mMapCanvas->setMapTool( mMapTools.mRotateFeature );
4607+
}
4608+
45954609
void QgisApp::rotateLabel()
45964610
{
45974611
mMapCanvas->setMapTool( mMapTools.mRotateLabel );
@@ -7396,6 +7410,7 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
73967410
mActionFeatureAction->setEnabled( false );
73977411
mActionAddFeature->setEnabled( false );
73987412
mActionMoveFeature->setEnabled( false );
7413+
mActionRotateFeature->setEnabled( false );
73997414
mActionOffsetCurve->setEnabled( false );
74007415
mActionNodeTool->setEnabled( false );
74017416
mActionDeleteSelected->setEnabled( false );
@@ -7538,13 +7553,15 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
75387553
mActionAddPart->setEnabled( true );
75397554
mActionDeletePart->setEnabled( true );
75407555
mActionMoveFeature->setEnabled( true );
7556+
mActionRotateFeature->setEnabled( true );
75417557
mActionNodeTool->setEnabled( true );
75427558
}
75437559
else
75447560
{
75457561
mActionAddPart->setEnabled( false );
75467562
mActionDeletePart->setEnabled( false );
75477563
mActionMoveFeature->setEnabled( false );
7564+
mActionRotateFeature->setEnabled( false );
75487565
mActionOffsetCurve->setEnabled( false );
75497566
mActionNodeTool->setEnabled( false );
75507567
}
@@ -7669,6 +7686,7 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
76697686
mActionAddPart->setEnabled( false );
76707687
mActionNodeTool->setEnabled( false );
76717688
mActionMoveFeature->setEnabled( false );
7689+
mActionRotateFeature->setEnabled( false );
76727690
mActionOffsetCurve->setEnabled( false );
76737691
mActionCopyFeatures->setEnabled( false );
76747692
mActionCutFeatures->setEnabled( false );

‎src/app/qgisapp.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
240240
QAction *actionDeleteSelected() { return mActionDeleteSelected; }
241241
QAction *actionAddFeature() { return mActionAddFeature; }
242242
QAction *actionMoveFeature() { return mActionMoveFeature; }
243+
QAction *actionRotateFeature() { return mActionRotateFeature;}
243244
QAction *actionSplitFeatures() { return mActionSplitFeatures; }
244245
QAction *actionAddRing() { return mActionAddRing; }
245246
QAction *actionAddPart() { return mActionAddPart; }
@@ -964,6 +965,8 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
964965
void showHideLabels();
965966
//! Activates the move label tool
966967
void moveLabel();
968+
//! Activates rotate feature tool
969+
void rotateFeature();
967970
//! Activates rotate label tool
968971
void rotateLabel();
969972
//! Activates label property tool
@@ -1173,6 +1176,7 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
11731176
QgsMapTool* mPinLabels;
11741177
QgsMapTool* mShowHideLabels;
11751178
QgsMapTool* mMoveLabel;
1179+
QgsMapTool* mRotateFeature;
11761180
QgsMapTool* mRotateLabel;
11771181
QgsMapTool* mChangeLabelProperties;
11781182
} mMapTools;

‎src/app/qgsmaptoolrotatefeature.cpp

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
#include "qgsmaptoolrotatefeature.h"
2+
#include "qgsgeometry.h"
3+
#include "qgslogger.h"
4+
#include "qgsmapcanvas.h"
5+
#include "qgsrubberband.h"
6+
#include "qgsvectordataprovider.h"
7+
#include "qgsvectorlayer.h"
8+
#include "qgstolerance.h"
9+
#include <QMessageBox>
10+
#include <QMouseEvent>
11+
#include <QSettings>
12+
#include <limits>
13+
#include <math.h>
14+
#include "qgsvertexmarker.h"
15+
16+
#define PI 3.14159265
17+
18+
QgsMapToolRotateFeature::QgsMapToolRotateFeature( QgsMapCanvas* canvas ): QgsMapToolEdit( canvas ), mRubberBand( 0 )
19+
{
20+
mRotation = 0;
21+
}
22+
23+
QgsMapToolRotateFeature::~QgsMapToolRotateFeature()
24+
{
25+
delete mAnchorPoint;
26+
delete mRubberBand;
27+
}
28+
29+
void QgsMapToolRotateFeature::canvasMoveEvent( QMouseEvent * e )
30+
{
31+
if( mCtrl == true )
32+
{
33+
mAnchorPoint->setCenter(toMapCoordinates(e->pos()));
34+
mStartPointMapCoords = toMapCoordinates(e->pos());
35+
mStPoint = e->pos();
36+
return;
37+
}
38+
if ( mRubberBand )
39+
{
40+
double XDistance = mStPoint.x() - e->pos().x();
41+
double YDistance = mStPoint.y() - e->pos().y();
42+
mRotation = atan2(YDistance, XDistance) * (180/PI);
43+
44+
double offsetX = mStPoint.x() - mRubberBand->x();
45+
double offsetY = mStPoint.y() - mRubberBand->y();
46+
mRubberBand->setTransform(QTransform().translate(offsetX, offsetY).rotate(mRotation).translate(-1 * offsetX, -1 * offsetY));
47+
mRubberBand->update();
48+
}
49+
}
50+
51+
void QgsMapToolRotateFeature::canvasPressEvent( QMouseEvent * e )
52+
{
53+
mRotation = 0;
54+
if( mCtrl == true )
55+
{
56+
return;
57+
}
58+
59+
delete mRubberBand;
60+
mRubberBand = 0;
61+
62+
mInitialPos = e->pos();
63+
64+
QgsVectorLayer* vlayer = currentVectorLayer();
65+
if ( !vlayer )
66+
{
67+
return;
68+
}
69+
70+
if ( vlayer->selectedFeatureCount() == 0 )
71+
{
72+
return;
73+
}
74+
else
75+
{
76+
mMovedFeatures = vlayer->selectedFeaturesIds();
77+
78+
mRubberBand = createRubberBand();
79+
for ( int i = 0; i < vlayer->selectedFeatureCount(); i++ )
80+
{
81+
mRubberBand->addGeometry( vlayer->selectedFeatures()[i].geometry(), vlayer );
82+
}
83+
}
84+
85+
mRubberBand->setColor( Qt::red );
86+
mRubberBand->setWidth( 2 );
87+
mRubberBand->show();
88+
89+
}
90+
91+
void QgsMapToolRotateFeature::canvasReleaseEvent( QMouseEvent * e )
92+
{
93+
if ( !mRubberBand )
94+
{
95+
return;
96+
}
97+
98+
QgsVectorLayer* vlayer = currentVectorLayer();
99+
if ( !vlayer )
100+
{
101+
return;
102+
}
103+
104+
//calculations for affine transformation..
105+
double angle = -1 * mRotation * (PI/180);
106+
QgsPoint anchorPoint = mStartPointMapCoords;
107+
double a = cos(angle);
108+
double b = -1 * sin(angle);
109+
double c = anchorPoint.x() - cos(angle) * anchorPoint.x() + sin(angle) * anchorPoint.y();
110+
double d = sin(angle);
111+
double ee = cos(angle);
112+
double f = anchorPoint.y() - sin(angle) * anchorPoint.x() - cos(angle) * anchorPoint.y();
113+
114+
vlayer->beginEditCommand( tr( "Features Rotated" ) );
115+
116+
int start;
117+
if ( vlayer->geometryType()==2)
118+
{
119+
start=1;
120+
}
121+
else
122+
{
123+
start=0;
124+
}
125+
126+
int i = 0;
127+
foreach ( QgsFeatureId id, mMovedFeatures )
128+
{
129+
QgsFeature feat;
130+
vlayer->featureAtId(id,feat);
131+
QgsGeometry* geom = feat.geometry();
132+
i = start;
133+
134+
QgsPoint vertex = geom->vertexAt(i);
135+
while ( vertex != QgsPoint(0,0))
136+
{
137+
double newX = a * vertex.x() + b * vertex.y() + c;
138+
double newY = d * vertex.x() + ee * vertex.y() + f;
139+
140+
vlayer->moveVertex(newX,newY,id,i);
141+
i = i + 1;
142+
vertex = geom->vertexAt(i);
143+
}
144+
145+
}
146+
147+
double anchorX = a * anchorPoint.x() + b * anchorPoint.y() + c;
148+
double anchorY = d * anchorPoint.x() + ee * anchorPoint.y() + f;
149+
150+
mAnchorPoint->setCenter(QgsPoint(anchorX,anchorY));
151+
152+
delete mRubberBand;
153+
mRubberBand = 0;
154+
155+
mCanvas->refresh();
156+
vlayer->endEditCommand();
157+
158+
}
159+
160+
void QgsMapToolRotateFeature::resetAnchor()
161+
{
162+
QgsVectorLayer* vlayer = currentVectorLayer();
163+
if ( !vlayer )
164+
{
165+
return;
166+
}
167+
168+
if ( vlayer->selectedFeatureCount() == 0 )
169+
{
170+
return;
171+
}
172+
else
173+
{
174+
175+
QgsRectangle bound = vlayer->boundingBoxOfSelected();
176+
mStartPointMapCoords = bound.center();
177+
178+
mAnchorPoint->setCenter(mStartPointMapCoords);
179+
180+
mStPoint = toCanvasCoordinates(mStartPointMapCoords);
181+
}
182+
183+
}
184+
185+
186+
void QgsMapToolRotateFeature::keyPressEvent( QKeyEvent* e )
187+
{
188+
if ( e->key() == Qt::Key_Control )
189+
{
190+
mCtrl = true;
191+
mCanvas->viewport()->setMouseTracking(true);
192+
return;
193+
}
194+
195+
if (e->key() == Qt::Key_Escape)
196+
{
197+
this->resetAnchor();
198+
}
199+
}
200+
201+
void QgsMapToolRotateFeature::keyReleaseEvent( QKeyEvent* e )
202+
{
203+
if ( e->key() == Qt::Key_Control )
204+
{
205+
mCtrl = false;
206+
mCanvas->viewport()->setMouseTracking(false);
207+
208+
return;
209+
}
210+
211+
}
212+
213+
void QgsMapToolRotateFeature::activate()
214+
{
215+
216+
QgsVectorLayer* vlayer = currentVectorLayer();
217+
if ( !vlayer )
218+
{
219+
return;
220+
}
221+
222+
if ( !vlayer->isEditable() )
223+
{
224+
QMessageBox::information( 0, tr( "Layer not editable" ),
225+
tr( "Cannot edit the vector layer. Use 'Toggle Editing' to make it editable." )
226+
);
227+
return;
228+
}
229+
230+
if ( vlayer->selectedFeatureCount() == 0 )
231+
{
232+
return;
233+
}
234+
else
235+
{
236+
237+
QgsRectangle bound = vlayer->boundingBoxOfSelected();
238+
mStartPointMapCoords = bound.center();
239+
240+
mAnchorPoint = new QgsVertexMarker(mCanvas);
241+
mAnchorPoint->setIconType( QgsVertexMarker::ICON_CROSS );
242+
mAnchorPoint->setCenter(mStartPointMapCoords);
243+
mAnchorPoint->acceptTouchEvents();
244+
245+
mStPoint = toCanvasCoordinates(mStartPointMapCoords);
246+
mCtrl = false;
247+
248+
QgsMapTool::activate();
249+
}
250+
}
251+
252+
void QgsMapToolRotateFeature::deactivate()
253+
{
254+
delete mRubberBand;
255+
delete mAnchorPoint;
256+
mRubberBand = 0;
257+
mAnchorPoint = 0;
258+
259+
QgsMapTool::deactivate();
260+
}

‎src/app/qgsmaptoolrotatefeature.h

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/***************************************************************************
2+
qgsmaptoolmovefeature.h - map tool for translating features by mouse drag
3+
---------------------
4+
begin : Juli 2007
5+
copyright : (C) 2007 by Marco Hugentobler
6+
email : marco dot hugentobler at karto dot baug dot ethz dot ch
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+
#ifndef QGSMAPTOOLROTATEFEATURE_H
17+
#define QGSMAPTOOLROTATEFEATURE_H
18+
19+
#include "qgsmaptooledit.h"
20+
#include "qgsvectorlayer.h"
21+
22+
class QgsVertexMarker;
23+
24+
/**Map tool for translating feature position by mouse drag*/
25+
class QgsMapToolRotateFeature: public QgsMapToolEdit
26+
{
27+
Q_OBJECT
28+
public:
29+
QgsMapToolRotateFeature( QgsMapCanvas* canvas );
30+
virtual ~QgsMapToolRotateFeature();
31+
32+
virtual void canvasMoveEvent( QMouseEvent * e );
33+
34+
virtual void canvasPressEvent( QMouseEvent * e );
35+
36+
virtual void canvasReleaseEvent( QMouseEvent * e );
37+
38+
void keyPressEvent( QKeyEvent* e );
39+
40+
void keyReleaseEvent( QKeyEvent* e );
41+
42+
43+
44+
//! to reset the rotation anchor to selectionbound center
45+
void resetAnchor();
46+
//! called when map tool is being deactivated
47+
void deactivate();
48+
49+
void activate();
50+
51+
52+
53+
private:
54+
55+
QgsGeometry rotateGeometry(QgsGeometry geom, QgsPoint point, double angle);
56+
QgsPoint rotatePoint(QgsPoint point, double angle);
57+
58+
/**Start point of the move in map coordinates*/
59+
QgsPoint mStartPointMapCoords;
60+
QPointF mInitialPos;
61+
62+
/**Rubberband that shows the feature being moved*/
63+
QgsRubberBand* mRubberBand;
64+
65+
/**Id of moved feature*/
66+
QgsFeatureIds mMovedFeatures;
67+
double mRotation;
68+
69+
QPoint mStPoint;
70+
QgsVertexMarker* mAnchorPoint;
71+
72+
/** flag if crtl is pressed */
73+
bool mCtrl;
74+
};
75+
76+
#endif

‎src/ui/qgisapp.ui

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<x>0</x>
1818
<y>0</y>
1919
<width>1052</width>
20-
<height>20</height>
20+
<height>25</height>
2121
</rect>
2222
</property>
2323
<widget class="QMenu" name="mEditMenu">
@@ -288,6 +288,7 @@
288288
<addaction name="mActionSaveLayerEdits"/>
289289
<addaction name="mActionAddFeature"/>
290290
<addaction name="mActionMoveFeature"/>
291+
<addaction name="mActionRotateFeature"/>
291292
<addaction name="mActionNodeTool"/>
292293
<addaction name="mActionDeleteSelected"/>
293294
<addaction name="mActionCutFeatures"/>
@@ -1968,6 +1969,17 @@ Acts on currently active editable layer</string>
19681969
<string>Save Layer Edits</string>
19691970
</property>
19701971
</action>
1972+
<action name="mActionRotateFeature">
1973+
<property name="checkable">
1974+
<bool>true</bool>
1975+
</property>
1976+
<property name="text">
1977+
<string>Rotate Feature(s)</string>
1978+
</property>
1979+
<property name="toolTip">
1980+
<string>Rotate Feature(s)</string>
1981+
</property>
1982+
</action>
19711983
</widget>
19721984
<resources>
19731985
<include location="../../images/images.qrc"/>

0 commit comments

Comments
 (0)
Please sign in to comment.