mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-18 00:06:00 -04:00
[FEATURE]: add tool to graphically rotate points (by changing the value of the rotation field). Needs some more beautifying, perhaps a nicer arrow
git-svn-id: http://svn.osgeo.org/qgis/trunk@11671 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
parent
1669b15f6a
commit
94e76d8535
BIN
images/themes/default/mActionRotatePointSymbols.png
Normal file
BIN
images/themes/default/mActionRotatePointSymbols.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
@ -40,6 +40,7 @@ SET(QGIS_APP_SRCS
|
|||||||
qgsmaptoolmovevertex.cpp
|
qgsmaptoolmovevertex.cpp
|
||||||
qgsmaptoolnodetool.cpp
|
qgsmaptoolnodetool.cpp
|
||||||
qgsmaptoolreshape.cpp
|
qgsmaptoolreshape.cpp
|
||||||
|
qgsmaptoolrotatepointsymbols.cpp
|
||||||
qgsmaptoolselect.cpp
|
qgsmaptoolselect.cpp
|
||||||
qgsmaptoolsimplify.cpp
|
qgsmaptoolsimplify.cpp
|
||||||
qgsmaptoolsplitfeatures.cpp
|
qgsmaptoolsplitfeatures.cpp
|
||||||
@ -52,6 +53,7 @@ SET(QGIS_APP_SRCS
|
|||||||
qgsogrsublayersdialog.cpp
|
qgsogrsublayersdialog.cpp
|
||||||
qgsoptions.cpp
|
qgsoptions.cpp
|
||||||
qgspastetransformations.cpp
|
qgspastetransformations.cpp
|
||||||
|
qgspointrotationitem.cpp
|
||||||
qgspluginitem.cpp
|
qgspluginitem.cpp
|
||||||
qgspluginmanager.cpp
|
qgspluginmanager.cpp
|
||||||
qgspluginmetadata.cpp
|
qgspluginmetadata.cpp
|
||||||
|
@ -172,6 +172,7 @@
|
|||||||
#include "qgsmaptoolpan.h"
|
#include "qgsmaptoolpan.h"
|
||||||
#include "qgsmaptoolselect.h"
|
#include "qgsmaptoolselect.h"
|
||||||
#include "qgsmaptoolreshape.h"
|
#include "qgsmaptoolreshape.h"
|
||||||
|
#include "qgsmaptoolrotatepointsymbols.h"
|
||||||
#include "qgsmaptoolsplitfeatures.h"
|
#include "qgsmaptoolsplitfeatures.h"
|
||||||
#include "qgsmaptoolvertexedit.h"
|
#include "qgsmaptoolvertexedit.h"
|
||||||
#include "qgsmaptoolzoom.h"
|
#include "qgsmaptoolzoom.h"
|
||||||
@ -740,6 +741,12 @@ void QgisApp::createActions()
|
|||||||
connect( mActionNodeTool, SIGNAL( triggered() ), this, SLOT( nodeTool() ) );
|
connect( mActionNodeTool, SIGNAL( triggered() ), this, SLOT( nodeTool() ) );
|
||||||
mActionNodeTool->setEnabled( false );
|
mActionNodeTool->setEnabled( false );
|
||||||
|
|
||||||
|
mActionRotatePointSymbols = new QAction( getThemeIcon( "mActionRotatePointSymbols.png" ), tr( "Rotate Point Symbols" ), this );
|
||||||
|
shortcuts->registerAction( mActionRotatePointSymbols );
|
||||||
|
mActionRotatePointSymbols->setStatusTip( tr( "Rotate Point Symbols" ) );
|
||||||
|
connect( mActionRotatePointSymbols, SIGNAL( triggered() ), this, SLOT( rotatePointSymbols() ) );
|
||||||
|
mActionRotatePointSymbols->setEnabled( false );
|
||||||
|
|
||||||
// View Menu Items
|
// View Menu Items
|
||||||
|
|
||||||
mActionPan = new QAction( getThemeIcon( "mActionPan.png" ), tr( "Pan Map" ), this );
|
mActionPan = new QAction( getThemeIcon( "mActionPan.png" ), tr( "Pan Map" ), this );
|
||||||
@ -1094,7 +1101,8 @@ void QgisApp::createActionGroups()
|
|||||||
mMapToolGroup->addAction( mActionMergeFeatures );
|
mMapToolGroup->addAction( mActionMergeFeatures );
|
||||||
mActionNodeTool->setCheckable( true );
|
mActionNodeTool->setCheckable( true );
|
||||||
mMapToolGroup->addAction( mActionNodeTool );
|
mMapToolGroup->addAction( mActionNodeTool );
|
||||||
|
mActionRotatePointSymbols->setCheckable( true );
|
||||||
|
mMapToolGroup->addAction( mActionRotatePointSymbols );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgisApp::createMenus()
|
void QgisApp::createMenus()
|
||||||
@ -1189,6 +1197,7 @@ void QgisApp::createMenus()
|
|||||||
mEditMenu->addAction( mActionSplitFeatures );
|
mEditMenu->addAction( mActionSplitFeatures );
|
||||||
mEditMenu->addAction( mActionMergeFeatures );
|
mEditMenu->addAction( mActionMergeFeatures );
|
||||||
mEditMenu->addAction( mActionNodeTool );
|
mEditMenu->addAction( mActionNodeTool );
|
||||||
|
mEditMenu->addAction( mActionRotatePointSymbols );
|
||||||
|
|
||||||
if ( layout == QDialogButtonBox::GnomeLayout || layout == QDialogButtonBox::MacLayout )
|
if ( layout == QDialogButtonBox::GnomeLayout || layout == QDialogButtonBox::MacLayout )
|
||||||
{
|
{
|
||||||
@ -1398,6 +1407,7 @@ void QgisApp::createToolBars()
|
|||||||
mAdvancedDigitizeToolBar->addAction( mActionSplitFeatures );
|
mAdvancedDigitizeToolBar->addAction( mActionSplitFeatures );
|
||||||
mAdvancedDigitizeToolBar->addAction( mActionMergeFeatures );
|
mAdvancedDigitizeToolBar->addAction( mActionMergeFeatures );
|
||||||
mAdvancedDigitizeToolBar->addAction( mActionNodeTool );
|
mAdvancedDigitizeToolBar->addAction( mActionNodeTool );
|
||||||
|
mAdvancedDigitizeToolBar->addAction( mActionRotatePointSymbols );
|
||||||
mToolbarMenu->addAction( mAdvancedDigitizeToolBar->toggleViewAction() );
|
mToolbarMenu->addAction( mAdvancedDigitizeToolBar->toggleViewAction() );
|
||||||
|
|
||||||
|
|
||||||
@ -1788,6 +1798,8 @@ void QgisApp::createCanvas()
|
|||||||
mMapTools.mDeletePart->setAction( mActionDeletePart );
|
mMapTools.mDeletePart->setAction( mActionDeletePart );
|
||||||
mMapTools.mNodeTool = new QgsMapToolNodeTool( mMapCanvas );
|
mMapTools.mNodeTool = new QgsMapToolNodeTool( mMapCanvas );
|
||||||
mMapTools.mNodeTool->setAction( mActionNodeTool );
|
mMapTools.mNodeTool->setAction( mActionNodeTool );
|
||||||
|
mMapTools.mRotatePointSymbolsTool = new QgsMapToolRotatePointSymbols( mMapCanvas );
|
||||||
|
mMapTools.mRotatePointSymbolsTool->setAction( mActionRotatePointSymbols );
|
||||||
//ensure that non edit tool is initialised or we will get crashes in some situations
|
//ensure that non edit tool is initialised or we will get crashes in some situations
|
||||||
mNonEditMapTool = mMapTools.mPan;
|
mNonEditMapTool = mMapTools.mPan;
|
||||||
}
|
}
|
||||||
@ -4298,6 +4310,11 @@ void QgisApp::nodeTool()
|
|||||||
mMapCanvas->setMapTool( mMapTools.mNodeTool );
|
mMapCanvas->setMapTool( mMapTools.mNodeTool );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgisApp::rotatePointSymbols()
|
||||||
|
{
|
||||||
|
mMapCanvas->setMapTool( mMapTools.mRotatePointSymbolsTool );
|
||||||
|
}
|
||||||
|
|
||||||
void QgisApp::splitFeatures()
|
void QgisApp::splitFeatures()
|
||||||
{
|
{
|
||||||
mMapCanvas->setMapTool( mMapTools.mSplitFeatures );
|
mMapCanvas->setMapTool( mMapTools.mSplitFeatures );
|
||||||
@ -5639,11 +5656,19 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
|
|||||||
mActionSplitFeatures->setEnabled( false );
|
mActionSplitFeatures->setEnabled( false );
|
||||||
mActionSimplifyFeature->setEnabled( false );
|
mActionSimplifyFeature->setEnabled( false );
|
||||||
mActionDeleteRing->setEnabled( false );
|
mActionDeleteRing->setEnabled( false );
|
||||||
|
mActionRotatePointSymbols->setEnabled( false );
|
||||||
|
|
||||||
if ( vlayer->isEditable() && dprovider->capabilities() & QgsVectorDataProvider::ChangeGeometries )
|
if ( vlayer->isEditable() && dprovider->capabilities() & QgsVectorDataProvider::ChangeGeometries )
|
||||||
{
|
{
|
||||||
mActionMoveVertex->setEnabled( true );
|
mActionMoveVertex->setEnabled( true );
|
||||||
}
|
}
|
||||||
|
if ( vlayer->isEditable() && dprovider->capabilities() & QgsVectorDataProvider::ChangeAttributeValues )
|
||||||
|
{
|
||||||
|
if ( QgsMapToolRotatePointSymbols::layerIsRotatable( vlayer ) )
|
||||||
|
{
|
||||||
|
mActionRotatePointSymbols->setEnabled( true );
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ( vlayer->geometryType() == QGis::Line )
|
else if ( vlayer->geometryType() == QGis::Line )
|
||||||
@ -5752,6 +5777,9 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
|
|||||||
mActionCopyFeatures->setEnabled( false );
|
mActionCopyFeatures->setEnabled( false );
|
||||||
mActionCutFeatures->setEnabled( false );
|
mActionCutFeatures->setEnabled( false );
|
||||||
mActionPasteFeatures->setEnabled( false );
|
mActionPasteFeatures->setEnabled( false );
|
||||||
|
mActionRotatePointSymbols->setEnabled( false );
|
||||||
|
mActionNodeTool->setEnabled( false );
|
||||||
|
mActionDeletePart->setEnabled( false );
|
||||||
|
|
||||||
//NOTE: This check does not really add any protection, as it is called on load not on layer select/activate
|
//NOTE: This check does not really add any protection, as it is called on load not on layer select/activate
|
||||||
//If you load a layer with a provider and idenitfy ability then load another without, the tool would be disabled for both
|
//If you load a layer with a provider and idenitfy ability then load another without, the tool would be disabled for both
|
||||||
|
@ -523,6 +523,8 @@ class QgisApp : public QMainWindow
|
|||||||
void mergeSelectedFeatures();
|
void mergeSelectedFeatures();
|
||||||
//! provides operations with nodes
|
//! provides operations with nodes
|
||||||
void nodeTool();
|
void nodeTool();
|
||||||
|
//! activates the rotate points tool
|
||||||
|
void rotatePointSymbols();
|
||||||
|
|
||||||
//! activates the selection tool
|
//! activates the selection tool
|
||||||
void select();
|
void select();
|
||||||
@ -742,6 +744,7 @@ class QgisApp : public QMainWindow
|
|||||||
QAction *mActionDeletePart;
|
QAction *mActionDeletePart;
|
||||||
QAction *mActionMergeFeatures;
|
QAction *mActionMergeFeatures;
|
||||||
QAction *mActionNodeTool;
|
QAction *mActionNodeTool;
|
||||||
|
QAction *mActionRotatePointSymbols;
|
||||||
QAction *mActionEditSeparator3;
|
QAction *mActionEditSeparator3;
|
||||||
|
|
||||||
QAction *mActionPan;
|
QAction *mActionPan;
|
||||||
@ -864,6 +867,7 @@ class QgisApp : public QMainWindow
|
|||||||
QgsMapTool* mDeleteRing;
|
QgsMapTool* mDeleteRing;
|
||||||
QgsMapTool* mDeletePart;
|
QgsMapTool* mDeletePart;
|
||||||
QgsMapTool* mNodeTool;
|
QgsMapTool* mNodeTool;
|
||||||
|
QgsMapTool* mRotatePointSymbolsTool;
|
||||||
} mMapTools;
|
} mMapTools;
|
||||||
|
|
||||||
QgsMapTool *mNonEditMapTool;
|
QgsMapTool *mNonEditMapTool;
|
||||||
|
250
src/app/qgsmaptoolrotatepointsymbols.cpp
Normal file
250
src/app/qgsmaptoolrotatepointsymbols.cpp
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmaptoolrotatepointsymbols.cpp
|
||||||
|
--------------------------------
|
||||||
|
begin : September 2009
|
||||||
|
copyright : (C) 2009 by Marco Hugentobler
|
||||||
|
email : marco at hugis dot net
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "qgsmaptoolrotatepointsymbols.h"
|
||||||
|
#include "qgsapplication.h"
|
||||||
|
#include "qgsmapcanvas.h"
|
||||||
|
#include "qgspointrotationitem.h"
|
||||||
|
#include "qgsrenderer.h"
|
||||||
|
#include "qgssymbol.h"
|
||||||
|
#include "qgsvectorlayer.h"
|
||||||
|
#include <QGraphicsPixmapItem>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
|
||||||
|
QgsMapToolRotatePointSymbols::QgsMapToolRotatePointSymbols( QgsMapCanvas* canvas ): QgsMapToolEdit( canvas ), \
|
||||||
|
mActiveLayer( 0 ), mFeatureNumber( 0 ), mCurrentMouseAzimut( 0.0 ), mCurrentRotationFeature( 0.0 ), mRotating( false ), mRotationItem( 0 )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMapToolRotatePointSymbols::~QgsMapToolRotatePointSymbols()
|
||||||
|
{
|
||||||
|
delete mRotationItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsMapToolRotatePointSymbols::layerIsRotatable( QgsMapLayer* ml )
|
||||||
|
{
|
||||||
|
if ( !ml )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//a vector layer
|
||||||
|
QgsVectorLayer* vLayer = dynamic_cast<QgsVectorLayer*>( ml );
|
||||||
|
if ( !vLayer )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//does it have point or multipoint type?
|
||||||
|
if ( vLayer->geometryType() != QGis::Point )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//does it have a least one rotation attribute?
|
||||||
|
QList<int> rotationAttributes;
|
||||||
|
layerRotationAttributes( vLayer, rotationAttributes );
|
||||||
|
if ( rotationAttributes.size() < 1 )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMapToolRotatePointSymbols::canvasPressEvent( QMouseEvent * e )
|
||||||
|
{
|
||||||
|
if ( !mCanvas )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mActiveLayer = currentVectorLayer();
|
||||||
|
if ( !mActiveLayer )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( mActiveLayer->geometryType() != QGis::Point || !mActiveLayer->isEditable() )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//find the closest feature to the pressed position
|
||||||
|
QgsMapCanvasSnapper canvasSnapper( mCanvas );
|
||||||
|
QList<QgsSnappingResult> snapResults;
|
||||||
|
if ( canvasSnapper.snapToCurrentLayer( e->pos(), snapResults, QgsSnapper::SnapToVertex, -1 ) != 0 || snapResults.size() < 1 )
|
||||||
|
{
|
||||||
|
QMessageBox::critical( 0, tr( "No point feature" ), tr( "No point feature was detected at the clicked position. Please click closer to the feature or enhance the search tolerance under Settings->Options->Digitizing->Serch radius for vertex edits" ) );
|
||||||
|
return; //error during snapping
|
||||||
|
}
|
||||||
|
|
||||||
|
mFeatureNumber = snapResults.at( 0 ).snappedAtGeometry;
|
||||||
|
|
||||||
|
//get list with renderer rotation attributes
|
||||||
|
if ( layerRotationAttributes( mActiveLayer, mCurrentRotationAttributes ) != 0 )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( mCurrentRotationAttributes.size() < 1 )
|
||||||
|
{
|
||||||
|
QMessageBox::critical( 0, tr( "No rotation Attributes" ), tr( "The active point layer does not have a rotation attribute" ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSnappedPoint = toCanvasCoordinates( snapResults.at( 0 ).snappedVertex );
|
||||||
|
|
||||||
|
//find out initial arrow direction
|
||||||
|
QgsFeature pointFeature;
|
||||||
|
if ( !mActiveLayer->featureAtId( mFeatureNumber, pointFeature, false, true ) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const QgsAttributeMap pointFeatureAttributes = pointFeature.attributeMap();
|
||||||
|
const QgsAttributeMap::const_iterator attIt = pointFeatureAttributes.find( mCurrentRotationAttributes.at( 0 ) );
|
||||||
|
if ( attIt == pointFeatureAttributes.constEnd() )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCurrentRotationFeature = attIt.value().toDouble();
|
||||||
|
createPixmapItem();
|
||||||
|
if ( mRotationItem )
|
||||||
|
{
|
||||||
|
mRotationItem->setPointLocation( snapResults.at( 0 ).snappedVertex );
|
||||||
|
}
|
||||||
|
mCurrentMouseAzimut = calculateAzimut( e->pos() );
|
||||||
|
setPixmapItemRotation( mCurrentMouseAzimut );
|
||||||
|
mRotating = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMapToolRotatePointSymbols::canvasMoveEvent( QMouseEvent * e )
|
||||||
|
{
|
||||||
|
if ( !mRotating )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double azimut = calculateAzimut( e->pos() );
|
||||||
|
double azimutDiff = azimut - mCurrentMouseAzimut;
|
||||||
|
|
||||||
|
//assign new feature rotation, making sure to respect the 0 - 360 degree range
|
||||||
|
mCurrentRotationFeature += azimutDiff;
|
||||||
|
if ( mCurrentRotationFeature < 0 )
|
||||||
|
{
|
||||||
|
mCurrentRotationFeature = 360 - mCurrentRotationFeature;
|
||||||
|
}
|
||||||
|
else if ( mCurrentRotationFeature >= 360 )
|
||||||
|
{
|
||||||
|
mCurrentRotationFeature -= 360;
|
||||||
|
}
|
||||||
|
mCurrentMouseAzimut = azimut;
|
||||||
|
if ( mCurrentMouseAzimut < 0 )
|
||||||
|
{
|
||||||
|
mCurrentMouseAzimut = 360 - mCurrentMouseAzimut;
|
||||||
|
}
|
||||||
|
else if ( mCurrentMouseAzimut >= 360 )
|
||||||
|
{
|
||||||
|
mCurrentMouseAzimut -= 360;
|
||||||
|
}
|
||||||
|
setPixmapItemRotation( mCurrentRotationFeature );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMapToolRotatePointSymbols::canvasReleaseEvent( QMouseEvent * e )
|
||||||
|
{
|
||||||
|
if ( mRotating && mActiveLayer )
|
||||||
|
{
|
||||||
|
mActiveLayer->beginEditCommand( tr( "Rotate symbol" ) );
|
||||||
|
bool rotateSuccess = true;
|
||||||
|
|
||||||
|
//write mCurrentRotationFeature to all rotation attributes of feature (mFeatureNumber)
|
||||||
|
QList<int>::const_iterator it = mCurrentRotationAttributes.constBegin();
|
||||||
|
for ( ; it != mCurrentRotationAttributes.constEnd(); ++it )
|
||||||
|
{
|
||||||
|
if ( !mActiveLayer->changeAttributeValue( mFeatureNumber, *it, mCurrentRotationFeature, true ) )
|
||||||
|
{
|
||||||
|
rotateSuccess = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( rotateSuccess )
|
||||||
|
{
|
||||||
|
mActiveLayer->endEditCommand();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mActiveLayer->destroyEditCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mRotating = false;
|
||||||
|
delete mRotationItem;
|
||||||
|
mRotationItem = 0;
|
||||||
|
mCanvas->refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsMapToolRotatePointSymbols::layerRotationAttributes( const QgsVectorLayer* vl, QList<int>& attList )
|
||||||
|
{
|
||||||
|
attList.clear();
|
||||||
|
if ( !vl )
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get renderer
|
||||||
|
const QgsRenderer* layerRenderer = vl->renderer();
|
||||||
|
if ( !layerRenderer )
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get renderer symbols
|
||||||
|
const QList<QgsSymbol*> rendererSymbols = layerRenderer->symbols();
|
||||||
|
int currentRotationAttribute;
|
||||||
|
|
||||||
|
QList<QgsSymbol*>::const_iterator symbolIt = rendererSymbols.constBegin();
|
||||||
|
for ( ; symbolIt != rendererSymbols.constEnd(); ++symbolIt )
|
||||||
|
{
|
||||||
|
currentRotationAttribute = ( *symbolIt )->rotationClassificationField();
|
||||||
|
if ( currentRotationAttribute >= 0 )
|
||||||
|
{
|
||||||
|
attList.push_back( currentRotationAttribute );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double QgsMapToolRotatePointSymbols::calculateAzimut( const QPoint& mousePos )
|
||||||
|
{
|
||||||
|
int dx = mousePos.x() - mSnappedPoint.x();
|
||||||
|
int dy = mousePos.y() - mSnappedPoint.y();
|
||||||
|
return 180 - atan2( dx, dy ) * 180.0 / M_PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMapToolRotatePointSymbols::createPixmapItem()
|
||||||
|
{
|
||||||
|
delete mRotationItem;
|
||||||
|
mRotationItem = new QgsPointRotationItem( mCanvas );
|
||||||
|
mRotationItem->setSymbol( QgsApplication::defaultThemePath() + "mActionArrowUp.png" );
|
||||||
|
mCanvas->scene()->addItem( mRotationItem );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMapToolRotatePointSymbols::setPixmapItemRotation( double rotation )
|
||||||
|
{
|
||||||
|
mRotationItem->setSymbolRotation( rotation );
|
||||||
|
mRotationItem->update();
|
||||||
|
}
|
||||||
|
|
68
src/app/qgsmaptoolrotatepointsymbols.h
Normal file
68
src/app/qgsmaptoolrotatepointsymbols.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmaptoolrotatepointsymbols.h
|
||||||
|
---------------------
|
||||||
|
begin : September 2009
|
||||||
|
copyright : (C) 2009 by Marco Hugentobler
|
||||||
|
email : marco at hugis dot net
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QGSMAPTOOLROTATEPOINTSYMBOLS_H
|
||||||
|
#define QGSMAPTOOLROTATEPOINTSYMBOLS_H
|
||||||
|
|
||||||
|
#include "qgsmaptooledit.h"
|
||||||
|
|
||||||
|
class QgsPointRotationItem;
|
||||||
|
|
||||||
|
/**A class that allows to interactively manipulate the value of the rotation field(s) for point layers*/
|
||||||
|
class QgsMapToolRotatePointSymbols: public QgsMapToolEdit
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QgsMapToolRotatePointSymbols( QgsMapCanvas* canvas );
|
||||||
|
~QgsMapToolRotatePointSymbols();
|
||||||
|
|
||||||
|
void canvasPressEvent( QMouseEvent * e );
|
||||||
|
void canvasMoveEvent( QMouseEvent * e );
|
||||||
|
void canvasReleaseEvent( QMouseEvent * e );
|
||||||
|
|
||||||
|
bool isEditTool() {return true;}
|
||||||
|
|
||||||
|
/**Returns true if the symbols of a maplayer can be rotated. This means the layer \
|
||||||
|
is a vector layer, has type point or multipoint and has at least one rotation attribute in the renderer*/
|
||||||
|
static bool layerIsRotatable( QgsMapLayer* ml );
|
||||||
|
|
||||||
|
private:
|
||||||
|
QgsVectorLayer* mActiveLayer;
|
||||||
|
int mFeatureNumber;
|
||||||
|
/**Last azimut between mouse and edited point*/
|
||||||
|
double mCurrentMouseAzimut;
|
||||||
|
/**Last feature rotation*/
|
||||||
|
double mCurrentRotationFeature;
|
||||||
|
bool mRotating;
|
||||||
|
QList<int> mCurrentRotationAttributes;
|
||||||
|
/**Screen coordinate of the snaped feature*/
|
||||||
|
QPoint mSnappedPoint;
|
||||||
|
/**Item that displays rotation during mouse move*/
|
||||||
|
QgsPointRotationItem* mRotationItem;
|
||||||
|
|
||||||
|
/**Finds out the rotation attributes of mActiveLayers
|
||||||
|
@param vl the point vector layer
|
||||||
|
@param attList out: the list containing the rotation indices
|
||||||
|
@return 0 in case of success*/
|
||||||
|
static int layerRotationAttributes( const QgsVectorLayer* vl, QList<int>& attList );
|
||||||
|
void drawArrow( double azimut ) const;
|
||||||
|
/**Calculates the azimut between mousePos and mSnappedPoint*/
|
||||||
|
double calculateAzimut( const QPoint& mousePos );
|
||||||
|
/**Create item that shows rotation to the user*/
|
||||||
|
void createPixmapItem();
|
||||||
|
/**Sets the rotation of the pixmap item*/
|
||||||
|
void setPixmapItemRotation( double rotation );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QGSMAPTOOLROTATEPOINTSYMBOLS_H
|
97
src/app/qgspointrotationitem.cpp
Normal file
97
src/app/qgspointrotationitem.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgspointrotationitem.cpp
|
||||||
|
------------------------
|
||||||
|
begin : September 2009
|
||||||
|
copyright : (C) 2009 by Marco Hugentobler
|
||||||
|
email : marco at hugis dot net
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "qgspointrotationitem.h"
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
#ifndef Q_OS_MACX
|
||||||
|
#include <cmath>
|
||||||
|
#else
|
||||||
|
#include <math.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QgsPointRotationItem::QgsPointRotationItem( QgsMapCanvas* canvas ): QgsMapCanvasItem( canvas ), mRotation( 0.0 )
|
||||||
|
{
|
||||||
|
//setup font
|
||||||
|
mFont.setPointSize( 12 );
|
||||||
|
mFont.setBold( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsPointRotationItem::QgsPointRotationItem(): QgsMapCanvasItem( 0 ), mRotation( 0.0 )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsPointRotationItem::~QgsPointRotationItem()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsPointRotationItem::paint( QPainter * painter )
|
||||||
|
{
|
||||||
|
if ( !painter )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
painter->save();
|
||||||
|
|
||||||
|
//do a bit of trigonometry to find out how to transform a rotated item such that the center point is at the point feature
|
||||||
|
double x = 0;
|
||||||
|
double y = 0;
|
||||||
|
double h, dAngel;
|
||||||
|
if ( mPixmap.width() > 0 && mPixmap.height() > 0 )
|
||||||
|
{
|
||||||
|
h = sqrt( mPixmap.width() * mPixmap.width() + mPixmap.height() * mPixmap.height() ) / 2; //the half of the item diagonal
|
||||||
|
dAngel = acos( mPixmap.width() / ( h * 2 ) ) * 180 / M_PI; //the diagonal angel of the original rect
|
||||||
|
x = h * cos(( mRotation - dAngel ) * M_PI / 180 );
|
||||||
|
y = h * sin(( mRotation - dAngel ) * M_PI / 180 );
|
||||||
|
}
|
||||||
|
|
||||||
|
//painter->translate(-mPixmap.width() / 2.0, -mPixmap.width() / 2.0);
|
||||||
|
painter->rotate( mRotation );
|
||||||
|
painter->translate( x - mPixmap.width() / 2.0, -y - mPixmap.height() / 2.0 );
|
||||||
|
painter->drawPixmap( 0, 0, mPixmap );
|
||||||
|
|
||||||
|
//draw numeric value beside the symbol
|
||||||
|
painter->restore();
|
||||||
|
QFontMetricsF fm( mFont );
|
||||||
|
painter->fillRect( mPixmap.width(), 0, mItemSize.width() - mPixmap.width(), mItemSize.height(), QColor( Qt::white ) );
|
||||||
|
painter->setFont( mFont );
|
||||||
|
painter->drawText( mPixmap.width(), mPixmap.height() / 2.0 + fm.height() / 2.0, QString::number( mRotation, 'f', 2 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsPointRotationItem::setPointLocation( const QgsPoint& p )
|
||||||
|
{
|
||||||
|
QPointF transformedPoint = toCanvasCoordinates( p );
|
||||||
|
setPos( transformedPoint.x() - mPixmap.width() / 2.0, transformedPoint.y() - mPixmap.height() / 2.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsPointRotationItem::setSymbol( const QString& symbolPath )
|
||||||
|
{
|
||||||
|
mPixmap = QPixmap( symbolPath );
|
||||||
|
QFontMetricsF fm( mFont );
|
||||||
|
mItemSize.setWidth( mPixmap.width() + fm.width( "360.99" ) );
|
||||||
|
double pixmapHeight = mPixmap.height();
|
||||||
|
double fontHeight = fm.height();
|
||||||
|
if ( pixmapHeight >= fontHeight )
|
||||||
|
{
|
||||||
|
mItemSize.setHeight( mPixmap.height() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mItemSize.setHeight( fm.height() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
51
src/app/qgspointrotationitem.h
Normal file
51
src/app/qgspointrotationitem.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgspointrotationitem.h
|
||||||
|
----------------------
|
||||||
|
begin : September 2009
|
||||||
|
copyright : (C) 2009 by Marco Hugentobler
|
||||||
|
email : marco at hugis dot net
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QGSPOINTROTATIONITEM_H
|
||||||
|
#define QGSPOINTROTATIONITEM_H
|
||||||
|
|
||||||
|
#include "qgsmapcanvasitem.h"
|
||||||
|
#include <QFontMetricsF>
|
||||||
|
#include <QPixmap>
|
||||||
|
|
||||||
|
/**An item that shows a rotated point symbol (e.g. arrow) centered to a map location together with a text displaying the rotation value*/
|
||||||
|
class QgsPointRotationItem: public QgsMapCanvasItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QgsPointRotationItem( QgsMapCanvas* canvas );
|
||||||
|
~QgsPointRotationItem();
|
||||||
|
|
||||||
|
void paint( QPainter * painter );
|
||||||
|
|
||||||
|
/**Sets the center point of the rotation symbol (in map coordinates)*/
|
||||||
|
void setPointLocation( const QgsPoint& p );
|
||||||
|
|
||||||
|
/**Sets the rotation of the symbol and displays the new rotation number. \
|
||||||
|
Units are degrees, starting from north direction, clockwise direction*/
|
||||||
|
void setSymbolRotation( double r ) {mRotation = r;}
|
||||||
|
|
||||||
|
/**Sets a symbol from image file*/
|
||||||
|
void setSymbol( const QString& symbolPath );
|
||||||
|
|
||||||
|
private:
|
||||||
|
QgsPointRotationItem();
|
||||||
|
/**Font to display the numerical rotation values*/
|
||||||
|
QFont mFont;
|
||||||
|
/**Symboll pixmap*/
|
||||||
|
QPixmap mPixmap;
|
||||||
|
double mRotation;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QGSPOINTROTATIONITEM_H
|
Loading…
x
Reference in New Issue
Block a user