mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-16 00:05:45 -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
|
||||
qgsmaptoolnodetool.cpp
|
||||
qgsmaptoolreshape.cpp
|
||||
qgsmaptoolrotatepointsymbols.cpp
|
||||
qgsmaptoolselect.cpp
|
||||
qgsmaptoolsimplify.cpp
|
||||
qgsmaptoolsplitfeatures.cpp
|
||||
@ -52,6 +53,7 @@ SET(QGIS_APP_SRCS
|
||||
qgsogrsublayersdialog.cpp
|
||||
qgsoptions.cpp
|
||||
qgspastetransformations.cpp
|
||||
qgspointrotationitem.cpp
|
||||
qgspluginitem.cpp
|
||||
qgspluginmanager.cpp
|
||||
qgspluginmetadata.cpp
|
||||
|
@ -172,6 +172,7 @@
|
||||
#include "qgsmaptoolpan.h"
|
||||
#include "qgsmaptoolselect.h"
|
||||
#include "qgsmaptoolreshape.h"
|
||||
#include "qgsmaptoolrotatepointsymbols.h"
|
||||
#include "qgsmaptoolsplitfeatures.h"
|
||||
#include "qgsmaptoolvertexedit.h"
|
||||
#include "qgsmaptoolzoom.h"
|
||||
@ -740,6 +741,12 @@ void QgisApp::createActions()
|
||||
connect( mActionNodeTool, SIGNAL( triggered() ), this, SLOT( nodeTool() ) );
|
||||
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
|
||||
|
||||
mActionPan = new QAction( getThemeIcon( "mActionPan.png" ), tr( "Pan Map" ), this );
|
||||
@ -1094,7 +1101,8 @@ void QgisApp::createActionGroups()
|
||||
mMapToolGroup->addAction( mActionMergeFeatures );
|
||||
mActionNodeTool->setCheckable( true );
|
||||
mMapToolGroup->addAction( mActionNodeTool );
|
||||
|
||||
mActionRotatePointSymbols->setCheckable( true );
|
||||
mMapToolGroup->addAction( mActionRotatePointSymbols );
|
||||
}
|
||||
|
||||
void QgisApp::createMenus()
|
||||
@ -1189,6 +1197,7 @@ void QgisApp::createMenus()
|
||||
mEditMenu->addAction( mActionSplitFeatures );
|
||||
mEditMenu->addAction( mActionMergeFeatures );
|
||||
mEditMenu->addAction( mActionNodeTool );
|
||||
mEditMenu->addAction( mActionRotatePointSymbols );
|
||||
|
||||
if ( layout == QDialogButtonBox::GnomeLayout || layout == QDialogButtonBox::MacLayout )
|
||||
{
|
||||
@ -1398,6 +1407,7 @@ void QgisApp::createToolBars()
|
||||
mAdvancedDigitizeToolBar->addAction( mActionSplitFeatures );
|
||||
mAdvancedDigitizeToolBar->addAction( mActionMergeFeatures );
|
||||
mAdvancedDigitizeToolBar->addAction( mActionNodeTool );
|
||||
mAdvancedDigitizeToolBar->addAction( mActionRotatePointSymbols );
|
||||
mToolbarMenu->addAction( mAdvancedDigitizeToolBar->toggleViewAction() );
|
||||
|
||||
|
||||
@ -1788,6 +1798,8 @@ void QgisApp::createCanvas()
|
||||
mMapTools.mDeletePart->setAction( mActionDeletePart );
|
||||
mMapTools.mNodeTool = new QgsMapToolNodeTool( mMapCanvas );
|
||||
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
|
||||
mNonEditMapTool = mMapTools.mPan;
|
||||
}
|
||||
@ -4298,6 +4310,11 @@ void QgisApp::nodeTool()
|
||||
mMapCanvas->setMapTool( mMapTools.mNodeTool );
|
||||
}
|
||||
|
||||
void QgisApp::rotatePointSymbols()
|
||||
{
|
||||
mMapCanvas->setMapTool( mMapTools.mRotatePointSymbolsTool );
|
||||
}
|
||||
|
||||
void QgisApp::splitFeatures()
|
||||
{
|
||||
mMapCanvas->setMapTool( mMapTools.mSplitFeatures );
|
||||
@ -5639,11 +5656,19 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
|
||||
mActionSplitFeatures->setEnabled( false );
|
||||
mActionSimplifyFeature->setEnabled( false );
|
||||
mActionDeleteRing->setEnabled( false );
|
||||
mActionRotatePointSymbols->setEnabled( false );
|
||||
|
||||
if ( vlayer->isEditable() && dprovider->capabilities() & QgsVectorDataProvider::ChangeGeometries )
|
||||
{
|
||||
mActionMoveVertex->setEnabled( true );
|
||||
}
|
||||
if ( vlayer->isEditable() && dprovider->capabilities() & QgsVectorDataProvider::ChangeAttributeValues )
|
||||
{
|
||||
if ( QgsMapToolRotatePointSymbols::layerIsRotatable( vlayer ) )
|
||||
{
|
||||
mActionRotatePointSymbols->setEnabled( true );
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if ( vlayer->geometryType() == QGis::Line )
|
||||
@ -5752,6 +5777,9 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
|
||||
mActionCopyFeatures->setEnabled( false );
|
||||
mActionCutFeatures->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
|
||||
//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();
|
||||
//! provides operations with nodes
|
||||
void nodeTool();
|
||||
//! activates the rotate points tool
|
||||
void rotatePointSymbols();
|
||||
|
||||
//! activates the selection tool
|
||||
void select();
|
||||
@ -742,6 +744,7 @@ class QgisApp : public QMainWindow
|
||||
QAction *mActionDeletePart;
|
||||
QAction *mActionMergeFeatures;
|
||||
QAction *mActionNodeTool;
|
||||
QAction *mActionRotatePointSymbols;
|
||||
QAction *mActionEditSeparator3;
|
||||
|
||||
QAction *mActionPan;
|
||||
@ -864,6 +867,7 @@ class QgisApp : public QMainWindow
|
||||
QgsMapTool* mDeleteRing;
|
||||
QgsMapTool* mDeletePart;
|
||||
QgsMapTool* mNodeTool;
|
||||
QgsMapTool* mRotatePointSymbolsTool;
|
||||
} mMapTools;
|
||||
|
||||
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