Skip to content
Permalink
Browse files
Patch #2622 by mhugent, enabling visualization of transform residuals…
… as arrow.

git-svn-id: http://svn.osgeo.org/qgis/trunk@13229 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mmassing committed Apr 3, 2010
1 parent f41489a commit 9b1e0b90a21df1d55977335ef6da2473b57b8d44
@@ -15,27 +15,40 @@
/* $Id$ */

#include "qgsgcpcanvasitem.h"
#include "qgsgeorefdatapoint.h"
#include "qgsmaplayerregistry.h"
#include "qgsmaprenderer.h"
#include "qgsrasterlayer.h"

QgsGCPCanvasItem::QgsGCPCanvasItem( QgsMapCanvas* mapCanvas, const QgsPoint& rasterCoords,
const QgsPoint& worldCoords, bool isGCPSource )
: QgsMapCanvasItem( mapCanvas )
QgsGCPCanvasItem::QgsGCPCanvasItem( QgsMapCanvas* mapCanvas, const QgsGeorefDataPoint* dataPoint, bool isGCPSource )
: QgsMapCanvasItem( mapCanvas ), mDataPoint( dataPoint )
, mPointBrush( Qt::red )
, mLabelBrush( Qt::yellow )
, mRasterCoords( rasterCoords )
, mWorldCoords( worldCoords )
, mId( -1 )
, mIsGCPSource( isGCPSource )
, mEnabled( true )
{
setFlags( QGraphicsItem::ItemIsMovable );
mResidualPen.setColor( QColor( 255, 0, 0 ) );
mResidualPen.setWidthF( 2.0 );

updatePosition();
}

void QgsGCPCanvasItem::paint( QPainter* p )
{
p->setRenderHint( QPainter::Antialiasing );
p->setOpacity( mEnabled ? 1.0 : 0.3 );

bool enabled = true;
QgsPoint worldCoords;
int id = -1;

if ( mDataPoint )
{
enabled = mDataPoint->isEnabled();
worldCoords = mDataPoint->mapCoords();
id = mDataPoint->id();
}

p->setOpacity( enabled ? 1.0 : 0.3 );

// draw the point
p->setPen( Qt::black );
@@ -46,8 +59,8 @@ void QgsGCPCanvasItem::paint( QPainter* p )
bool showIDs = s.value( "/Plugin-GeoReferencer/Config/ShowId" ).toBool();
if ( !showIDs && mIsGCPSource )
{
QString msg = QString( "X %1\nY %2" ).arg( QString::number( mWorldCoords.x(), 'f' ) ).
arg( QString::number( mWorldCoords.y(), 'f' ) );
QString msg = QString( "X %1\nY %2" ).arg( QString::number( worldCoords.x(), 'f' ) ).
arg( QString::number( worldCoords.y(), 'f' ) );
p->setFont( QFont( "helvetica", 9 ) );
QRect textBounds = p->boundingRect( 6, 6, 10, 10, Qt::AlignLeft, msg );
p->setBrush( mLabelBrush );
@@ -58,20 +71,52 @@ void QgsGCPCanvasItem::paint( QPainter* p )
else if ( showIDs )
{
p->setFont( QFont( "helvetica", 12 ) );
QString msg = QString::number( mId );
QString msg = QString::number( id );
p->setBrush( mLabelBrush );
p->drawRect( 5, 4, p->fontMetrics().width( msg ) + 2, 14 );
p->drawText( 6, 16, msg );
QFontMetrics fm = p->fontMetrics();
mTextBounds = QSize( fm.width( msg ) + 4, fm.height() + 4 );
}
// else
// mTextBounds = QSizeF(0, 0);

drawResidualArrow( p );
}

QRectF QgsGCPCanvasItem::boundingRect() const
{
return QRectF( -2, -2, mTextBounds.width() + 6, mTextBounds.height() + 6 );
double residualLeft, residualRight, residualTop, residualBottom;

QPointF residual;
if ( mDataPoint )
{
residual = mDataPoint->residual();
}
double rf = residualToScreenFactor();

if ( residual.x() > 0 )
{
residualRight = residual.x() * rf + mResidualPen.widthF();
residualLeft = -mResidualPen.widthF();
}
else
{
residualLeft = residual.x() * rf - mResidualPen.widthF();
residualRight = mResidualPen.widthF();
}
if ( residual.y() > 0 )
{
residualBottom = residual.y() * rf + mResidualPen.widthF();
residualTop = -mResidualPen.widthF();
}
else
{
residualBottom = mResidualPen.widthF();
residualTop = residual.y() * rf - mResidualPen.widthF();
}

QRectF residualArrowRect( QPointF( residualLeft, residualTop ), QPointF( residualRight, residualBottom ) );
QRectF markerRect( -2, -2, mTextBounds.width() + 6, mTextBounds.height() + 6 );
return residualArrowRect.united( markerRect );
}

QPainterPath QgsGCPCanvasItem::shape() const
@@ -83,31 +128,63 @@ QPainterPath QgsGCPCanvasItem::shape() const
return p;
}

void QgsGCPCanvasItem::setEnabled( bool enabled )
void QgsGCPCanvasItem::updatePosition()
{
mEnabled = enabled;
mPointBrush = enabled ? QBrush( Qt::red ) : QBrush( Qt::gray );
mLabelBrush = enabled ? QBrush( Qt::yellow ) : QBrush( Qt::gray );
update();
}
if ( !mDataPoint )
{
return;
}

void QgsGCPCanvasItem::setRasterCoords( QgsPoint p )
{
mRasterCoords = p;
setPos( toCanvasCoordinates( mIsGCPSource ? mDataPoint->pixelCoords() : mDataPoint->mapCoords() ) );
}

void QgsGCPCanvasItem::setWorldCoords( QgsPoint p )
void QgsGCPCanvasItem::drawResidualArrow( QPainter* p )
{
mWorldCoords = p;
if ( !mDataPoint || !mIsGCPSource )
{
return;
}

QPointF residual = mDataPoint->residual();

double rf = residualToScreenFactor();
p->setPen( mResidualPen );
p->drawLine( QPointF( 0, 0 ), QPointF( residual.rx() * rf, residual.ry() * rf ) );

}

void QgsGCPCanvasItem::setId( int id )
double QgsGCPCanvasItem::residualToScreenFactor() const
{
mId = id;
update();
if ( !mMapCanvas )
{
return 1;
}

double mapUnitsPerScreenPixel = mMapCanvas->mapUnitsPerPixel();
double mapUnitsPerRasterPixel = 1.0;

if ( mMapCanvas->mapRenderer() )
{
QStringList canvasLayers = mMapCanvas->mapRenderer()->layerSet();
if ( canvasLayers.size() > 0 )
{
QString layerId = canvasLayers.at( 0 );
QgsMapLayer* mapLayer = QgsMapLayerRegistry::instance()->mapLayer( layerId );
if ( mapLayer )
{
QgsRasterLayer* rasterLayer = dynamic_cast<QgsRasterLayer*>( mapLayer );
if ( rasterLayer )
{
mapUnitsPerRasterPixel = rasterLayer->rasterUnitsPerPixel();
}
}
}
}

return 1.0 / ( mapUnitsPerScreenPixel * mapUnitsPerRasterPixel );
}

void QgsGCPCanvasItem::updatePosition()
void QgsGCPCanvasItem::checkBoundingRectChange()
{
setPos( toCanvasCoordinates( mIsGCPSource ? mRasterCoords : mWorldCoords ) );
prepareGeometryChange();
}
@@ -20,11 +20,12 @@
#include "qgsmapcanvas.h"
#include "qgsmapcanvasitem.h"

class QgsGeorefDataPoint;

class QgsGCPCanvasItem : public QgsMapCanvasItem
{
public:
QgsGCPCanvasItem( QgsMapCanvas* mapCanvas, const QgsPoint& rasterCoords,
const QgsPoint& worldCoords, bool isGCPSource/* = true*/ );
QgsGCPCanvasItem( QgsMapCanvas* mapCanvas, const QgsGeorefDataPoint* dataPoint, bool isGCPSource/* = true*/ );

//! draws point information
void paint( QPainter* p );
@@ -34,26 +35,23 @@ class QgsGCPCanvasItem : public QgsMapCanvasItem

QPainterPath shape() const;

void setEnabled( bool enabled );

void setRasterCoords( QgsPoint p );
void setWorldCoords( QgsPoint p );

int id() { return mId; }
void setId( int id );

void updatePosition();

/**Calls prepareGeometryChange()*/
void checkBoundingRectChange();

private:

const QgsGeorefDataPoint* mDataPoint;
QSizeF mTextBounds;
QBrush mPointBrush;
QBrush mLabelBrush;
QgsPoint mRasterCoords;
QgsPoint mWorldCoords;

int mId;
bool mIsGCPSource;
bool mEnabled;
QPen mResidualPen;

void drawResidualArrow( QPainter* p );
/**Calculates scale factor for residual display*/
double residualToScreenFactor() const;
};

#endif // QGSGCPCANVASITEM_H
@@ -124,7 +124,7 @@ void QgsGCPListModel::updateModel()
setItem( i, j++, QGSSTANDARDITEM( p->mapCoords().x() ) /*create_item<double>( p->mapCoords().x() )*/ );
setItem( i, j++, QGSSTANDARDITEM( p->mapCoords().y() ) /*create_item<double>( p->mapCoords().y() )*/ );

double residual = -1.f;
double residual;
double dX, dY;
// Calculate residual if transform is available and up-to-date
if ( mGeorefTransform && bTransformUpdated && mGeorefTransform->parametersInitialized() )
@@ -135,18 +135,24 @@ void QgsGCPListModel::updateModel()
// As transforms of order >=2 are not invertible, we are only
// interested in the residual in this direction
mGeorefTransform->transformWorldToRaster( p->mapCoords(), dst );
dX = ( dst.x() - p->pixelCoords().x() );
dY = ( dst.y() - p->pixelCoords().y() );
dX = ( dst.x() - p->pixelCoords().x() );
dY = -( dst.y() - p->pixelCoords().y() );
residual = sqrt( dX * dX + dY * dY );
}
else
{
dX = dY = residual = 0;
}

if ( p )
{
p->setResidual( QPointF( dX, dY ) );
}

if ( residual >= 0.f )
{
setItem( i, j++, QGSSTANDARDITEM( dX ) /*create_item<double>(dX)*/ );
setItem( i, j++, QGSSTANDARDITEM( -dY ) /*create_item<double>(-dY)*/ );
setItem( i, j++, QGSSTANDARDITEM( dY ) /*create_item<double>(-dY)*/);
setItem( i, j++, QGSSTANDARDITEM( residual ) /*create_item<double>(residual)*/ );
}
else
@@ -30,8 +30,8 @@ QgsGeorefDataPoint::QgsGeorefDataPoint( QgsMapCanvas* srcCanvas, QgsMapCanvas *d
, mId( -1 )
, mEnabled( enable )
{
mGCPSourceItem = new QgsGCPCanvasItem( srcCanvas, pixelCoords, mapCoords, true );
mGCPDestinationItem = new QgsGCPCanvasItem( dstCanvas, pixelCoords, mapCoords, false );
mGCPSourceItem = new QgsGCPCanvasItem( srcCanvas, this, true );
mGCPDestinationItem = new QgsGCPCanvasItem( dstCanvas, this, false );

mGCPSourceItem->setEnabled( enable );
mGCPDestinationItem->setEnabled( enable );
@@ -58,36 +58,66 @@ QgsGeorefDataPoint::~QgsGeorefDataPoint()
void QgsGeorefDataPoint::setPixelCoords( const QgsPoint &p )
{
mPixelCoords = p;
mGCPSourceItem->setRasterCoords( p );
mGCPDestinationItem->setRasterCoords( p );
mGCPSourceItem->update();
mGCPDestinationItem->update();
}

void QgsGeorefDataPoint::setMapCoords( const QgsPoint &p )
{
mMapCoords = p;
mGCPSourceItem->setWorldCoords( p );
mGCPDestinationItem->setWorldCoords( p );
if ( mGCPSourceItem )
{
mGCPSourceItem->update();
}
if ( mGCPDestinationItem )
{
mGCPDestinationItem->update();
}
}

void QgsGeorefDataPoint::setEnabled( bool enabled )
{
mGCPSourceItem->setEnabled( enabled );
mEnabled = enabled;
if ( mGCPSourceItem )
{
mGCPSourceItem->update();
}
}

void QgsGeorefDataPoint::setId( int id )
{
mId = id;
mGCPSourceItem->setId( id );
mGCPDestinationItem->setId( id );
if ( mGCPSourceItem )
{
mGCPSourceItem->update();
}
if ( mGCPDestinationItem )
{
mGCPDestinationItem->update();
}
}

void QgsGeorefDataPoint::setResidual( const QPointF& r )
{
mResidual = r;
if ( mGCPSourceItem )
{
mGCPSourceItem->checkBoundingRectChange();
}
}

void QgsGeorefDataPoint::updateCoords()
{
mGCPSourceItem->updatePosition();
mGCPDestinationItem->updatePosition();
mGCPSourceItem->update();
mGCPDestinationItem->update();
if ( mGCPSourceItem )
{
mGCPSourceItem->updatePosition();
mGCPSourceItem->update();
}
if ( mGCPDestinationItem )
{
mGCPDestinationItem->updatePosition();
mGCPDestinationItem->update();
}
}

bool QgsGeorefDataPoint::contains( const QPoint &p )
@@ -39,14 +39,17 @@ class QgsGeorefDataPoint : public QObject
bool isEnabled() const { return mEnabled; };
void setEnabled( bool enabled );

int id() { return mId; }
int id() const { return mId; }
void setId( int id );

bool contains( const QPoint &p );

QgsMapCanvas *srcCanvas() const { return mSrcCanvas; }
QgsMapCanvas *dstCanvas() const { return mDstCanvas; }

QPointF residual() const { return mResidual; }
void setResidual( const QPointF& r );

public slots:
void moveTo( const QPoint & );
void updateCoords();
@@ -61,4 +64,5 @@ class QgsGeorefDataPoint : public QObject

int mId;
bool mEnabled;
QPointF mResidual;
};

0 comments on commit 9b1e0b9

Please sign in to comment.