Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[composer] Fix position of annotations in rotated maps
(AKA "stack some hacks on top of existing hacks")
  • Loading branch information
nyalldawson committed Jul 21, 2016
1 parent 12a2147 commit 72b53b9
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 10 deletions.
47 changes: 38 additions & 9 deletions src/core/composer/qgscomposermap.cpp
Expand Up @@ -20,6 +20,7 @@
#include "qgscomposermapoverview.h"
#include "qgscomposition.h"
#include "qgscomposerutils.h"
#include "qgscrscache.h"
#include "qgslogger.h"
#include "qgsmaprenderer.h"
#include "qgsmaprenderercustompainterjob.h"
Expand Down Expand Up @@ -2398,12 +2399,14 @@ void QgsComposerMap::drawCanvasItem( QGraphicsItem* item, QPainter* painter, con
QGraphicsItem* parent = item->parentItem();
if ( !parent )
{
// having no parent is a hack to indicate that annotation has a fixed position
QPointF mapPos = composerMapPosForItem( item );
itemX = mapPos.x();
itemY = mapPos.y();
}
else //place item relative to the parent item
{
// having a parent is a hack to indicate annotation has relative position
QPointF itemScenePos = item->scenePos();
QPointF parentScenePos = parent->scenePos();

Expand All @@ -2425,22 +2428,48 @@ void QgsComposerMap::drawCanvasItem( QGraphicsItem* item, QPainter* painter, con

QPointF QgsComposerMap::composerMapPosForItem( const QGraphicsItem* item ) const
{
if ( !item || !mMapCanvas )
{
if ( !item )
return QPointF( 0, 0 );
}

if ( currentMapExtent()->height() <= 0 || currentMapExtent()->width() <= 0 || mMapCanvas->width() <= 0 || mMapCanvas->height() <= 0 )
double mapX = 0.0;
double mapY = 0.0;
if ( item->parentItem() && !mMapCanvas )
{
// having a parentItem is a hack used to indicate annotation has relative position
return QPointF( 0, 0 );
}
else if ( item->parentItem() )
{
// TODO this is totally broken for rotated maps
if ( currentMapExtent()->height() <= 0 || currentMapExtent()->width() <= 0 || mMapCanvas->width() <= 0 || mMapCanvas->height() <= 0 )
{
return QPointF( 0, 0 );
}

QRectF graphicsSceneRect = mMapCanvas->sceneRect();
QPointF itemScenePos = item->scenePos();
QgsRectangle mapRendererExtent = mComposition->mapSettings().visibleExtent();

mapX = itemScenePos.x() / graphicsSceneRect.width() * mapRendererExtent.width() + mapRendererExtent.xMinimum();
mapY = mapRendererExtent.yMaximum() - itemScenePos.y() / graphicsSceneRect.height() * mapRendererExtent.height();
}
else
{
//fixed position, use a hack where the position is encoded in item's custom data
//(this whole annotation handling is a hack and needs to be rewritten)
mapX = item->data( 2 ).toDouble();
mapY = item->data( 3 ).toDouble();
long crsid = item->data( 4 ).toLongLong();

QRectF graphicsSceneRect = mMapCanvas->sceneRect();
QPointF itemScenePos = item->scenePos();
QgsRectangle mapRendererExtent = mComposition->mapSettings().visibleExtent();
if ( crsid != mComposition->mapSettings().destinationCrs().srsid() )
{
//need to reproject
QgsCoordinateTransform t( QgsCrsCache::instance()->crsBySrsId( crsid ), mComposition->mapSettings().destinationCrs() );
double z = 0.0;
t.transformInPlace( mapX, mapY, z );
}
}

double mapX = itemScenePos.x() / graphicsSceneRect.width() * mapRendererExtent.width() + mapRendererExtent.xMinimum();
double mapY = mapRendererExtent.yMaximum() - itemScenePos.y() / graphicsSceneRect.height() * mapRendererExtent.height();
return mapToItemCoords( QPointF( mapX, mapY ) );
}

Expand Down
20 changes: 19 additions & 1 deletion src/gui/qgsannotationitem.cpp
Expand Up @@ -53,13 +53,20 @@ void QgsAnnotationItem::setMarkerSymbol( QgsMarkerSymbolV2* symbol )
void QgsAnnotationItem::setMapPosition( const QgsPoint& pos )
{
mMapPosition = pos;
// use a hack to make position accessible to composer (in core, so can't directly access this class)
// TODO - fix this hacky mess with an interface class
setData( 2, mMapPosition.x() );
setData( 3, mMapPosition.y() );

setPos( toCanvasCoordinates( mMapPosition ) );
mMapPositionCrs = mMapCanvas->mapSettings().destinationCrs();
setMapPositionCrs( mMapCanvas->mapSettings().destinationCrs() );
}

void QgsAnnotationItem::setMapPositionCrs( const QgsCoordinateReferenceSystem& crs )
{
mMapPositionCrs = crs;
// use a hack to make crs accessible to composer
setData( 4, qlonglong( crs.srsid() ) );
}

void QgsAnnotationItem::setOffsetFromReferencePoint( QPointF offset )
Expand Down Expand Up @@ -98,6 +105,10 @@ void QgsAnnotationItem::updatePosition()
else
{
mMapPosition = toMapCoordinates( pos().toPoint() );
// use a hack to make position accessible to composer (in core, so can't directly access this class)
// TODO - fix this hacky mess with an interface class
setData( 2, mMapPosition.x() );
setData( 3, mMapPosition.y() );
}
}

Expand Down Expand Up @@ -444,8 +455,15 @@ void QgsAnnotationItem::_readXml( const QDomDocument& doc, const QDomElement& an
mapPos.setX( annotationElem.attribute( "mapPosX", "0" ).toDouble() );
mapPos.setY( annotationElem.attribute( "mapPosY", "0" ).toDouble() );
mMapPosition = mapPos;
setData( 2, mMapPosition.x() );
setData( 3, mMapPosition.y() );

if ( !mMapPositionCrs.readXml( annotationElem ) )
{
mMapPositionCrs = mMapCanvas->mapSettings().destinationCrs();
}
setMapPositionCrs( mMapPositionCrs );

mFrameBorderWidth = annotationElem.attribute( "frameBorderWidth", "0.5" ).toDouble();
mFrameColor.setNamedColor( annotationElem.attribute( "frameColor", "#000000" ) );
mFrameColor.setAlpha( annotationElem.attribute( "frameColorAlpha", "255" ).toInt() );
Expand Down

0 comments on commit 72b53b9

Please sign in to comment.