Skip to content

Commit a9f345f

Browse files
author
mmassing
committedMay 7, 2010
Partial patch #2673 by mhugent:
-Configurable GCP labeling -Ability to generate PDF report of residuals and transform parameters -Allow resampling to output file even for linear transforms git-svn-id: http://svn.osgeo.org/qgis/trunk@13436 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent cca4b0c commit a9f345f

14 files changed

+463
-85
lines changed
 

‎src/plugins/georeferencer/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ SET (GEOREF_SRCS
1515
qgsgeorefvalidators.cpp
1616
qgsleastsquares.cpp
1717
qgsmapcoordsdialog.cpp
18+
qgsresidualplotitem.cpp
1819
qgstransformsettingsdialog.cpp
1920

2021
qgsgcplist.cpp
@@ -67,7 +68,7 @@ ADD_LIBRARY (georefplugin MODULE ${GEOREF_SRCS} ${GEOREF_MOC_SRCS} ${GEOREF_RCC_
6768
INCLUDE_DIRECTORIES(
6869
${CMAKE_CURRENT_SOURCE_DIR}
6970
${CMAKE_CURRENT_BINARY_DIR}
70-
../../core ../../core/raster ../../core/renderer ../../core/symbology
71+
../../core ../../core/raster ../../core/renderer ../../core/symbology ../../core/composer
7172
../../gui
7273
..
7374
${GSL_INCLUDE_DIR}

‎src/plugins/georeferencer/qgsgcpcanvasitem.cpp

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ QgsGCPCanvasItem::QgsGCPCanvasItem( QgsMapCanvas* mapCanvas, const QgsGeorefData
3535

3636
void QgsGCPCanvasItem::paint( QPainter* p )
3737
{
38+
QgsRenderContext context;
39+
if ( !setRenderContextVariables( p, context ) )
40+
{
41+
return;
42+
}
43+
3844
p->setRenderHint( QPainter::Antialiasing );
3945

4046
bool enabled = true;
@@ -57,29 +63,39 @@ void QgsGCPCanvasItem::paint( QPainter* p )
5763

5864
QSettings s;
5965
bool showIDs = s.value( "/Plugin-GeoReferencer/Config/ShowId" ).toBool();
60-
if ( !showIDs && mIsGCPSource )
66+
bool showCoords = s.value( "/Plugin-GeoReferencer/Config/ShowCoords" ).toBool();
67+
68+
QString msg;
69+
if ( showIDs && showCoords )
6170
{
62-
QString msg = QString( "X %1\nY %2" ).arg( QString::number( worldCoords.x(), 'f' ) ).
63-
arg( QString::number( worldCoords.y(), 'f' ) );
64-
p->setFont( QFont( "helvetica", 9 ) );
65-
QRect textBounds = p->boundingRect( 6, 6, 10, 10, Qt::AlignLeft, msg );
66-
p->setBrush( mLabelBrush );
67-
p->drawRect( textBounds.x() - 2, textBounds.y() - 2, textBounds.width() + 4, textBounds.height() + 4 );
68-
p->drawText( textBounds, Qt::AlignLeft, msg );
69-
mTextBounds = QSizeF( textBounds.width() + 4, textBounds.height() + 4 );
71+
msg = QString( "%1\nX %2\nY %3" ).arg( QString::number( id ) ).arg( QString::number( worldCoords.x(), 'f' ) ).arg( QString::number( worldCoords.y(), 'f' ) );
7072
}
7173
else if ( showIDs )
7274
{
73-
p->setFont( QFont( "helvetica", 12 ) );
74-
QString msg = QString::number( id );
75+
msg = msg = QString::number( id );
76+
}
77+
else if ( showCoords )
78+
{
79+
msg = QString( "X %1\nY %2" ).arg( QString::number( worldCoords.x(), 'f' ) ).arg( QString::number( worldCoords.y(), 'f' ) );
80+
}
81+
82+
if ( !msg.isEmpty() )
83+
{
7584
p->setBrush( mLabelBrush );
76-
p->drawRect( 5, 4, p->fontMetrics().width( msg ) + 2, 14 );
77-
p->drawText( 6, 16, msg );
78-
QFontMetrics fm = p->fontMetrics();
79-
mTextBounds = QSize( fm.width( msg ) + 4, fm.height() + 4 );
85+
QFont textFont( "helvetica" );
86+
textFont.setPixelSize( fontSizePainterUnits( 12, context ) );
87+
p->setFont( textFont );
88+
QRectF textBounds = p->boundingRect( 3 * context.scaleFactor(), 3 * context.scaleFactor(), 5 * context.scaleFactor(), 5 * context.scaleFactor(), Qt::AlignLeft, msg );
89+
mTextBoxRect = QRectF( textBounds.x() - context.scaleFactor() * 1, textBounds.y() - context.scaleFactor() * 1, \
90+
textBounds.width() + 2 * context.scaleFactor(), textBounds.height() + 2 * context.scaleFactor() );
91+
p->drawRect( mTextBoxRect );
92+
p->drawText( textBounds, Qt::AlignLeft, msg );
8093
}
8194

82-
drawResidualArrow( p );
95+
if ( data( 0 ) != "composer" ) //draw residuals only on screen
96+
{
97+
drawResidualArrow( p, context );
98+
}
8399
}
84100

85101
QRectF QgsGCPCanvasItem::boundingRect() const
@@ -91,6 +107,8 @@ QRectF QgsGCPCanvasItem::boundingRect() const
91107
{
92108
residual = mDataPoint->residual();
93109
}
110+
111+
//only considering screen resolution is ok for the bounding box function
94112
double rf = residualToScreenFactor();
95113

96114
if ( residual.x() > 0 )
@@ -116,7 +134,12 @@ QRectF QgsGCPCanvasItem::boundingRect() const
116134

117135
QRectF residualArrowRect( QPointF( residualLeft, residualTop ), QPointF( residualRight, residualBottom ) );
118136
QRectF markerRect( -2, -2, mTextBounds.width() + 6, mTextBounds.height() + 6 );
119-
return residualArrowRect.united( markerRect );
137+
QRectF boundingRect = residualArrowRect.united( markerRect );
138+
if ( !mTextBoxRect.isNull() )
139+
{
140+
boundingRect = boundingRect.united( mTextBoxRect );
141+
}
142+
return boundingRect;
120143
}
121144

122145
QPainterPath QgsGCPCanvasItem::shape() const
@@ -138,9 +161,9 @@ void QgsGCPCanvasItem::updatePosition()
138161
setPos( toCanvasCoordinates( mIsGCPSource ? mDataPoint->pixelCoords() : mDataPoint->mapCoords() ) );
139162
}
140163

141-
void QgsGCPCanvasItem::drawResidualArrow( QPainter* p )
164+
void QgsGCPCanvasItem::drawResidualArrow( QPainter* p, const QgsRenderContext& context )
142165
{
143-
if ( !mDataPoint || !mIsGCPSource )
166+
if ( !mDataPoint || !mIsGCPSource || !mMapCanvas )
144167
{
145168
return;
146169
}
@@ -188,3 +211,9 @@ void QgsGCPCanvasItem::checkBoundingRectChange()
188211
{
189212
prepareGeometryChange();
190213
}
214+
215+
double QgsGCPCanvasItem::fontSizePainterUnits( double points, const QgsRenderContext& c )
216+
{
217+
return points * 0.3527 * c.scaleFactor();
218+
}
219+

‎src/plugins/georeferencer/qgsgcpcanvasitem.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,14 @@ class QgsGCPCanvasItem : public QgsMapCanvasItem
4949
bool mIsGCPSource;
5050
QPen mResidualPen;
5151

52-
void drawResidualArrow( QPainter* p );
52+
//text box rect for bounding rect calculation (updated in the paint event)
53+
QRectF mTextBoxRect;
54+
55+
void drawResidualArrow( QPainter* p, const QgsRenderContext& context );
5356
/**Calculates scale factor for residual display*/
5457
double residualToScreenFactor() const;
58+
/**Calculates pixel size for a font point size*/
59+
double fontSizePainterUnits( double points, const QgsRenderContext& c );
5560
};
5661

5762
#endif // QGSGCPCANVASITEM_H

‎src/plugins/georeferencer/qgsgeorefconfigdialog.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,27 @@ void QgsGeorefConfigDialog::readSettings()
5454
{
5555
QSettings s;
5656
if ( s.value( "/Plugin-GeoReferencer/Config/ShowId" ).toBool() )
57-
mShowIDsRadioButton->setChecked( true );
57+
{
58+
mShowIDsCheckBox->setChecked( true );
59+
}
60+
else
61+
{
62+
mShowIDsCheckBox->setChecked( false );
63+
}
64+
65+
if ( s.value( "/Plugin-GeoReferencer/Config/ShowCoords" ).toBool() )
66+
{
67+
mShowCoordsCheckBox->setChecked( true );
68+
}
5869
else
59-
mShowCoordsRadioButton->setChecked( true );
70+
{
71+
mShowCoordsCheckBox->setChecked( false );
72+
}
6073
}
6174

6275
void QgsGeorefConfigDialog::writeSettings()
6376
{
6477
QSettings s;
65-
s.setValue( "/Plugin-GeoReferencer/Config/ShowId", mShowIDsRadioButton->isChecked() );
78+
s.setValue( "/Plugin-GeoReferencer/Config/ShowId", mShowIDsCheckBox->isChecked() );
79+
s.setValue( "/Plugin-GeoReferencer/Config/ShowCoords", mShowCoordsCheckBox->isChecked() );
6680
}

‎src/plugins/georeferencer/qgsgeorefconfigdialogbase.ui

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,29 @@
66
<rect>
77
<x>0</x>
88
<y>0</y>
9-
<width>221</width>
10-
<height>102</height>
9+
<width>219</width>
10+
<height>162</height>
1111
</rect>
1212
</property>
1313
<property name="windowTitle">
1414
<string>Configure Georeferencer</string>
1515
</property>
16-
<layout class="QGridLayout" name="gridLayout">
16+
<layout class="QGridLayout" name="gridLayout_2">
1717
<item row="0" column="0">
1818
<widget class="QGroupBox" name="mPointTipGroupBox">
1919
<property name="title">
2020
<string>Point tip</string>
2121
</property>
2222
<layout class="QHBoxLayout" name="horizontalLayout">
2323
<item>
24-
<widget class="QRadioButton" name="mShowIDsRadioButton">
24+
<widget class="QCheckBox" name="mShowIDsCheckBox">
2525
<property name="text">
2626
<string>Show IDs</string>
2727
</property>
28-
<property name="checked">
29-
<bool>true</bool>
30-
</property>
3128
</widget>
3229
</item>
3330
<item>
34-
<widget class="QRadioButton" name="mShowCoordsRadioButton">
31+
<widget class="QCheckBox" name="mShowCoordsCheckBox">
3532
<property name="text">
3633
<string>Show coords</string>
3734
</property>

‎src/plugins/georeferencer/qgsgeorefdatapoint.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ QgsGeorefDataPoint::QgsGeorefDataPoint( const QgsGeorefDataPoint &p )
4747
mPixelCoords = p.pixelCoords();
4848
mMapCoords = p.mapCoords();
4949
mEnabled = p.isEnabled();
50+
mResidual = p.residual();
51+
mId = p.id();
5052
}
5153

5254
QgsGeorefDataPoint::~QgsGeorefDataPoint()

‎src/plugins/georeferencer/qgsgeorefdatapoint.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
* *
1414
***************************************************************************/
1515
/* $Id$ */
16+
17+
#ifndef QGSGEOREFDATAPOINT_H
18+
#define QGSGEOREFDATAPOINT_H
19+
1620
#include "qgsmapcanvasitem.h"
1721

1822
class QgsGCPCanvasItem;
@@ -66,3 +70,5 @@ class QgsGeorefDataPoint : public QObject
6670
bool mEnabled;
6771
QPointF mResidual;
6872
};
73+
74+
#endif //QGSGEOREFDATAPOINT_H

‎src/plugins/georeferencer/qgsgeorefplugingui.cpp

Lines changed: 263 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <QMouseEvent>
2424
#include <QPainter>
2525
#include <QPlainTextEdit>
26+
#include <QPrinter>
2627
#include <QProgressDialog>
2728
#include <QPushButton>
2829
#include <QSettings>
@@ -32,9 +33,13 @@
3233
#include "qgslegendinterface.h"
3334
#include "qgsapplication.h"
3435

36+
#include "qgscomposerlabel.h"
37+
#include "qgscomposermap.h"
38+
#include "qgscomposertexttable.h"
3539
#include "qgsmapcanvas.h"
3640
#include "qgsmapcoordsdialog.h"
3741
#include "qgsmaplayerregistry.h"
42+
#include "qgsmaprenderer.h"
3843
#include "qgsmaptoolzoom.h"
3944
#include "qgsmaptoolpan.h"
4045

@@ -52,10 +57,26 @@
5257

5358
#include "qgsgeorefconfigdialog.h"
5459
#include "qgsgeorefdescriptiondialog.h"
60+
#include "qgsresidualplotitem.h"
5561
#include "qgstransformsettingsdialog.h"
5662

5763
#include "qgsgeorefplugingui.h"
5864

65+
class QgsGeorefDockWidget : public QDockWidget
66+
{
67+
public:
68+
QgsGeorefDockWidget( const QString & title, QWidget * parent = 0, Qt::WindowFlags flags = 0 )
69+
: QDockWidget( title, parent, flags )
70+
{
71+
setObjectName( "GeorefDockWidget" ); // set object name so the position can be saved
72+
}
73+
74+
virtual void closeEvent( QCloseEvent * ev )
75+
{
76+
deleteLater();
77+
}
78+
};
79+
5980
QgsGeorefPluginGui::QgsGeorefPluginGui( QgisInterface* theQgisInterface, QWidget* parent, Qt::WFlags fl )
6081
: QMainWindow( parent, fl )
6182
, mTransformParam( QgsGeorefTransform::InvalidTransform )
@@ -232,7 +253,7 @@ void QgsGeorefPluginGui::doGeoreference()
232253
{
233254
if ( mLoadInQgis )
234255
{
235-
if ( QgsGeorefTransform::Linear == mTransformParam )
256+
if ( mModifiedRasterFileName.isEmpty() )
236257
{
237258
mIface->addRasterLayer( mRasterFileName );
238259
}
@@ -264,7 +285,7 @@ bool QgsGeorefPluginGui::getTransformSettings()
264285
}
265286

266287
d.getTransformSettings( mTransformParam, mResamplingMethod, mCompressionMethod,
267-
mModifiedRasterFileName, mProjection, mUseZeroForTrans, mLoadInQgis, mUserResX, mUserResY );
288+
mModifiedRasterFileName, mProjection, mPdfOutputFile, mUseZeroForTrans, mLoadInQgis, mUserResX, mUserResY );
268289
mTransformParamLabel->setText( tr( "Transform: " ) + convertTransformEnumToString( mTransformParam ) );
269290
mGeorefTransform.selectTransformParametrisation( mTransformParam );
270291
mGCPListWidget->setGeorefTransform( &mGeorefTransform );
@@ -543,9 +564,11 @@ void QgsGeorefPluginGui::showRasterPropertiesDialog()
543564
void QgsGeorefPluginGui::showGeorefConfigDialog()
544565
{
545566
QgsGeorefConfigDialog config;
546-
config.exec();
547-
mCanvas->refresh();
548-
mIface->mapCanvas()->refresh();
567+
if ( config.exec() == QDialog::Accepted )
568+
{
569+
mCanvas->refresh();
570+
mIface->mapCanvas()->refresh();
571+
}
549572
}
550573

551574
// Info slots
@@ -1042,11 +1065,12 @@ bool QgsGeorefPluginGui::georeference()
10421065
if ( !checkReadyGeoref() )
10431066
return false;
10441067

1045-
if ( QgsGeorefTransform::Linear == mGeorefTransform.transformParametrisation() )
1068+
if ( mModifiedRasterFileName.isEmpty() && ( QgsGeorefTransform::Linear == mGeorefTransform.transformParametrisation() || \
1069+
QgsGeorefTransform::Helmert == mGeorefTransform.transformParametrisation() ) )
10461070
{
10471071
QgsPoint origin;
1048-
double pixelXSize, pixelYSize;
1049-
if ( !mGeorefTransform.getLinearOriginScale( origin, pixelXSize, pixelYSize ) )
1072+
double pixelXSize, pixelYSize, rotation;
1073+
if ( !mGeorefTransform.getOriginScaleRotation( origin, pixelXSize, pixelYSize, rotation ) )
10501074
{
10511075
QMessageBox::information( this, tr( "Info" ),
10521076
tr( "Failed to get linear transform parameters" ) );
@@ -1076,7 +1100,11 @@ bool QgsGeorefPluginGui::georeference()
10761100
return false;
10771101
}
10781102

1079-
return writeWorldFile( origin, pixelXSize, pixelYSize );
1103+
bool success = writeWorldFile( origin, pixelXSize, pixelYSize, rotation );
1104+
if ( success && !mPdfOutputFile.isEmpty() )
1105+
{
1106+
writePDFReportFile( mPdfOutputFile, mGeorefTransform );
1107+
}
10801108
}
10811109
else // Helmert, Polinom 1, Polinom 2, Polinom 3
10821110
{
@@ -1097,12 +1125,16 @@ bool QgsGeorefPluginGui::georeference()
10971125
}
10981126
else // 1 all right
10991127
{
1128+
if ( !mPdfOutputFile.isEmpty() )
1129+
{
1130+
writePDFReportFile( mPdfOutputFile, mGeorefTransform );
1131+
}
11001132
return true;
11011133
}
11021134
}
11031135
}
11041136

1105-
bool QgsGeorefPluginGui::writeWorldFile( QgsPoint origin, double pixelXSize, double pixelYSize )
1137+
bool QgsGeorefPluginGui::writeWorldFile( QgsPoint origin, double pixelXSize, double pixelYSize, double rotation )
11061138
{
11071139
// write the world file
11081140
QFile file( mWorldFileName );
@@ -1112,16 +1144,233 @@ bool QgsGeorefPluginGui::writeWorldFile( QgsPoint origin, double pixelXSize, dou
11121144
tr( "Could not write to %1" ).arg( mWorldFileName ) );
11131145
return false;
11141146
}
1147+
1148+
double rotationX = 0;
1149+
double rotationY = 0;
1150+
1151+
if ( !doubleNear( rotation, 0.0 ) )
1152+
{
1153+
rotationX = pixelXSize * sin( rotation );
1154+
rotationY = pixelYSize * sin( rotation );
1155+
pixelXSize *= cos( rotation );
1156+
pixelYSize *= cos( rotation );
1157+
}
1158+
11151159
QTextStream stream( &file );
11161160
stream << QString::number( pixelXSize, 'f', 15 ) << endl
1117-
<< 0 << endl
1118-
<< 0 << endl
1161+
<< rotationX << endl
1162+
<< rotationY << endl
11191163
<< QString::number( -pixelYSize, 'f', 15 ) << endl
11201164
<< QString::number( origin.x(), 'f', 15 ) << endl
11211165
<< QString::number( origin.y(), 'f', 15 ) << endl;
11221166
return true;
11231167
}
11241168

1169+
bool QgsGeorefPluginGui::writePDFReportFile( const QString& fileName, const QgsGeorefTransform& transform )
1170+
{
1171+
if ( !mCanvas )
1172+
{
1173+
return false;
1174+
}
1175+
1176+
QgsMapRenderer* canvasRenderer = mCanvas->mapRenderer();
1177+
if ( !canvasRenderer )
1178+
{
1179+
return false;
1180+
}
1181+
1182+
QPrinter printer;
1183+
printer.setOutputFormat( QPrinter::PdfFormat );
1184+
printer.setOutputFileName( fileName );
1185+
1186+
//create composition A4 with 300 dpi
1187+
QgsComposition* composition = new QgsComposition( mCanvas->mapRenderer() );
1188+
composition->setPaperSize( 210, 297 ); //A4
1189+
composition->setPrintResolution( 300 );
1190+
printer.setPaperSize( QSizeF( composition->paperWidth(), composition->paperHeight() ), QPrinter::Millimeter );
1191+
1192+
//title
1193+
QFileInfo rasterFi( mRasterFileName );
1194+
QgsComposerLabel* titleLabel = new QgsComposerLabel( composition );
1195+
titleLabel->setText( rasterFi.fileName() );
1196+
composition->addItem( titleLabel );
1197+
titleLabel->setSceneRect( QRectF( 10, 5, composition->paperWidth(), 8 ) );
1198+
titleLabel->setFrame( false );
1199+
1200+
//composer map
1201+
QgsComposerMap* composerMap = new QgsComposerMap( composition, 10, titleLabel->rect().bottom() + titleLabel->transform().dy(), 190, 277 );
1202+
composerMap->setLayerSet( canvasRenderer->layerSet() );
1203+
composerMap->setNewExtent( mCanvas->extent() );
1204+
composerMap->setMapCanvas( mCanvas );
1205+
composition->addItem( composerMap );
1206+
printer.setFullPage( true );
1207+
printer.setColorMode( QPrinter::Color );
1208+
1209+
QgsComposerTextTable* parameterTable = 0;
1210+
double scaleX, scaleY, rotation;
1211+
QgsPoint origin;
1212+
1213+
QgsComposerLabel* parameterLabel = 0;
1214+
//transformation that involves only scaling and rotation (linear or helmert) ?
1215+
bool wldTransform = transform.getOriginScaleRotation( origin, scaleX, scaleY, rotation );
1216+
1217+
//consider rotation in scale parameter
1218+
double wldScaleX = scaleX;
1219+
double wldScaleY = scaleY;
1220+
if ( wldTransform && !doubleNear( rotation, 0.0 ) )
1221+
{
1222+
wldScaleX *= cos( rotation );
1223+
wldScaleY *= cos( rotation );
1224+
}
1225+
1226+
if ( wldTransform )
1227+
{
1228+
parameterLabel = new QgsComposerLabel( composition );
1229+
parameterLabel->setText( tr( "Transformation parameters" ) );
1230+
parameterLabel->adjustSizeToText();
1231+
composition->addItem( parameterLabel );
1232+
parameterLabel->setSceneRect( QRectF( 10, composerMap->rect().bottom() + composerMap->transform().dy() + 5, composition->paperWidth(), 8 ) );
1233+
parameterLabel->setFrame( false );
1234+
1235+
//calculate mean error (in map units)
1236+
double meanError = 0;
1237+
if ( mPoints.size() > 4 )
1238+
{
1239+
double sumVxSquare = 0;
1240+
double sumVySquare = 0;
1241+
double resXMap, resYMap;
1242+
1243+
int nPointsEnabled = 0;
1244+
QgsGCPList::const_iterator gcpIt = mPoints.constBegin();
1245+
for ( ; gcpIt != mPoints.constEnd(); ++gcpIt )
1246+
{
1247+
if (( *gcpIt )->isEnabled() )
1248+
{
1249+
resXMap = ( *gcpIt )->residual().x() * wldScaleX;
1250+
resYMap = ( *gcpIt )->residual().x() * wldScaleY;
1251+
sumVxSquare += ( resXMap * resXMap );
1252+
sumVySquare += ( resYMap * resYMap );
1253+
++nPointsEnabled;
1254+
}
1255+
}
1256+
1257+
if ( nPointsEnabled > 4 )
1258+
{
1259+
meanError = sqrt(( sumVxSquare + sumVySquare ) / ( 2 * nPointsEnabled - 4 ) ) * sqrt( 2 );
1260+
}
1261+
}
1262+
1263+
1264+
parameterTable = new QgsComposerTextTable( composition );
1265+
QStringList headers;
1266+
headers << tr( "Translation x" ) << tr( "Translation y" ) << tr( "Scale x" ) << tr( "Scale y" ) << tr( "Rotation [degrees]" ) << tr( "Mean error [map units]" );
1267+
parameterTable->setHeaderLabels( headers );
1268+
QStringList row;
1269+
row << QString::number( origin.x() ) << QString::number( origin.y() ) << QString::number( scaleX ) << QString::number( scaleY ) << QString::number( rotation * 180 / M_PI ) << QString::number( meanError );
1270+
parameterTable->addRow( row );
1271+
composition->addItem( parameterTable );
1272+
parameterTable->setSceneRect( QRectF( 10, parameterLabel->rect().bottom() + parameterLabel->transform().dy() + 5, 50, 20 ) );
1273+
parameterTable->setGridStrokeWidth( 0.1 );
1274+
parameterTable->adjustFrameToSize();
1275+
}
1276+
1277+
QGraphicsRectItem* previousItem = composerMap;
1278+
if ( parameterTable )
1279+
{
1280+
previousItem = parameterTable;
1281+
}
1282+
1283+
QgsComposerLabel* residualLabel = new QgsComposerLabel( composition );
1284+
residualLabel->setText( tr( "Residuals" ) );
1285+
composition->addItem( residualLabel );
1286+
residualLabel->setSceneRect( QRectF( 10, previousItem->rect().bottom() + previousItem->transform().dy() + 5, composition->paperWidth(), 6 ) );
1287+
residualLabel->setFrame( false );
1288+
1289+
//residual plot
1290+
QgsResidualPlotItem* resPlotItem = new QgsResidualPlotItem( composition );
1291+
composition->addItem( resPlotItem );
1292+
resPlotItem->setSceneRect( QRectF( 10, residualLabel->rect().bottom() + residualLabel->transform().dy() + 5, composerMap->rect().width(), composerMap->rect().height() ) );
1293+
resPlotItem->setExtent( composerMap->extent() );
1294+
resPlotItem->setGCPList( mPoints );
1295+
1296+
//convert residual scale bar plot to map units if scaling is equal in x- and y-direction (e.g. helmert)
1297+
if ( wldTransform )
1298+
{
1299+
if ( doubleNear( wldScaleX, wldScaleY ) )
1300+
{
1301+
resPlotItem->setPixelToMapUnits( scaleX );
1302+
resPlotItem->setConvertScaleToMapUnits( true );
1303+
}
1304+
}
1305+
1306+
QString residualUnits;
1307+
if ( wldTransform )
1308+
{
1309+
residualUnits = tr( "map units" );
1310+
}
1311+
else
1312+
{
1313+
residualUnits = tr( "pixels" );
1314+
}
1315+
QgsComposerTextTable* gcpTable = new QgsComposerTextTable( composition );
1316+
QStringList gcpHeader;
1317+
gcpHeader << "id" << "enabled" << "pixelCoordX" << "pixelCoordY" << "mapCoordX" << "mapCoordY" << "resX[" + residualUnits + "]" << "resY[" + residualUnits + "]" << "resTot[" + residualUnits + "]";
1318+
gcpTable->setHeaderLabels( gcpHeader );
1319+
1320+
QgsGCPList::const_iterator gcpIt = mPoints.constBegin();
1321+
for ( ; gcpIt != mPoints.constEnd(); ++gcpIt )
1322+
{
1323+
QStringList currentGCPStrings;
1324+
QPointF residual = ( *gcpIt )->residual();
1325+
double residualX = residual.x();
1326+
if ( wldTransform )
1327+
{
1328+
residualX *= wldScaleX;
1329+
}
1330+
double residualY = residual.y();
1331+
if ( wldTransform )
1332+
{
1333+
residualY *= wldScaleY;
1334+
}
1335+
double residualTot = sqrt( residualX * residualX + residualY * residualY );
1336+
1337+
currentGCPStrings << QString::number(( *gcpIt )->id() );
1338+
if (( *gcpIt )->isEnabled() )
1339+
{
1340+
currentGCPStrings << tr( "yes" );
1341+
}
1342+
else
1343+
{
1344+
currentGCPStrings << tr( "no" );
1345+
}
1346+
currentGCPStrings << QString::number(( *gcpIt )->pixelCoords().x() ) << QString::number(( *gcpIt )->pixelCoords().y() ) << QString::number(( *gcpIt )->mapCoords().x() )\
1347+
<< QString::number(( *gcpIt )->mapCoords().y() ) << QString::number( residualX ) << QString::number( residualY ) << QString::number( residualTot );
1348+
gcpTable->addRow( currentGCPStrings );
1349+
}
1350+
1351+
composition->addItem( gcpTable );
1352+
1353+
gcpTable->setSceneRect( QRectF( 10, resPlotItem->rect().bottom() + resPlotItem->transform().dy() + 5, 170, 100 ) );
1354+
gcpTable->setGridStrokeWidth( 0.1 );
1355+
1356+
printer.setResolution( composition->printResolution() );
1357+
QPainter p( &printer );
1358+
composition->setPlotStyle( QgsComposition::Print );
1359+
QRectF paperRectMM = printer.pageRect( QPrinter::Millimeter );
1360+
QRectF paperRectPixel = printer.pageRect( QPrinter::DevicePixel );
1361+
composition->render( &p, paperRectPixel, paperRectMM );
1362+
1363+
delete titleLabel;
1364+
delete parameterLabel;
1365+
delete residualLabel;
1366+
delete resPlotItem;
1367+
delete parameterTable;
1368+
delete gcpTable;
1369+
delete composerMap;
1370+
delete composition;
1371+
return true;
1372+
}
1373+
11251374
// Gdal script
11261375
void QgsGeorefPluginGui::showGDALScript( int argNum... )
11271376
{
@@ -1248,7 +1497,8 @@ bool QgsGeorefPluginGui::checkReadyGeoref()
12481497
continue;
12491498
}
12501499

1251-
if ( mModifiedRasterFileName.isEmpty() && QgsGeorefTransform::Linear != mTransformParam )
1500+
//MH: helmert transformation without warping disabled until qgis is able to read rotated rasters efficiently
1501+
if ( mModifiedRasterFileName.isEmpty() && QgsGeorefTransform::Linear != mTransformParam /*&& QgsGeorefTransform::Helmert != mTransformParam*/ )
12521502
{
12531503
QMessageBox::information( this, tr( "Info" ), tr( "Please set output raster name" ) );
12541504
if ( !getTransformSettings() )

‎src/plugins/georeferencer/qgsgeorefplugingui.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,14 @@ class QgsGeorefPluginGui : public QMainWindow, private Ui::QgsGeorefPluginGuiBas
131131

132132
// georeference
133133
bool georeference();
134-
bool writeWorldFile( QgsPoint origin, double pixelXSize, double pixelYSize );
134+
bool writeWorldFile( QgsPoint origin, double pixelXSize, double pixelYSize, double rotation );
135+
bool writePDFReportFile( const QString& fileName, const QgsGeorefTransform& transform );
135136

136137
// gdal script
137138
void showGDALScript( int argNum... );
138-
QString generateGDALtranslateCommand( bool generateTFW = true);
139+
QString generateGDALtranslateCommand( bool generateTFW = true );
139140
/* Generate command-line for gdalwarp based on current GCPs and given parameters.
140-
* For values in the range 1 to 3, the parameter "order" prescribes the degree of the interpolating polynomials to use,
141+
* For values in the range 1 to 3, the parameter "order" prescribes the degree of the interpolating polynomials to use,
141142
* a value of -1 indicates that thin plate spline interpolation should be used for warping.*/
142143
QString generateGDALwarpCommand( QString resampling, QString compress, bool useZeroForTrans, int order,
143144
double targetResX, double targetResY );
@@ -177,6 +178,7 @@ class QgsGeorefPluginGui : public QMainWindow, private Ui::QgsGeorefPluginGuiBas
177178
QString mTranslatedRasterFileName;
178179
QString mGCPpointsFileName;
179180
QString mProjection;
181+
QString mPdfOutputFile;
180182
double mUserResX, mUserResY; // User specified target scale
181183

182184
QgsGeorefTransform::TransformParametrisation mTransformParam;

‎src/plugins/georeferencer/qgsgeoreftransform.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class QgsHelmertGeorefTransform : public QgsGeorefTransformInterface
7171
double angle;
7272
};
7373

74+
bool getOriginScaleRotation( QgsPoint &origin, double& scale, double& rotation ) const;
7475
bool updateParametersFromGCPs( const std::vector<QgsPoint> &mapCoords, const std::vector<QgsPoint> &pixelCoords );
7576
uint getMinimumGCPCount() const;
7677

@@ -246,6 +247,28 @@ bool QgsGeorefTransform::getLinearOriginScale( QgsPoint &origin, double &scaleX,
246247
return dynamic_cast<QgsLinearGeorefTransform *>( mGeorefTransformImplementation )->getOriginScale( origin, scaleX, scaleY );
247248
}
248249

250+
bool QgsGeorefTransform::getOriginScaleRotation( QgsPoint &origin, double &scaleX, double &scaleY, double& rotation ) const
251+
{
252+
253+
if ( mTransformParametrisation == Linear )
254+
{
255+
rotation = 0.0;
256+
return dynamic_cast<QgsLinearGeorefTransform *>( mGeorefTransformImplementation )->getOriginScale( origin, scaleX, scaleY );
257+
}
258+
else if ( mTransformParametrisation == Helmert )
259+
{
260+
double scale;
261+
if ( ! dynamic_cast<QgsHelmertGeorefTransform*>( mGeorefTransformImplementation )->getOriginScaleRotation( origin, scale, rotation ) )
262+
{
263+
return false;
264+
}
265+
scaleX = scale;
266+
scaleY = scale;
267+
return true;
268+
}
269+
return false;
270+
}
271+
249272

250273
bool QgsGeorefTransform::gdal_transform( const QgsPoint &src, QgsPoint &dst, int dstToSrc ) const
251274
{
@@ -357,6 +380,13 @@ void *QgsHelmertGeorefTransform::GDALTransformerArgs() const
357380
return ( void* )&mHelmertParameters;
358381
}
359382

383+
bool QgsHelmertGeorefTransform::getOriginScaleRotation( QgsPoint &origin, double& scale, double& rotation ) const
384+
{
385+
origin = mHelmertParameters.origin;
386+
scale = mHelmertParameters.scale;
387+
rotation = mHelmertParameters.angle;
388+
return true;
389+
}
360390

361391
int QgsHelmertGeorefTransform::helmert_transform( void *pTransformerArg, int bDstToSrc, int nPointCount,
362392
double *x, double *y, double *z, int *panSuccess )

‎src/plugins/georeferencer/qgsgeoreftransform.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ class QgsGeorefTransform : public QgsGeorefTransformInterface
129129

130130
//! \brief Returns origin and scale if this is a linear transform, fails otherwise.
131131
bool getLinearOriginScale( QgsPoint &origin, double &scaleX, double &scaleY ) const;
132+
133+
//! \brief Returns origin, scale and rotation for linear and helmert transform, fails otherwise.
134+
bool getOriginScaleRotation( QgsPoint &origin, double &scaleX, double &scaleY, double& rotation ) const;
135+
132136
private:
133137
// shallow copy constructor
134138
QgsGeorefTransform( const QgsGeorefTransform &other );

‎src/plugins/georeferencer/qgstransformsettingsdialog.cpp

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ QgsTransformSettingsDialog::QgsTransformSettingsDialog( const QString &raster, c
3434
{
3535
setupUi( this );
3636

37-
cmbTransformType->addItem( tr( "Linear" ) , (int)QgsGeorefTransform::Linear ) ;
38-
cmbTransformType->addItem( tr( "Helmert" ), (int)QgsGeorefTransform::Helmert );
39-
cmbTransformType->addItem( tr( "Polynomial 1" ), (int)QgsGeorefTransform::PolynomialOrder1 );
40-
cmbTransformType->addItem( tr( "Polynomial 2" ), (int)QgsGeorefTransform::PolynomialOrder2 );
41-
cmbTransformType->addItem( tr( "Polynomial 3" ), (int)QgsGeorefTransform::PolynomialOrder3 );
42-
cmbTransformType->addItem( tr( "Thin Plate Spline" ), (int)QgsGeorefTransform::ThinPlateSpline );
43-
37+
cmbTransformType->addItem( tr( "Linear" ) , ( int )QgsGeorefTransform::Linear ) ;
38+
cmbTransformType->addItem( tr( "Helmert" ), ( int )QgsGeorefTransform::Helmert );
39+
cmbTransformType->addItem( tr( "Polynomial 1" ), ( int )QgsGeorefTransform::PolynomialOrder1 );
40+
cmbTransformType->addItem( tr( "Polynomial 2" ), ( int )QgsGeorefTransform::PolynomialOrder2 );
41+
cmbTransformType->addItem( tr( "Polynomial 3" ), ( int )QgsGeorefTransform::PolynomialOrder3 );
42+
cmbTransformType->addItem( tr( "Thin Plate Spline" ), ( int )QgsGeorefTransform::ThinPlateSpline );
43+
4444
leOutputRaster->setText( output );
4545

4646
mRegExpValidator = new QRegExpValidator( QRegExp( "(^epsg:{1}\\s*\\d+)|(^\\+proj.*)", Qt::CaseInsensitive ), leTargetSRS );
@@ -70,12 +70,13 @@ QgsTransformSettingsDialog::QgsTransformSettingsDialog( const QString &raster, c
7070

7171
tbnOutputRaster->setIcon( getThemeIcon( "/mPushButtonFileOpen.png" ) );
7272
tbnTargetSRS->setIcon( getThemeIcon( "/mPushButtonTargetSRSDisabled.png" ) );
73+
tbnReportFile->setIcon( getThemeIcon( "/mActionSaveAsPDF.png" ) );
7374
}
7475

7576
void QgsTransformSettingsDialog::getTransformSettings( QgsGeorefTransform::TransformParametrisation &tp,
7677
QgsImageWarper::ResamplingMethod &rm,
7778
QString &comprMethod, QString &raster,
78-
QString &proj, bool &zt, bool &loadInQgis,
79+
QString &proj, QString& pdfReportFile, bool &zt, bool &loadInQgis,
7980
double& resX, double& resY )
8081
{
8182
if ( cmbTransformType->currentIndex() == -1 )
@@ -87,6 +88,7 @@ void QgsTransformSettingsDialog::getTransformSettings( QgsGeorefTransform::Trans
8788
comprMethod = cmbCompressionComboBox->currentText();
8889
raster = leOutputRaster->text();
8990
proj = leTargetSRS->text();
91+
pdfReportFile = mReportFileLineEdit->text();
9092
zt = cbxZeroAsTrans->isChecked();
9193
loadInQgis = cbxLoadInQgisWhenDone->isChecked();
9294
resX = 0.0;
@@ -130,7 +132,7 @@ void QgsTransformSettingsDialog::accept()
130132
int minGCPpoints;
131133
if ( checkGCPpoints( cmbTransformType->currentIndex(), minGCPpoints ) )
132134
{
133-
if ( leOutputRaster->text().isEmpty() && cmbTransformType->currentIndex() != 0 )
135+
if ( leOutputRaster->text().isEmpty() && cmbTransformType->currentIndex() > 1 )
134136
{
135137
QMessageBox::information( this, tr( "Info" ), tr( "Please set output name" ) );
136138
return;
@@ -156,6 +158,12 @@ void QgsTransformSettingsDialog::accept()
156158
s.setValue( "/Plugin-GeoReferencer/user_specified_resolution", cbxUserResolution->isChecked() );
157159
s.setValue( "/Plugin-GeoReferencer/user_specified_resx", dsbHorizRes->value() );
158160
s.setValue( "/Plugin-GeoReferencer/user_specified_resy", dsbVerticalRes->value() );
161+
QString pdfReportFileName = mReportFileLineEdit->text();
162+
if ( !pdfReportFileName.isEmpty() )
163+
{
164+
QFileInfo fi( pdfReportFileName );
165+
s.setValue( "/Plugin-GeoReferencer/lastPDFReportDir", fi.absolutePath() );
166+
}
159167
}
160168

161169
void QgsTransformSettingsDialog::on_tbnOutputRaster_clicked()
@@ -201,6 +209,17 @@ void QgsTransformSettingsDialog::on_tbnTargetSRS_clicked()
201209
}
202210
}
203211

212+
void QgsTransformSettingsDialog::on_tbnReportFile_clicked()
213+
{
214+
QSettings s;
215+
QString myLastUsedDir = s.value( "/Plugin-GeoReferencer/lastPDFReportDir", "" ).toString();
216+
QString outputFileName = QFileDialog::getSaveFileName( 0, tr( "Select save PDF file" ), myLastUsedDir, tr( "PDF Format" ) + " (*.pdf *PDF)" );
217+
if ( !outputFileName.isNull() )
218+
{
219+
mReportFileLineEdit->setText( outputFileName );
220+
}
221+
}
222+
204223
void QgsTransformSettingsDialog::on_leTargetSRS_textChanged( const QString &text )
205224
{
206225
QString t = text;

‎src/plugins/georeferencer/qgstransformsettingsdialog.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class QgsTransformSettingsDialog : public QDialog, private Ui::QgsTransformSetti
3232
int countGCPpoints, QWidget *parent = 0 );
3333
void getTransformSettings( QgsGeorefTransform::TransformParametrisation &tp,
3434
QgsImageWarper::ResamplingMethod &rm, QString &comprMethod,
35-
QString &raster, QString &proj, bool &zt, bool &loadInQgis,
35+
QString &raster, QString &proj, QString& pdfReportFile, bool &zt, bool &loadInQgis,
3636
double& resX, double& resY );
3737
static void resetSettings();
3838

@@ -43,6 +43,7 @@ class QgsTransformSettingsDialog : public QDialog, private Ui::QgsTransformSetti
4343
private slots:
4444
void on_tbnOutputRaster_clicked();
4545
void on_tbnTargetSRS_clicked();
46+
void on_tbnReportFile_clicked();
4647
void on_leTargetSRS_textChanged( const QString &text );
4748
QIcon getThemeIcon( const QString &theName );
4849

‎src/plugins/georeferencer/qgstransformsettingsdialogbase.ui

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,16 @@
66
<rect>
77
<x>0</x>
88
<y>0</y>
9-
<width>307</width>
10-
<height>328</height>
9+
<width>356</width>
10+
<height>381</height>
1111
</rect>
1212
</property>
1313
<property name="windowTitle">
1414
<string>Transformation settings</string>
1515
</property>
16-
<layout class="QVBoxLayout" name="verticalLayout">
17-
<item>
18-
<layout class="QFormLayout" name="formLayout">
19-
<property name="fieldGrowthPolicy">
20-
<enum>QFormLayout::ExpandingFieldsGrow</enum>
21-
</property>
16+
<layout class="QGridLayout" name="gridLayout_2">
17+
<item row="0" column="0">
18+
<layout class="QGridLayout" name="gridLayout">
2219
<item row="0" column="0">
2320
<widget class="QLabel" name="label">
2421
<property name="text">
@@ -161,27 +158,61 @@
161158
</layout>
162159
</item>
163160
<item row="5" column="0">
161+
<widget class="QLabel" name="label_6">
162+
<property name="text">
163+
<string>Generate pdf report:</string>
164+
</property>
165+
</widget>
166+
</item>
167+
<item row="5" column="1">
168+
<layout class="QHBoxLayout" name="horizontalLayout_3">
169+
<item>
170+
<widget class="QLineEdit" name="mReportFileLineEdit"/>
171+
</item>
172+
<item>
173+
<widget class="QToolButton" name="tbnReportFile">
174+
<property name="text">
175+
<string>...</string>
176+
</property>
177+
</widget>
178+
</item>
179+
</layout>
180+
</item>
181+
<item row="6" column="0">
164182
<widget class="QCheckBox" name="cbxUserResolution">
165183
<property name="text">
166184
<string>Set Target Resolution</string>
167185
</property>
168186
</widget>
169187
</item>
170-
<item row="6" column="0">
188+
<item row="7" column="0">
171189
<widget class="QLabel" name="label_4">
172190
<property name="text">
173191
<string>Horizontal</string>
174192
</property>
175193
</widget>
176194
</item>
177-
<item row="7" column="0">
195+
<item row="7" column="1">
196+
<widget class="QgsValidatedDoubleSpinBox" name="dsbHorizRes">
197+
<property name="decimals">
198+
<number>5</number>
199+
</property>
200+
<property name="minimum">
201+
<double>0.000000000000000</double>
202+
</property>
203+
<property name="maximum">
204+
<double>999999.000000000000000</double>
205+
</property>
206+
</widget>
207+
</item>
208+
<item row="8" column="0">
178209
<widget class="QLabel" name="label_5">
179210
<property name="text">
180211
<string>Vertical</string>
181212
</property>
182213
</widget>
183214
</item>
184-
<item row="7" column="1">
215+
<item row="8" column="1">
185216
<widget class="QgsValidatedDoubleSpinBox" name="dsbVerticalRes">
186217
<property name="sizePolicy">
187218
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
@@ -203,22 +234,9 @@
203234
</property>
204235
</widget>
205236
</item>
206-
<item row="6" column="1">
207-
<widget class="QgsValidatedDoubleSpinBox" name="dsbHorizRes">
208-
<property name="decimals">
209-
<number>5</number>
210-
</property>
211-
<property name="minimum">
212-
<double>0.000000000000000</double>
213-
</property>
214-
<property name="maximum">
215-
<double>999999.000000000000000</double>
216-
</property>
217-
</widget>
218-
</item>
219237
</layout>
220238
</item>
221-
<item>
239+
<item row="1" column="0">
222240
<widget class="QCheckBox" name="cbxZeroAsTrans">
223241
<property name="text">
224242
<string>Use 0 for transparency when needed</string>
@@ -228,14 +246,14 @@
228246
</property>
229247
</widget>
230248
</item>
231-
<item>
249+
<item row="2" column="0">
232250
<widget class="QCheckBox" name="cbxLoadInQgisWhenDone">
233251
<property name="text">
234252
<string>Load in QGIS when done</string>
235253
</property>
236254
</widget>
237255
</item>
238-
<item>
256+
<item row="3" column="0">
239257
<widget class="QDialogButtonBox" name="buttonBox">
240258
<property name="orientation">
241259
<enum>Qt::Horizontal</enum>

0 commit comments

Comments
 (0)
Please sign in to comment.