[QGIS Commit] r13436 - trunk/qgis/src/plugins/georeferencer

svn_qgis at osgeo.org svn_qgis at osgeo.org
Fri May 7 09:32:20 EDT 2010


Author: mmassing
Date: 2010-05-07 09:32:19 -0400 (Fri, 07 May 2010)
New Revision: 13436

Modified:
   trunk/qgis/src/plugins/georeferencer/CMakeLists.txt
   trunk/qgis/src/plugins/georeferencer/qgsgcpcanvasitem.cpp
   trunk/qgis/src/plugins/georeferencer/qgsgcpcanvasitem.h
   trunk/qgis/src/plugins/georeferencer/qgsgeorefconfigdialog.cpp
   trunk/qgis/src/plugins/georeferencer/qgsgeorefconfigdialogbase.ui
   trunk/qgis/src/plugins/georeferencer/qgsgeorefdatapoint.cpp
   trunk/qgis/src/plugins/georeferencer/qgsgeorefdatapoint.h
   trunk/qgis/src/plugins/georeferencer/qgsgeorefplugingui.cpp
   trunk/qgis/src/plugins/georeferencer/qgsgeorefplugingui.h
   trunk/qgis/src/plugins/georeferencer/qgsgeoreftransform.cpp
   trunk/qgis/src/plugins/georeferencer/qgsgeoreftransform.h
   trunk/qgis/src/plugins/georeferencer/qgstransformsettingsdialog.cpp
   trunk/qgis/src/plugins/georeferencer/qgstransformsettingsdialog.h
   trunk/qgis/src/plugins/georeferencer/qgstransformsettingsdialogbase.ui
Log:
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

Modified: trunk/qgis/src/plugins/georeferencer/CMakeLists.txt
===================================================================
--- trunk/qgis/src/plugins/georeferencer/CMakeLists.txt	2010-05-07 11:12:48 UTC (rev 13435)
+++ trunk/qgis/src/plugins/georeferencer/CMakeLists.txt	2010-05-07 13:32:19 UTC (rev 13436)
@@ -15,6 +15,7 @@
      qgsgeorefvalidators.cpp
      qgsleastsquares.cpp
      qgsmapcoordsdialog.cpp
+     qgsresidualplotitem.cpp
      qgstransformsettingsdialog.cpp
 
      qgsgcplist.cpp
@@ -67,7 +68,7 @@
 INCLUDE_DIRECTORIES(
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_BINARY_DIR}
-     ../../core ../../core/raster ../../core/renderer ../../core/symbology
+     ../../core ../../core/raster ../../core/renderer ../../core/symbology ../../core/composer
      ../../gui
      ..
      ${GSL_INCLUDE_DIR}

Modified: trunk/qgis/src/plugins/georeferencer/qgsgcpcanvasitem.cpp
===================================================================
--- trunk/qgis/src/plugins/georeferencer/qgsgcpcanvasitem.cpp	2010-05-07 11:12:48 UTC (rev 13435)
+++ trunk/qgis/src/plugins/georeferencer/qgsgcpcanvasitem.cpp	2010-05-07 13:32:19 UTC (rev 13436)
@@ -35,6 +35,12 @@
 
 void QgsGCPCanvasItem::paint( QPainter* p )
 {
+  QgsRenderContext context;
+  if ( !setRenderContextVariables( p, context ) )
+  {
+    return;
+  }
+
   p->setRenderHint( QPainter::Antialiasing );
 
   bool enabled = true;
@@ -57,29 +63,39 @@
 
   QSettings s;
   bool showIDs = s.value( "/Plugin-GeoReferencer/Config/ShowId" ).toBool();
-  if ( !showIDs && mIsGCPSource )
+  bool showCoords = s.value( "/Plugin-GeoReferencer/Config/ShowCoords" ).toBool();
+
+  QString msg;
+  if ( showIDs && showCoords )
   {
-    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 );
-    p->drawRect( textBounds.x() - 2, textBounds.y() - 2, textBounds.width() + 4, textBounds.height() + 4 );
-    p->drawText( textBounds, Qt::AlignLeft, msg );
-    mTextBounds = QSizeF( textBounds.width() + 4, textBounds.height() + 4 );
+    msg = QString( "%1\nX %2\nY %3" ).arg( QString::number( id ) ).arg( QString::number( worldCoords.x(), 'f' ) ).arg( QString::number( worldCoords.y(), 'f' ) );
   }
   else if ( showIDs )
   {
-    p->setFont( QFont( "helvetica", 12 ) );
-    QString msg = QString::number( id );
+    msg = msg = QString::number( id );
+  }
+  else if ( showCoords )
+  {
+    msg = QString( "X %1\nY %2" ).arg( QString::number( worldCoords.x(), 'f' ) ).arg( QString::number( worldCoords.y(), 'f' ) );
+  }
+
+  if ( !msg.isEmpty() )
+  {
     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 );
+    QFont textFont( "helvetica" );
+    textFont.setPixelSize( fontSizePainterUnits( 12, context ) );
+    p->setFont( textFont );
+    QRectF textBounds = p->boundingRect( 3 * context.scaleFactor(), 3 * context.scaleFactor(), 5 * context.scaleFactor(), 5 * context.scaleFactor(), Qt::AlignLeft, msg );
+    mTextBoxRect = QRectF( textBounds.x() - context.scaleFactor() * 1, textBounds.y() - context.scaleFactor() * 1, \
+                           textBounds.width() + 2 * context.scaleFactor(), textBounds.height() + 2 * context.scaleFactor() );
+    p->drawRect( mTextBoxRect );
+    p->drawText( textBounds, Qt::AlignLeft, msg );
   }
 
-  drawResidualArrow( p );
+  if ( data( 0 ) != "composer" ) //draw residuals only on screen
+  {
+    drawResidualArrow( p, context );
+  }
 }
 
 QRectF QgsGCPCanvasItem::boundingRect() const
@@ -91,6 +107,8 @@
   {
     residual = mDataPoint->residual();
   }
+
+  //only considering screen resolution is ok for the bounding box function
   double rf = residualToScreenFactor();
 
   if ( residual.x() > 0 )
@@ -116,7 +134,12 @@
 
   QRectF residualArrowRect( QPointF( residualLeft, residualTop ), QPointF( residualRight, residualBottom ) );
   QRectF markerRect( -2, -2, mTextBounds.width() + 6, mTextBounds.height() + 6 );
-  return residualArrowRect.united( markerRect );
+  QRectF boundingRect =  residualArrowRect.united( markerRect );
+  if ( !mTextBoxRect.isNull() )
+  {
+    boundingRect = boundingRect.united( mTextBoxRect );
+  }
+  return boundingRect;
 }
 
 QPainterPath QgsGCPCanvasItem::shape() const
@@ -138,9 +161,9 @@
   setPos( toCanvasCoordinates( mIsGCPSource ? mDataPoint->pixelCoords() : mDataPoint->mapCoords() ) );
 }
 
-void QgsGCPCanvasItem::drawResidualArrow( QPainter* p )
+void QgsGCPCanvasItem::drawResidualArrow( QPainter* p, const QgsRenderContext& context )
 {
-  if ( !mDataPoint || !mIsGCPSource )
+  if ( !mDataPoint || !mIsGCPSource || !mMapCanvas )
   {
     return;
   }
@@ -188,3 +211,9 @@
 {
   prepareGeometryChange();
 }
+
+double QgsGCPCanvasItem::fontSizePainterUnits( double points, const QgsRenderContext& c )
+{
+  return points * 0.3527 * c.scaleFactor();
+}
+

Modified: trunk/qgis/src/plugins/georeferencer/qgsgcpcanvasitem.h
===================================================================
--- trunk/qgis/src/plugins/georeferencer/qgsgcpcanvasitem.h	2010-05-07 11:12:48 UTC (rev 13435)
+++ trunk/qgis/src/plugins/georeferencer/qgsgcpcanvasitem.h	2010-05-07 13:32:19 UTC (rev 13436)
@@ -49,9 +49,14 @@
     bool mIsGCPSource;
     QPen mResidualPen;
 
-    void drawResidualArrow( QPainter* p );
+    //text box rect for bounding rect calculation (updated in the paint event)
+    QRectF mTextBoxRect;
+
+    void drawResidualArrow( QPainter* p, const QgsRenderContext& context );
     /**Calculates scale factor for residual display*/
     double residualToScreenFactor() const;
+    /**Calculates pixel size for a font point size*/
+    double fontSizePainterUnits( double points, const QgsRenderContext& c );
 };
 
 #endif // QGSGCPCANVASITEM_H

Modified: trunk/qgis/src/plugins/georeferencer/qgsgeorefconfigdialog.cpp
===================================================================
--- trunk/qgis/src/plugins/georeferencer/qgsgeorefconfigdialog.cpp	2010-05-07 11:12:48 UTC (rev 13435)
+++ trunk/qgis/src/plugins/georeferencer/qgsgeorefconfigdialog.cpp	2010-05-07 13:32:19 UTC (rev 13436)
@@ -54,13 +54,27 @@
 {
   QSettings s;
   if ( s.value( "/Plugin-GeoReferencer/Config/ShowId" ).toBool() )
-    mShowIDsRadioButton->setChecked( true );
+  {
+    mShowIDsCheckBox->setChecked( true );
+  }
   else
-    mShowCoordsRadioButton->setChecked( true );
+  {
+    mShowIDsCheckBox->setChecked( false );
+  }
+
+  if ( s.value( "/Plugin-GeoReferencer/Config/ShowCoords" ).toBool() )
+  {
+    mShowCoordsCheckBox->setChecked( true );
+  }
+  else
+  {
+    mShowCoordsCheckBox->setChecked( false );
+  }
 }
 
 void QgsGeorefConfigDialog::writeSettings()
 {
   QSettings s;
-  s.setValue( "/Plugin-GeoReferencer/Config/ShowId", mShowIDsRadioButton->isChecked() );
+  s.setValue( "/Plugin-GeoReferencer/Config/ShowId", mShowIDsCheckBox->isChecked() );
+  s.setValue( "/Plugin-GeoReferencer/Config/ShowCoords", mShowCoordsCheckBox->isChecked() );
 }

Modified: trunk/qgis/src/plugins/georeferencer/qgsgeorefconfigdialogbase.ui
===================================================================
--- trunk/qgis/src/plugins/georeferencer/qgsgeorefconfigdialogbase.ui	2010-05-07 11:12:48 UTC (rev 13435)
+++ trunk/qgis/src/plugins/georeferencer/qgsgeorefconfigdialogbase.ui	2010-05-07 13:32:19 UTC (rev 13436)
@@ -6,14 +6,14 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>221</width>
-    <height>102</height>
+    <width>219</width>
+    <height>162</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>Configure Georeferencer</string>
   </property>
-  <layout class="QGridLayout" name="gridLayout">
+  <layout class="QGridLayout" name="gridLayout_2">
    <item row="0" column="0">
     <widget class="QGroupBox" name="mPointTipGroupBox">
      <property name="title">
@@ -21,17 +21,14 @@
      </property>
      <layout class="QHBoxLayout" name="horizontalLayout">
       <item>
-       <widget class="QRadioButton" name="mShowIDsRadioButton">
+       <widget class="QCheckBox" name="mShowIDsCheckBox">
         <property name="text">
          <string>Show IDs</string>
         </property>
-        <property name="checked">
-         <bool>true</bool>
-        </property>
        </widget>
       </item>
       <item>
-       <widget class="QRadioButton" name="mShowCoordsRadioButton">
+       <widget class="QCheckBox" name="mShowCoordsCheckBox">
         <property name="text">
          <string>Show coords</string>
         </property>

Modified: trunk/qgis/src/plugins/georeferencer/qgsgeorefdatapoint.cpp
===================================================================
--- trunk/qgis/src/plugins/georeferencer/qgsgeorefdatapoint.cpp	2010-05-07 11:12:48 UTC (rev 13435)
+++ trunk/qgis/src/plugins/georeferencer/qgsgeorefdatapoint.cpp	2010-05-07 13:32:19 UTC (rev 13436)
@@ -47,6 +47,8 @@
   mPixelCoords = p.pixelCoords();
   mMapCoords = p.mapCoords();
   mEnabled = p.isEnabled();
+  mResidual = p.residual();
+  mId = p.id();
 }
 
 QgsGeorefDataPoint::~QgsGeorefDataPoint()

Modified: trunk/qgis/src/plugins/georeferencer/qgsgeorefdatapoint.h
===================================================================
--- trunk/qgis/src/plugins/georeferencer/qgsgeorefdatapoint.h	2010-05-07 11:12:48 UTC (rev 13435)
+++ trunk/qgis/src/plugins/georeferencer/qgsgeorefdatapoint.h	2010-05-07 13:32:19 UTC (rev 13436)
@@ -13,6 +13,10 @@
  *                                                                         *
  ***************************************************************************/
 /* $Id$ */
+
+#ifndef QGSGEOREFDATAPOINT_H
+#define QGSGEOREFDATAPOINT_H
+
 #include "qgsmapcanvasitem.h"
 
 class QgsGCPCanvasItem;
@@ -66,3 +70,5 @@
     bool mEnabled;
     QPointF mResidual;
 };
+
+#endif //QGSGEOREFDATAPOINT_H

Modified: trunk/qgis/src/plugins/georeferencer/qgsgeorefplugingui.cpp
===================================================================
--- trunk/qgis/src/plugins/georeferencer/qgsgeorefplugingui.cpp	2010-05-07 11:12:48 UTC (rev 13435)
+++ trunk/qgis/src/plugins/georeferencer/qgsgeorefplugingui.cpp	2010-05-07 13:32:19 UTC (rev 13436)
@@ -23,6 +23,7 @@
 #include <QMouseEvent>
 #include <QPainter>
 #include <QPlainTextEdit>
+#include <QPrinter>
 #include <QProgressDialog>
 #include <QPushButton>
 #include <QSettings>
@@ -32,9 +33,13 @@
 #include "qgslegendinterface.h"
 #include "qgsapplication.h"
 
+#include "qgscomposerlabel.h"
+#include "qgscomposermap.h"
+#include "qgscomposertexttable.h"
 #include "qgsmapcanvas.h"
 #include "qgsmapcoordsdialog.h"
 #include "qgsmaplayerregistry.h"
+#include "qgsmaprenderer.h"
 #include "qgsmaptoolzoom.h"
 #include "qgsmaptoolpan.h"
 
@@ -52,10 +57,26 @@
 
 #include "qgsgeorefconfigdialog.h"
 #include "qgsgeorefdescriptiondialog.h"
+#include "qgsresidualplotitem.h"
 #include "qgstransformsettingsdialog.h"
 
 #include "qgsgeorefplugingui.h"
 
+class QgsGeorefDockWidget : public QDockWidget
+{
+  public:
+    QgsGeorefDockWidget( const QString & title, QWidget * parent = 0, Qt::WindowFlags flags = 0 )
+        : QDockWidget( title, parent, flags )
+    {
+      setObjectName( "GeorefDockWidget" ); // set object name so the position can be saved
+    }
+
+    virtual void closeEvent( QCloseEvent * ev )
+    {
+      deleteLater();
+    }
+};
+
 QgsGeorefPluginGui::QgsGeorefPluginGui( QgisInterface* theQgisInterface, QWidget* parent, Qt::WFlags fl )
     : QMainWindow( parent, fl )
     , mTransformParam( QgsGeorefTransform::InvalidTransform )
@@ -232,7 +253,7 @@
   {
     if ( mLoadInQgis )
     {
-      if ( QgsGeorefTransform::Linear == mTransformParam )
+      if ( mModifiedRasterFileName.isEmpty() )
       {
         mIface->addRasterLayer( mRasterFileName );
       }
@@ -264,7 +285,7 @@
   }
 
   d.getTransformSettings( mTransformParam, mResamplingMethod, mCompressionMethod,
-                          mModifiedRasterFileName, mProjection, mUseZeroForTrans, mLoadInQgis, mUserResX, mUserResY );
+                          mModifiedRasterFileName, mProjection, mPdfOutputFile, mUseZeroForTrans, mLoadInQgis, mUserResX, mUserResY );
   mTransformParamLabel->setText( tr( "Transform: " ) + convertTransformEnumToString( mTransformParam ) );
   mGeorefTransform.selectTransformParametrisation( mTransformParam );
   mGCPListWidget->setGeorefTransform( &mGeorefTransform );
@@ -543,9 +564,11 @@
 void QgsGeorefPluginGui::showGeorefConfigDialog()
 {
   QgsGeorefConfigDialog config;
-  config.exec();
-  mCanvas->refresh();
-  mIface->mapCanvas()->refresh();
+  if ( config.exec() == QDialog::Accepted )
+  {
+    mCanvas->refresh();
+    mIface->mapCanvas()->refresh();
+  }
 }
 
 // Info slots
@@ -1042,11 +1065,12 @@
   if ( !checkReadyGeoref() )
     return false;
 
-  if ( QgsGeorefTransform::Linear == mGeorefTransform.transformParametrisation() )
+  if ( mModifiedRasterFileName.isEmpty() && ( QgsGeorefTransform::Linear == mGeorefTransform.transformParametrisation() || \
+       QgsGeorefTransform::Helmert == mGeorefTransform.transformParametrisation() ) )
   {
     QgsPoint origin;
-    double pixelXSize, pixelYSize;
-    if ( !mGeorefTransform.getLinearOriginScale( origin, pixelXSize, pixelYSize ) )
+    double pixelXSize, pixelYSize, rotation;
+    if ( !mGeorefTransform.getOriginScaleRotation( origin, pixelXSize, pixelYSize, rotation ) )
     {
       QMessageBox::information( this, tr( "Info" ),
                                 tr( "Failed to get linear transform parameters" ) );
@@ -1076,7 +1100,11 @@
       return false;
     }
 
-    return writeWorldFile( origin, pixelXSize, pixelYSize );
+    bool success = writeWorldFile( origin, pixelXSize, pixelYSize, rotation );
+    if ( success && !mPdfOutputFile.isEmpty() )
+    {
+      writePDFReportFile( mPdfOutputFile, mGeorefTransform );
+    }
   }
   else // Helmert, Polinom 1, Polinom 2, Polinom 3
   {
@@ -1097,12 +1125,16 @@
     }
     else // 1 all right
     {
+      if ( !mPdfOutputFile.isEmpty() )
+      {
+        writePDFReportFile( mPdfOutputFile, mGeorefTransform );
+      }
       return true;
     }
   }
 }
 
-bool QgsGeorefPluginGui::writeWorldFile( QgsPoint origin, double pixelXSize, double pixelYSize )
+bool QgsGeorefPluginGui::writeWorldFile( QgsPoint origin, double pixelXSize, double pixelYSize, double rotation )
 {
   // write the world file
   QFile file( mWorldFileName );
@@ -1112,16 +1144,233 @@
                            tr( "Could not write to %1" ).arg( mWorldFileName ) );
     return false;
   }
+
+  double rotationX = 0;
+  double rotationY = 0;
+
+  if ( !doubleNear( rotation, 0.0 ) )
+  {
+    rotationX = pixelXSize * sin( rotation );
+    rotationY = pixelYSize * sin( rotation );
+    pixelXSize *= cos( rotation );
+    pixelYSize *= cos( rotation );
+  }
+
   QTextStream stream( &file );
   stream << QString::number( pixelXSize, 'f', 15 ) << endl
-  << 0 << endl
-  << 0 << endl
+  << rotationX << endl
+  << rotationY << endl
   << QString::number( -pixelYSize, 'f', 15 ) << endl
   << QString::number( origin.x(), 'f', 15 ) << endl
   << QString::number( origin.y(), 'f', 15 ) << endl;
   return true;
 }
 
+bool QgsGeorefPluginGui::writePDFReportFile( const QString& fileName, const QgsGeorefTransform& transform )
+{
+  if ( !mCanvas )
+  {
+    return false;
+  }
+
+  QgsMapRenderer* canvasRenderer = mCanvas->mapRenderer();
+  if ( !canvasRenderer )
+  {
+    return false;
+  }
+
+  QPrinter printer;
+  printer.setOutputFormat( QPrinter::PdfFormat );
+  printer.setOutputFileName( fileName );
+
+  //create composition A4 with 300 dpi
+  QgsComposition* composition = new QgsComposition( mCanvas->mapRenderer() );
+  composition->setPaperSize( 210, 297 ); //A4
+  composition->setPrintResolution( 300 );
+  printer.setPaperSize( QSizeF( composition->paperWidth(), composition->paperHeight() ), QPrinter::Millimeter );
+
+  //title
+  QFileInfo rasterFi( mRasterFileName );
+  QgsComposerLabel* titleLabel = new QgsComposerLabel( composition );
+  titleLabel->setText( rasterFi.fileName() );
+  composition->addItem( titleLabel );
+  titleLabel->setSceneRect( QRectF( 10, 5, composition->paperWidth(), 8 ) );
+  titleLabel->setFrame( false );
+
+  //composer map
+  QgsComposerMap* composerMap = new QgsComposerMap( composition, 10, titleLabel->rect().bottom() + titleLabel->transform().dy(), 190, 277 );
+  composerMap->setLayerSet( canvasRenderer->layerSet() );
+  composerMap->setNewExtent( mCanvas->extent() );
+  composerMap->setMapCanvas( mCanvas );
+  composition->addItem( composerMap );
+  printer.setFullPage( true );
+  printer.setColorMode( QPrinter::Color );
+
+  QgsComposerTextTable* parameterTable = 0;
+  double scaleX, scaleY, rotation;
+  QgsPoint origin;
+
+  QgsComposerLabel* parameterLabel = 0;
+  //transformation that involves only scaling and rotation (linear or helmert) ?
+  bool wldTransform = transform.getOriginScaleRotation( origin, scaleX, scaleY, rotation );
+
+  //consider rotation in scale parameter
+  double wldScaleX = scaleX;
+  double wldScaleY = scaleY;
+  if ( wldTransform && !doubleNear( rotation, 0.0 ) )
+  {
+    wldScaleX *= cos( rotation );
+    wldScaleY *= cos( rotation );
+  }
+
+  if ( wldTransform )
+  {
+    parameterLabel = new QgsComposerLabel( composition );
+    parameterLabel->setText( tr( "Transformation parameters" ) );
+    parameterLabel->adjustSizeToText();
+    composition->addItem( parameterLabel );
+    parameterLabel->setSceneRect( QRectF( 10, composerMap->rect().bottom() + composerMap->transform().dy() + 5, composition->paperWidth(), 8 ) );
+    parameterLabel->setFrame( false );
+
+    //calculate mean error (in map units)
+    double meanError = 0;
+    if ( mPoints.size() > 4 )
+    {
+      double sumVxSquare = 0;
+      double sumVySquare = 0;
+      double resXMap, resYMap;
+
+      int nPointsEnabled = 0;
+      QgsGCPList::const_iterator gcpIt = mPoints.constBegin();
+      for ( ; gcpIt != mPoints.constEnd(); ++gcpIt )
+      {
+        if (( *gcpIt )->isEnabled() )
+        {
+          resXMap = ( *gcpIt )->residual().x() * wldScaleX;
+          resYMap = ( *gcpIt )->residual().x() * wldScaleY;
+          sumVxSquare += ( resXMap * resXMap );
+          sumVySquare += ( resYMap * resYMap );
+          ++nPointsEnabled;
+        }
+      }
+
+      if ( nPointsEnabled > 4 )
+      {
+        meanError = sqrt(( sumVxSquare + sumVySquare ) / ( 2 * nPointsEnabled - 4 ) ) * sqrt( 2 );
+      }
+    }
+
+
+    parameterTable = new QgsComposerTextTable( composition );
+    QStringList headers;
+    headers << tr( "Translation x" ) << tr( "Translation y" ) << tr( "Scale x" ) << tr( "Scale y" ) << tr( "Rotation [degrees]" ) << tr( "Mean error [map units]" );
+    parameterTable->setHeaderLabels( headers );
+    QStringList row;
+    row << QString::number( origin.x() ) << QString::number( origin.y() ) << QString::number( scaleX ) << QString::number( scaleY ) << QString::number( rotation * 180 / M_PI ) << QString::number( meanError );
+    parameterTable->addRow( row );
+    composition->addItem( parameterTable );
+    parameterTable->setSceneRect( QRectF( 10, parameterLabel->rect().bottom() + parameterLabel->transform().dy() + 5, 50, 20 ) );
+    parameterTable->setGridStrokeWidth( 0.1 );
+    parameterTable->adjustFrameToSize();
+  }
+
+  QGraphicsRectItem* previousItem = composerMap;
+  if ( parameterTable )
+  {
+    previousItem = parameterTable;
+  }
+
+  QgsComposerLabel* residualLabel = new QgsComposerLabel( composition );
+  residualLabel->setText( tr( "Residuals" ) );
+  composition->addItem( residualLabel );
+  residualLabel->setSceneRect( QRectF( 10, previousItem->rect().bottom() + previousItem->transform().dy() + 5, composition->paperWidth(), 6 ) );
+  residualLabel->setFrame( false );
+
+  //residual plot
+  QgsResidualPlotItem* resPlotItem = new QgsResidualPlotItem( composition );
+  composition->addItem( resPlotItem );
+  resPlotItem->setSceneRect( QRectF( 10, residualLabel->rect().bottom() + residualLabel->transform().dy() + 5, composerMap->rect().width(), composerMap->rect().height() ) );
+  resPlotItem->setExtent( composerMap->extent() );
+  resPlotItem->setGCPList( mPoints );
+
+  //convert residual scale bar plot to map units if scaling is equal in x- and y-direction (e.g. helmert)
+  if ( wldTransform )
+  {
+    if ( doubleNear( wldScaleX, wldScaleY ) )
+    {
+      resPlotItem->setPixelToMapUnits( scaleX );
+      resPlotItem->setConvertScaleToMapUnits( true );
+    }
+  }
+
+  QString residualUnits;
+  if ( wldTransform )
+  {
+    residualUnits = tr( "map units" );
+  }
+  else
+  {
+    residualUnits = tr( "pixels" );
+  }
+  QgsComposerTextTable* gcpTable = new QgsComposerTextTable( composition );
+  QStringList gcpHeader;
+  gcpHeader << "id" << "enabled" << "pixelCoordX" << "pixelCoordY" << "mapCoordX" << "mapCoordY" << "resX[" + residualUnits + "]" << "resY[" + residualUnits + "]" << "resTot[" + residualUnits + "]";
+  gcpTable->setHeaderLabels( gcpHeader );
+
+  QgsGCPList::const_iterator gcpIt = mPoints.constBegin();
+  for ( ; gcpIt != mPoints.constEnd(); ++gcpIt )
+  {
+    QStringList currentGCPStrings;
+    QPointF residual = ( *gcpIt )->residual();
+    double residualX = residual.x();
+    if ( wldTransform )
+    {
+      residualX *= wldScaleX;
+    }
+    double residualY = residual.y();
+    if ( wldTransform )
+    {
+      residualY *= wldScaleY;
+    }
+    double residualTot = sqrt( residualX * residualX + residualY * residualY );
+
+    currentGCPStrings << QString::number(( *gcpIt )->id() );
+    if (( *gcpIt )->isEnabled() )
+    {
+      currentGCPStrings << tr( "yes" );
+    }
+    else
+    {
+      currentGCPStrings << tr( "no" );
+    }
+    currentGCPStrings << QString::number(( *gcpIt )->pixelCoords().x() ) << QString::number(( *gcpIt )->pixelCoords().y() ) << QString::number(( *gcpIt )->mapCoords().x() )\
+    <<  QString::number(( *gcpIt )->mapCoords().y() ) <<  QString::number( residualX ) <<  QString::number( residualY ) << QString::number( residualTot );
+    gcpTable->addRow( currentGCPStrings );
+  }
+
+  composition->addItem( gcpTable );
+
+  gcpTable->setSceneRect( QRectF( 10,  resPlotItem->rect().bottom() + resPlotItem->transform().dy() + 5, 170, 100 ) );
+  gcpTable->setGridStrokeWidth( 0.1 );
+
+  printer.setResolution( composition->printResolution() );
+  QPainter p( &printer );
+  composition->setPlotStyle( QgsComposition::Print );
+  QRectF paperRectMM = printer.pageRect( QPrinter::Millimeter );
+  QRectF paperRectPixel = printer.pageRect( QPrinter::DevicePixel );
+  composition->render( &p, paperRectPixel, paperRectMM );
+
+  delete titleLabel;
+  delete parameterLabel;
+  delete residualLabel;
+  delete resPlotItem;
+  delete parameterTable;
+  delete gcpTable;
+  delete composerMap;
+  delete composition;
+  return true;
+}
+
 // Gdal script
 void QgsGeorefPluginGui::showGDALScript( int argNum... )
 {
@@ -1248,7 +1497,8 @@
       continue;
     }
 
-    if ( mModifiedRasterFileName.isEmpty() && QgsGeorefTransform::Linear != mTransformParam )
+    //MH: helmert transformation without warping disabled until qgis is able to read rotated rasters efficiently
+    if ( mModifiedRasterFileName.isEmpty() && QgsGeorefTransform::Linear != mTransformParam /*&& QgsGeorefTransform::Helmert != mTransformParam*/ )
     {
       QMessageBox::information( this, tr( "Info" ), tr( "Please set output raster name" ) );
       if ( !getTransformSettings() )

Modified: trunk/qgis/src/plugins/georeferencer/qgsgeorefplugingui.h
===================================================================
--- trunk/qgis/src/plugins/georeferencer/qgsgeorefplugingui.h	2010-05-07 11:12:48 UTC (rev 13435)
+++ trunk/qgis/src/plugins/georeferencer/qgsgeorefplugingui.h	2010-05-07 13:32:19 UTC (rev 13436)
@@ -131,13 +131,14 @@
 
     // georeference
     bool georeference();
-    bool writeWorldFile( QgsPoint origin, double pixelXSize, double pixelYSize );
+    bool writeWorldFile( QgsPoint origin, double pixelXSize, double pixelYSize, double rotation );
+    bool writePDFReportFile( const QString& fileName, const QgsGeorefTransform& transform );
 
     // gdal script
     void showGDALScript( int argNum... );
-    QString generateGDALtranslateCommand( bool generateTFW = true);   
+    QString generateGDALtranslateCommand( bool generateTFW = true );
     /* Generate command-line for gdalwarp based on current GCPs and given parameters.
-     * For values in the range 1 to 3, the parameter "order" prescribes the degree of the interpolating polynomials to use, 
+     * For values in the range 1 to 3, the parameter "order" prescribes the degree of the interpolating polynomials to use,
      * a value of -1 indicates that thin plate spline interpolation should be used for warping.*/
     QString generateGDALwarpCommand( QString resampling, QString compress, bool useZeroForTrans, int order,
                                      double targetResX, double targetResY );
@@ -177,6 +178,7 @@
     QString mTranslatedRasterFileName;
     QString mGCPpointsFileName;
     QString mProjection;
+    QString mPdfOutputFile;
     double  mUserResX, mUserResY;  // User specified target scale
 
     QgsGeorefTransform::TransformParametrisation mTransformParam;

Modified: trunk/qgis/src/plugins/georeferencer/qgsgeoreftransform.cpp
===================================================================
--- trunk/qgis/src/plugins/georeferencer/qgsgeoreftransform.cpp	2010-05-07 11:12:48 UTC (rev 13435)
+++ trunk/qgis/src/plugins/georeferencer/qgsgeoreftransform.cpp	2010-05-07 13:32:19 UTC (rev 13436)
@@ -71,6 +71,7 @@
       double   angle;
     };
 
+    bool getOriginScaleRotation( QgsPoint &origin, double& scale, double& rotation ) const;
     bool updateParametersFromGCPs( const std::vector<QgsPoint> &mapCoords, const std::vector<QgsPoint> &pixelCoords );
     uint getMinimumGCPCount() const;
 
@@ -246,7 +247,29 @@
   return dynamic_cast<QgsLinearGeorefTransform *>( mGeorefTransformImplementation )->getOriginScale( origin, scaleX, scaleY );
 }
 
+bool QgsGeorefTransform::getOriginScaleRotation( QgsPoint &origin, double &scaleX, double &scaleY, double& rotation ) const
+{
 
+  if ( mTransformParametrisation == Linear )
+  {
+    rotation = 0.0;
+    return dynamic_cast<QgsLinearGeorefTransform *>( mGeorefTransformImplementation )->getOriginScale( origin, scaleX, scaleY );
+  }
+  else if ( mTransformParametrisation == Helmert )
+  {
+    double scale;
+    if ( ! dynamic_cast<QgsHelmertGeorefTransform*>( mGeorefTransformImplementation )->getOriginScaleRotation( origin, scale, rotation ) )
+    {
+      return false;
+    }
+    scaleX = scale;
+    scaleY = scale;
+    return true;
+  }
+  return false;
+}
+
+
 bool QgsGeorefTransform::gdal_transform( const QgsPoint &src, QgsPoint &dst, int dstToSrc ) const
 {
   GDALTransformerFunc t = GDALTransformer();
@@ -357,6 +380,13 @@
   return ( void* )&mHelmertParameters;
 }
 
+bool QgsHelmertGeorefTransform::getOriginScaleRotation( QgsPoint &origin, double& scale, double& rotation ) const
+{
+  origin = mHelmertParameters.origin;
+  scale = mHelmertParameters.scale;
+  rotation = mHelmertParameters.angle;
+  return true;
+}
 
 int QgsHelmertGeorefTransform::helmert_transform( void *pTransformerArg, int bDstToSrc, int nPointCount,
     double *x, double *y, double *z, int *panSuccess )

Modified: trunk/qgis/src/plugins/georeferencer/qgsgeoreftransform.h
===================================================================
--- trunk/qgis/src/plugins/georeferencer/qgsgeoreftransform.h	2010-05-07 11:12:48 UTC (rev 13435)
+++ trunk/qgis/src/plugins/georeferencer/qgsgeoreftransform.h	2010-05-07 13:32:19 UTC (rev 13436)
@@ -129,6 +129,10 @@
 
     //! \brief Returns origin and scale if this is a linear transform, fails otherwise.
     bool getLinearOriginScale( QgsPoint &origin, double &scaleX, double &scaleY ) const;
+
+    //! \brief Returns origin, scale and rotation for linear and helmert transform, fails otherwise.
+    bool getOriginScaleRotation( QgsPoint &origin, double &scaleX, double &scaleY, double& rotation ) const;
+
   private:
     // shallow copy constructor
     QgsGeorefTransform( const QgsGeorefTransform &other );

Modified: trunk/qgis/src/plugins/georeferencer/qgstransformsettingsdialog.cpp
===================================================================
--- trunk/qgis/src/plugins/georeferencer/qgstransformsettingsdialog.cpp	2010-05-07 11:12:48 UTC (rev 13435)
+++ trunk/qgis/src/plugins/georeferencer/qgstransformsettingsdialog.cpp	2010-05-07 13:32:19 UTC (rev 13436)
@@ -34,13 +34,13 @@
 {
   setupUi( this );
 
-  cmbTransformType->addItem( tr( "Linear" ) ,           (int)QgsGeorefTransform::Linear ) ;
-  cmbTransformType->addItem( tr( "Helmert" ),           (int)QgsGeorefTransform::Helmert );
-  cmbTransformType->addItem( tr( "Polynomial 1" ),      (int)QgsGeorefTransform::PolynomialOrder1 );
-  cmbTransformType->addItem( tr( "Polynomial 2" ),      (int)QgsGeorefTransform::PolynomialOrder2 );
-  cmbTransformType->addItem( tr( "Polynomial 3" ),      (int)QgsGeorefTransform::PolynomialOrder3 );
-  cmbTransformType->addItem( tr( "Thin Plate Spline" ), (int)QgsGeorefTransform::ThinPlateSpline );
-  
+  cmbTransformType->addItem( tr( "Linear" ) , ( int )QgsGeorefTransform::Linear ) ;
+  cmbTransformType->addItem( tr( "Helmert" ), ( int )QgsGeorefTransform::Helmert );
+  cmbTransformType->addItem( tr( "Polynomial 1" ), ( int )QgsGeorefTransform::PolynomialOrder1 );
+  cmbTransformType->addItem( tr( "Polynomial 2" ), ( int )QgsGeorefTransform::PolynomialOrder2 );
+  cmbTransformType->addItem( tr( "Polynomial 3" ), ( int )QgsGeorefTransform::PolynomialOrder3 );
+  cmbTransformType->addItem( tr( "Thin Plate Spline" ), ( int )QgsGeorefTransform::ThinPlateSpline );
+
   leOutputRaster->setText( output );
 
   mRegExpValidator = new QRegExpValidator( QRegExp( "(^epsg:{1}\\s*\\d+)|(^\\+proj.*)", Qt::CaseInsensitive ), leTargetSRS );
@@ -70,12 +70,13 @@
 
   tbnOutputRaster->setIcon( getThemeIcon( "/mPushButtonFileOpen.png" ) );
   tbnTargetSRS->setIcon( getThemeIcon( "/mPushButtonTargetSRSDisabled.png" ) );
+  tbnReportFile->setIcon( getThemeIcon( "/mActionSaveAsPDF.png" ) );
 }
 
 void QgsTransformSettingsDialog::getTransformSettings( QgsGeorefTransform::TransformParametrisation &tp,
     QgsImageWarper::ResamplingMethod &rm,
     QString &comprMethod, QString &raster,
-    QString &proj, bool &zt, bool &loadInQgis,
+    QString &proj, QString& pdfReportFile, bool &zt, bool &loadInQgis,
     double& resX, double& resY )
 {
   if ( cmbTransformType->currentIndex() == -1 )
@@ -87,6 +88,7 @@
   comprMethod = cmbCompressionComboBox->currentText();
   raster = leOutputRaster->text();
   proj = leTargetSRS->text();
+  pdfReportFile = mReportFileLineEdit->text();
   zt = cbxZeroAsTrans->isChecked();
   loadInQgis = cbxLoadInQgisWhenDone->isChecked();
   resX = 0.0;
@@ -130,7 +132,7 @@
   int minGCPpoints;
   if ( checkGCPpoints( cmbTransformType->currentIndex(), minGCPpoints ) )
   {
-    if ( leOutputRaster->text().isEmpty() && cmbTransformType->currentIndex() != 0 )
+    if ( leOutputRaster->text().isEmpty() && cmbTransformType->currentIndex() > 1 )
     {
       QMessageBox::information( this, tr( "Info" ), tr( "Please set output name" ) );
       return;
@@ -156,6 +158,12 @@
   s.setValue( "/Plugin-GeoReferencer/user_specified_resolution", cbxUserResolution->isChecked() );
   s.setValue( "/Plugin-GeoReferencer/user_specified_resx", dsbHorizRes->value() );
   s.setValue( "/Plugin-GeoReferencer/user_specified_resy", dsbVerticalRes->value() );
+  QString pdfReportFileName = mReportFileLineEdit->text();
+  if ( !pdfReportFileName.isEmpty() )
+  {
+    QFileInfo fi( pdfReportFileName );
+    s.setValue( "/Plugin-GeoReferencer/lastPDFReportDir", fi.absolutePath() );
+  }
 }
 
 void QgsTransformSettingsDialog::on_tbnOutputRaster_clicked()
@@ -201,6 +209,17 @@
   }
 }
 
+void QgsTransformSettingsDialog::on_tbnReportFile_clicked()
+{
+  QSettings s;
+  QString myLastUsedDir = s.value( "/Plugin-GeoReferencer/lastPDFReportDir", "" ).toString();
+  QString outputFileName = QFileDialog::getSaveFileName( 0, tr( "Select save PDF file" ), myLastUsedDir, tr( "PDF Format" ) + " (*.pdf *PDF)" );
+  if ( !outputFileName.isNull() )
+  {
+    mReportFileLineEdit->setText( outputFileName );
+  }
+}
+
 void QgsTransformSettingsDialog::on_leTargetSRS_textChanged( const QString &text )
 {
   QString t = text;

Modified: trunk/qgis/src/plugins/georeferencer/qgstransformsettingsdialog.h
===================================================================
--- trunk/qgis/src/plugins/georeferencer/qgstransformsettingsdialog.h	2010-05-07 11:12:48 UTC (rev 13435)
+++ trunk/qgis/src/plugins/georeferencer/qgstransformsettingsdialog.h	2010-05-07 13:32:19 UTC (rev 13436)
@@ -32,7 +32,7 @@
                                 int countGCPpoints, QWidget *parent = 0 );
     void getTransformSettings( QgsGeorefTransform::TransformParametrisation &tp,
                                QgsImageWarper::ResamplingMethod &rm, QString &comprMethod,
-                               QString &raster, QString &proj, bool &zt, bool &loadInQgis,
+                               QString &raster, QString &proj, QString& pdfReportFile, bool &zt, bool &loadInQgis,
                                double& resX, double& resY );
     static void resetSettings();
 
@@ -43,6 +43,7 @@
   private slots:
     void on_tbnOutputRaster_clicked();
     void on_tbnTargetSRS_clicked();
+    void on_tbnReportFile_clicked();
     void on_leTargetSRS_textChanged( const QString &text );
     QIcon getThemeIcon( const QString &theName );
 

Modified: trunk/qgis/src/plugins/georeferencer/qgstransformsettingsdialogbase.ui
===================================================================
--- trunk/qgis/src/plugins/georeferencer/qgstransformsettingsdialogbase.ui	2010-05-07 11:12:48 UTC (rev 13435)
+++ trunk/qgis/src/plugins/georeferencer/qgstransformsettingsdialogbase.ui	2010-05-07 13:32:19 UTC (rev 13436)
@@ -6,19 +6,16 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>307</width>
-    <height>328</height>
+    <width>356</width>
+    <height>381</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>Transformation settings</string>
   </property>
-  <layout class="QVBoxLayout" name="verticalLayout">
-   <item>
-    <layout class="QFormLayout" name="formLayout">
-     <property name="fieldGrowthPolicy">
-      <enum>QFormLayout::ExpandingFieldsGrow</enum>
-     </property>
+  <layout class="QGridLayout" name="gridLayout_2">
+   <item row="0" column="0">
+    <layout class="QGridLayout" name="gridLayout">
      <item row="0" column="0">
       <widget class="QLabel" name="label">
        <property name="text">
@@ -161,27 +158,61 @@
       </layout>
      </item>
      <item row="5" column="0">
+      <widget class="QLabel" name="label_6">
+       <property name="text">
+        <string>Generate pdf report:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="5" column="1">
+      <layout class="QHBoxLayout" name="horizontalLayout_3">
+       <item>
+        <widget class="QLineEdit" name="mReportFileLineEdit"/>
+       </item>
+       <item>
+        <widget class="QToolButton" name="tbnReportFile">
+         <property name="text">
+          <string>...</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item row="6" column="0">
       <widget class="QCheckBox" name="cbxUserResolution">
        <property name="text">
         <string>Set Target Resolution</string>
        </property>
       </widget>
      </item>
-     <item row="6" column="0">
+     <item row="7" column="0">
       <widget class="QLabel" name="label_4">
        <property name="text">
         <string>Horizontal</string>
        </property>
       </widget>
      </item>
-     <item row="7" column="0">
+     <item row="7" column="1">
+      <widget class="QgsValidatedDoubleSpinBox" name="dsbHorizRes">
+       <property name="decimals">
+        <number>5</number>
+       </property>
+       <property name="minimum">
+        <double>0.000000000000000</double>
+       </property>
+       <property name="maximum">
+        <double>999999.000000000000000</double>
+       </property>
+      </widget>
+     </item>
+     <item row="8" column="0">
       <widget class="QLabel" name="label_5">
        <property name="text">
         <string>Vertical</string>
        </property>
       </widget>
      </item>
-     <item row="7" column="1">
+     <item row="8" column="1">
       <widget class="QgsValidatedDoubleSpinBox" name="dsbVerticalRes">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
@@ -203,22 +234,9 @@
        </property>
       </widget>
      </item>
-     <item row="6" column="1">
-      <widget class="QgsValidatedDoubleSpinBox" name="dsbHorizRes">
-       <property name="decimals">
-        <number>5</number>
-       </property>
-       <property name="minimum">
-        <double>0.000000000000000</double>
-       </property>
-       <property name="maximum">
-        <double>999999.000000000000000</double>
-       </property>
-      </widget>
-     </item>
     </layout>
    </item>
-   <item>
+   <item row="1" column="0">
     <widget class="QCheckBox" name="cbxZeroAsTrans">
      <property name="text">
       <string>Use 0 for transparency when needed</string>
@@ -228,14 +246,14 @@
      </property>
     </widget>
    </item>
-   <item>
+   <item row="2" column="0">
     <widget class="QCheckBox" name="cbxLoadInQgisWhenDone">
      <property name="text">
       <string>Load in QGIS when done</string>
      </property>
     </widget>
    </item>
-   <item>
+   <item row="3" column="0">
     <widget class="QDialogButtonBox" name="buttonBox">
      <property name="orientation">
       <enum>Qt::Horizontal</enum>



More information about the QGIS-commit mailing list