Skip to content

Commit 9b1e0b9

Browse files
author
mmassing
committed
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
1 parent f41489a commit 9b1e0b9

File tree

5 files changed

+178
-63
lines changed

5 files changed

+178
-63
lines changed

src/plugins/georeferencer/qgsgcpcanvasitem.cpp

+107-30
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,40 @@
1515
/* $Id$ */
1616

1717
#include "qgsgcpcanvasitem.h"
18+
#include "qgsgeorefdatapoint.h"
19+
#include "qgsmaplayerregistry.h"
20+
#include "qgsmaprenderer.h"
21+
#include "qgsrasterlayer.h"
1822

19-
QgsGCPCanvasItem::QgsGCPCanvasItem( QgsMapCanvas* mapCanvas, const QgsPoint& rasterCoords,
20-
const QgsPoint& worldCoords, bool isGCPSource )
21-
: QgsMapCanvasItem( mapCanvas )
23+
QgsGCPCanvasItem::QgsGCPCanvasItem( QgsMapCanvas* mapCanvas, const QgsGeorefDataPoint* dataPoint, bool isGCPSource )
24+
: QgsMapCanvasItem( mapCanvas ), mDataPoint( dataPoint )
2225
, mPointBrush( Qt::red )
2326
, mLabelBrush( Qt::yellow )
24-
, mRasterCoords( rasterCoords )
25-
, mWorldCoords( worldCoords )
26-
, mId( -1 )
2727
, mIsGCPSource( isGCPSource )
28-
, mEnabled( true )
2928
{
3029
setFlags( QGraphicsItem::ItemIsMovable );
30+
mResidualPen.setColor( QColor( 255, 0, 0 ) );
31+
mResidualPen.setWidthF( 2.0 );
3132

3233
updatePosition();
3334
}
3435

3536
void QgsGCPCanvasItem::paint( QPainter* p )
3637
{
3738
p->setRenderHint( QPainter::Antialiasing );
38-
p->setOpacity( mEnabled ? 1.0 : 0.3 );
39+
40+
bool enabled = true;
41+
QgsPoint worldCoords;
42+
int id = -1;
43+
44+
if ( mDataPoint )
45+
{
46+
enabled = mDataPoint->isEnabled();
47+
worldCoords = mDataPoint->mapCoords();
48+
id = mDataPoint->id();
49+
}
50+
51+
p->setOpacity( enabled ? 1.0 : 0.3 );
3952

4053
// draw the point
4154
p->setPen( Qt::black );
@@ -46,8 +59,8 @@ void QgsGCPCanvasItem::paint( QPainter* p )
4659
bool showIDs = s.value( "/Plugin-GeoReferencer/Config/ShowId" ).toBool();
4760
if ( !showIDs && mIsGCPSource )
4861
{
49-
QString msg = QString( "X %1\nY %2" ).arg( QString::number( mWorldCoords.x(), 'f' ) ).
50-
arg( QString::number( mWorldCoords.y(), 'f' ) );
62+
QString msg = QString( "X %1\nY %2" ).arg( QString::number( worldCoords.x(), 'f' ) ).
63+
arg( QString::number( worldCoords.y(), 'f' ) );
5164
p->setFont( QFont( "helvetica", 9 ) );
5265
QRect textBounds = p->boundingRect( 6, 6, 10, 10, Qt::AlignLeft, msg );
5366
p->setBrush( mLabelBrush );
@@ -58,20 +71,52 @@ void QgsGCPCanvasItem::paint( QPainter* p )
5871
else if ( showIDs )
5972
{
6073
p->setFont( QFont( "helvetica", 12 ) );
61-
QString msg = QString::number( mId );
74+
QString msg = QString::number( id );
6275
p->setBrush( mLabelBrush );
6376
p->drawRect( 5, 4, p->fontMetrics().width( msg ) + 2, 14 );
6477
p->drawText( 6, 16, msg );
6578
QFontMetrics fm = p->fontMetrics();
6679
mTextBounds = QSize( fm.width( msg ) + 4, fm.height() + 4 );
6780
}
68-
// else
69-
// mTextBounds = QSizeF(0, 0);
81+
82+
drawResidualArrow( p );
7083
}
7184

7285
QRectF QgsGCPCanvasItem::boundingRect() const
7386
{
74-
return QRectF( -2, -2, mTextBounds.width() + 6, mTextBounds.height() + 6 );
87+
double residualLeft, residualRight, residualTop, residualBottom;
88+
89+
QPointF residual;
90+
if ( mDataPoint )
91+
{
92+
residual = mDataPoint->residual();
93+
}
94+
double rf = residualToScreenFactor();
95+
96+
if ( residual.x() > 0 )
97+
{
98+
residualRight = residual.x() * rf + mResidualPen.widthF();
99+
residualLeft = -mResidualPen.widthF();
100+
}
101+
else
102+
{
103+
residualLeft = residual.x() * rf - mResidualPen.widthF();
104+
residualRight = mResidualPen.widthF();
105+
}
106+
if ( residual.y() > 0 )
107+
{
108+
residualBottom = residual.y() * rf + mResidualPen.widthF();
109+
residualTop = -mResidualPen.widthF();
110+
}
111+
else
112+
{
113+
residualBottom = mResidualPen.widthF();
114+
residualTop = residual.y() * rf - mResidualPen.widthF();
115+
}
116+
117+
QRectF residualArrowRect( QPointF( residualLeft, residualTop ), QPointF( residualRight, residualBottom ) );
118+
QRectF markerRect( -2, -2, mTextBounds.width() + 6, mTextBounds.height() + 6 );
119+
return residualArrowRect.united( markerRect );
75120
}
76121

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

86-
void QgsGCPCanvasItem::setEnabled( bool enabled )
131+
void QgsGCPCanvasItem::updatePosition()
87132
{
88-
mEnabled = enabled;
89-
mPointBrush = enabled ? QBrush( Qt::red ) : QBrush( Qt::gray );
90-
mLabelBrush = enabled ? QBrush( Qt::yellow ) : QBrush( Qt::gray );
91-
update();
92-
}
133+
if ( !mDataPoint )
134+
{
135+
return;
136+
}
93137

94-
void QgsGCPCanvasItem::setRasterCoords( QgsPoint p )
95-
{
96-
mRasterCoords = p;
138+
setPos( toCanvasCoordinates( mIsGCPSource ? mDataPoint->pixelCoords() : mDataPoint->mapCoords() ) );
97139
}
98140

99-
void QgsGCPCanvasItem::setWorldCoords( QgsPoint p )
141+
void QgsGCPCanvasItem::drawResidualArrow( QPainter* p )
100142
{
101-
mWorldCoords = p;
143+
if ( !mDataPoint || !mIsGCPSource )
144+
{
145+
return;
146+
}
147+
148+
QPointF residual = mDataPoint->residual();
149+
150+
double rf = residualToScreenFactor();
151+
p->setPen( mResidualPen );
152+
p->drawLine( QPointF( 0, 0 ), QPointF( residual.rx() * rf, residual.ry() * rf ) );
153+
102154
}
103155

104-
void QgsGCPCanvasItem::setId( int id )
156+
double QgsGCPCanvasItem::residualToScreenFactor() const
105157
{
106-
mId = id;
107-
update();
158+
if ( !mMapCanvas )
159+
{
160+
return 1;
161+
}
162+
163+
double mapUnitsPerScreenPixel = mMapCanvas->mapUnitsPerPixel();
164+
double mapUnitsPerRasterPixel = 1.0;
165+
166+
if ( mMapCanvas->mapRenderer() )
167+
{
168+
QStringList canvasLayers = mMapCanvas->mapRenderer()->layerSet();
169+
if ( canvasLayers.size() > 0 )
170+
{
171+
QString layerId = canvasLayers.at( 0 );
172+
QgsMapLayer* mapLayer = QgsMapLayerRegistry::instance()->mapLayer( layerId );
173+
if ( mapLayer )
174+
{
175+
QgsRasterLayer* rasterLayer = dynamic_cast<QgsRasterLayer*>( mapLayer );
176+
if ( rasterLayer )
177+
{
178+
mapUnitsPerRasterPixel = rasterLayer->rasterUnitsPerPixel();
179+
}
180+
}
181+
}
182+
}
183+
184+
return 1.0 / ( mapUnitsPerScreenPixel * mapUnitsPerRasterPixel );
108185
}
109186

110-
void QgsGCPCanvasItem::updatePosition()
187+
void QgsGCPCanvasItem::checkBoundingRectChange()
111188
{
112-
setPos( toCanvasCoordinates( mIsGCPSource ? mRasterCoords : mWorldCoords ) );
189+
prepareGeometryChange();
113190
}

src/plugins/georeferencer/qgsgcpcanvasitem.h

+13-15
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@
2020
#include "qgsmapcanvas.h"
2121
#include "qgsmapcanvasitem.h"
2222

23+
class QgsGeorefDataPoint;
24+
2325
class QgsGCPCanvasItem : public QgsMapCanvasItem
2426
{
2527
public:
26-
QgsGCPCanvasItem( QgsMapCanvas* mapCanvas, const QgsPoint& rasterCoords,
27-
const QgsPoint& worldCoords, bool isGCPSource/* = true*/ );
28+
QgsGCPCanvasItem( QgsMapCanvas* mapCanvas, const QgsGeorefDataPoint* dataPoint, bool isGCPSource/* = true*/ );
2829

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

3536
QPainterPath shape() const;
3637

37-
void setEnabled( bool enabled );
38-
39-
void setRasterCoords( QgsPoint p );
40-
void setWorldCoords( QgsPoint p );
41-
42-
int id() { return mId; }
43-
void setId( int id );
44-
4538
void updatePosition();
4639

40+
/**Calls prepareGeometryChange()*/
41+
void checkBoundingRectChange();
42+
4743
private:
44+
45+
const QgsGeorefDataPoint* mDataPoint;
4846
QSizeF mTextBounds;
4947
QBrush mPointBrush;
5048
QBrush mLabelBrush;
51-
QgsPoint mRasterCoords;
52-
QgsPoint mWorldCoords;
53-
54-
int mId;
5549
bool mIsGCPSource;
56-
bool mEnabled;
50+
QPen mResidualPen;
51+
52+
void drawResidualArrow( QPainter* p );
53+
/**Calculates scale factor for residual display*/
54+
double residualToScreenFactor() const;
5755
};
5856

5957
#endif // QGSGCPCANVASITEM_H

src/plugins/georeferencer/qgsgcplistmodel.cpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ void QgsGCPListModel::updateModel()
124124
setItem( i, j++, QGSSTANDARDITEM( p->mapCoords().x() ) /*create_item<double>( p->mapCoords().x() )*/ );
125125
setItem( i, j++, QGSSTANDARDITEM( p->mapCoords().y() ) /*create_item<double>( p->mapCoords().y() )*/ );
126126

127-
double residual = -1.f;
127+
double residual;
128128
double dX, dY;
129129
// Calculate residual if transform is available and up-to-date
130130
if ( mGeorefTransform && bTransformUpdated && mGeorefTransform->parametersInitialized() )
@@ -135,18 +135,24 @@ void QgsGCPListModel::updateModel()
135135
// As transforms of order >=2 are not invertible, we are only
136136
// interested in the residual in this direction
137137
mGeorefTransform->transformWorldToRaster( p->mapCoords(), dst );
138-
dX = ( dst.x() - p->pixelCoords().x() );
139-
dY = ( dst.y() - p->pixelCoords().y() );
138+
dX = ( dst.x() - p->pixelCoords().x() );
139+
dY = -( dst.y() - p->pixelCoords().y() );
140140
residual = sqrt( dX * dX + dY * dY );
141141
}
142142
else
143143
{
144144
dX = dY = residual = 0;
145145
}
146+
147+
if ( p )
148+
{
149+
p->setResidual( QPointF( dX, dY ) );
150+
}
151+
146152
if ( residual >= 0.f )
147153
{
148154
setItem( i, j++, QGSSTANDARDITEM( dX ) /*create_item<double>(dX)*/ );
149-
setItem( i, j++, QGSSTANDARDITEM( -dY ) /*create_item<double>(-dY)*/ );
155+
setItem( i, j++, QGSSTANDARDITEM( dY ) /*create_item<double>(-dY)*/);
150156
setItem( i, j++, QGSSTANDARDITEM( residual ) /*create_item<double>(residual)*/ );
151157
}
152158
else

src/plugins/georeferencer/qgsgeorefdatapoint.cpp

+43-13
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ QgsGeorefDataPoint::QgsGeorefDataPoint( QgsMapCanvas* srcCanvas, QgsMapCanvas *d
3030
, mId( -1 )
3131
, mEnabled( enable )
3232
{
33-
mGCPSourceItem = new QgsGCPCanvasItem( srcCanvas, pixelCoords, mapCoords, true );
34-
mGCPDestinationItem = new QgsGCPCanvasItem( dstCanvas, pixelCoords, mapCoords, false );
33+
mGCPSourceItem = new QgsGCPCanvasItem( srcCanvas, this, true );
34+
mGCPDestinationItem = new QgsGCPCanvasItem( dstCanvas, this, false );
3535

3636
mGCPSourceItem->setEnabled( enable );
3737
mGCPDestinationItem->setEnabled( enable );
@@ -58,36 +58,66 @@ QgsGeorefDataPoint::~QgsGeorefDataPoint()
5858
void QgsGeorefDataPoint::setPixelCoords( const QgsPoint &p )
5959
{
6060
mPixelCoords = p;
61-
mGCPSourceItem->setRasterCoords( p );
62-
mGCPDestinationItem->setRasterCoords( p );
61+
mGCPSourceItem->update();
62+
mGCPDestinationItem->update();
6363
}
6464

6565
void QgsGeorefDataPoint::setMapCoords( const QgsPoint &p )
6666
{
6767
mMapCoords = p;
68-
mGCPSourceItem->setWorldCoords( p );
69-
mGCPDestinationItem->setWorldCoords( p );
68+
if ( mGCPSourceItem )
69+
{
70+
mGCPSourceItem->update();
71+
}
72+
if ( mGCPDestinationItem )
73+
{
74+
mGCPDestinationItem->update();
75+
}
7076
}
7177

7278
void QgsGeorefDataPoint::setEnabled( bool enabled )
7379
{
74-
mGCPSourceItem->setEnabled( enabled );
7580
mEnabled = enabled;
81+
if ( mGCPSourceItem )
82+
{
83+
mGCPSourceItem->update();
84+
}
7685
}
7786

7887
void QgsGeorefDataPoint::setId( int id )
7988
{
8089
mId = id;
81-
mGCPSourceItem->setId( id );
82-
mGCPDestinationItem->setId( id );
90+
if ( mGCPSourceItem )
91+
{
92+
mGCPSourceItem->update();
93+
}
94+
if ( mGCPDestinationItem )
95+
{
96+
mGCPDestinationItem->update();
97+
}
98+
}
99+
100+
void QgsGeorefDataPoint::setResidual( const QPointF& r )
101+
{
102+
mResidual = r;
103+
if ( mGCPSourceItem )
104+
{
105+
mGCPSourceItem->checkBoundingRectChange();
106+
}
83107
}
84108

85109
void QgsGeorefDataPoint::updateCoords()
86110
{
87-
mGCPSourceItem->updatePosition();
88-
mGCPDestinationItem->updatePosition();
89-
mGCPSourceItem->update();
90-
mGCPDestinationItem->update();
111+
if ( mGCPSourceItem )
112+
{
113+
mGCPSourceItem->updatePosition();
114+
mGCPSourceItem->update();
115+
}
116+
if ( mGCPDestinationItem )
117+
{
118+
mGCPDestinationItem->updatePosition();
119+
mGCPDestinationItem->update();
120+
}
91121
}
92122

93123
bool QgsGeorefDataPoint::contains( const QPoint &p )

src/plugins/georeferencer/qgsgeorefdatapoint.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,17 @@ class QgsGeorefDataPoint : public QObject
3939
bool isEnabled() const { return mEnabled; };
4040
void setEnabled( bool enabled );
4141

42-
int id() { return mId; }
42+
int id() const { return mId; }
4343
void setId( int id );
4444

4545
bool contains( const QPoint &p );
4646

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

50+
QPointF residual() const { return mResidual; }
51+
void setResidual( const QPointF& r );
52+
5053
public slots:
5154
void moveTo( const QPoint & );
5255
void updateCoords();
@@ -61,4 +64,5 @@ class QgsGeorefDataPoint : public QObject
6164

6265
int mId;
6366
bool mEnabled;
67+
QPointF mResidual;
6468
};

0 commit comments

Comments
 (0)