Index: src/plugins/georeferencer/qgsgeorefplugingui.h =================================================================== --- src/plugins/georeferencer/qgsgeorefplugingui.h (Revision 13528) +++ src/plugins/georeferencer/qgsgeorefplugingui.h (Arbeitskopie) @@ -102,6 +102,8 @@ void showMouseCoords( const QgsPoint pt ); void updateMouseCoordinatePrecision(); + bool updateGeorefTransform(); + private: enum SaveGCPs { @@ -133,6 +135,7 @@ bool georeference(); bool writeWorldFile( QgsPoint origin, double pixelXSize, double pixelYSize, double rotation ); bool writePDFReportFile( const QString& fileName, const QgsGeorefTransform& transform ); + void updateTransformParamLabel(); // gdal script void showGDALScript( int argNum... ); @@ -145,7 +148,6 @@ // utils bool checkReadyGeoref(); - bool updateGeorefTransform(); QgsRectangle transformViewportBoundingBox( const QgsRectangle &canvasExtent, const QgsGeorefTransform &t, bool rasterToWorld = true, uint numSamples = 4 ); QString convertTransformEnumToString( QgsGeorefTransform::TransformParametrisation transform ); @@ -158,6 +160,10 @@ void logTransformOptions(); void logRequaredGCPs(); void clearGCPData(); + /**Calculates mean transformation error + @param error out: the mean error + @return true in case of success*/ + bool calculateMeanError( double& error ) const; QMenu *mPanelMenu; Index: src/plugins/georeferencer/qgsgcplistmodel.cpp =================================================================== --- src/plugins/georeferencer/qgsgcplistmodel.cpp (Revision 13528) +++ src/plugins/georeferencer/qgsgcplistmodel.cpp (Arbeitskopie) @@ -16,7 +16,7 @@ #include "qgsgcplist.h" #include "qgsgcplistmodel.h" - +#include "qgis.h" #include "qgsgeorefdatapoint.h" #include "qgsgeoreftransform.h" @@ -85,15 +85,11 @@ if ( !mGCPList ) return; -// // Setup table header - QStringList itemLabels; -// // Set column headers - itemLabels << "on/off" << "id" << "srcX" << "srcY" << "dstX" << "dstY" << "dX" << "dY" << "residual"; -// setColumnCount(itemLabels.size()); - setHorizontalHeaderLabels( itemLabels ); - setRowCount( mGCPList->size() ); + bool bTransformUpdated = false; + bool wldTransform = false; + double wldScaleX, wldScaleY, rotation; + QgsPoint origin; - bool bTransformUpdated = false; if ( mGeorefTransform ) { vector mapCoords, pixelCoords; @@ -101,8 +97,32 @@ // TODO: the parameters should probable be updated externally (by user interaction) bTransformUpdated = mGeorefTransform->updateParametersFromGCPs( mapCoords, pixelCoords ); + //transformation that involves only scaling and rotation (linear or helmert) ? + wldTransform = mGeorefTransform->getOriginScaleRotation( origin, wldScaleX, wldScaleY, rotation ); + if ( wldTransform && !doubleNear( rotation, 0.0 ) ) + { + wldScaleX *= cos( rotation ); + wldScaleY *= cos( rotation ); + } + if ( wldTransform ) + { + + } } + // // Setup table header + QStringList itemLabels; + if ( wldTransform ) + { + itemLabels << "on/off" << "id" << "srcX" << "srcY" << "dstX" << "dstY" << QString( "dX[" ) + tr( "map units" ) + "]" << QString( "dY[" ) + tr( "map units" ) + "]" << "residual"; + } + else + { + itemLabels << "on/off" << "id" << "srcX" << "srcY" << "dstX" << "dstY" << QString( "dX[" ) + tr( "pixels" ) + "]" << QString( "dY[" ) + tr( "pixels" ) + "]" << "residual"; + } + setHorizontalHeaderLabels( itemLabels ); + setRowCount( mGCPList->size() ); + for ( int i = 0; i < mGCPList->sizeAll(); ++i ) { int j = 0; @@ -135,8 +155,13 @@ // 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() ); + dX = ( dst.x() - p->pixelCoords().x() ); dY = -( dst.y() - p->pixelCoords().y() ); + if ( wldTransform ) + { + dX *= wldScaleX; + dY *= wldScaleY; + } residual = sqrt( dX * dX + dY * dY ); } else @@ -152,7 +177,7 @@ if ( residual >= 0.f ) { setItem( i, j++, QGSSTANDARDITEM( dX ) /*create_item(dX)*/ ); - setItem( i, j++, QGSSTANDARDITEM( dY ) /*create_item(-dY)*/); + setItem( i, j++, QGSSTANDARDITEM( dY ) /*create_item(-dY)*/ ); setItem( i, j++, QGSSTANDARDITEM( residual ) /*create_item(residual)*/ ); } else Index: src/plugins/georeferencer/qgsgeorefplugingui.cpp =================================================================== --- src/plugins/georeferencer/qgsgeorefplugingui.cpp (Revision 13528) +++ src/plugins/georeferencer/qgsgeorefplugingui.cpp (Arbeitskopie) @@ -108,7 +108,6 @@ QgsGeorefPluginGui::~QgsGeorefPluginGui() { - QgsTransformSettingsDialog::resetSettings(); clearGCPData(); // delete layer (and don't signal it as it's our private layer) @@ -307,6 +306,7 @@ mActionLinkQGisToGeoref->setEnabled( false ); } + updateTransformParamLabel(); return true; } @@ -443,6 +443,7 @@ } connect( mCanvas, SIGNAL( extentsChanged() ), pnt, SLOT( updateCoords() ) ); + updateGeorefTransform(); // if (verbose) // logRequaredGCPs(); @@ -469,6 +470,7 @@ break; } } + updateGeorefTransform(); } void QgsGeorefPluginGui::deleteDataPoint( int index ) @@ -476,6 +478,7 @@ mGCPListWidget->model()->removeRow( index ); delete mPoints.takeAt( index ); mGCPListWidget->updateGCPList(); + updateGeorefTransform(); } void QgsGeorefPluginGui::selectPoint( const QPoint &p ) @@ -890,12 +893,24 @@ this, SLOT( replaceDataPoint( QgsGeorefDataPoint*, int ) ) ); connect( mGCPListWidget, SIGNAL( deleteDataPoint( int ) ), this, SLOT( deleteDataPoint( int ) ) ); + connect( mGCPListWidget, SIGNAL( pointEnabled( QgsGeorefDataPoint*, int ) ), this, SLOT( updateGeorefTransform() ) ); } void QgsGeorefPluginGui::createStatusBar() { QFont myFont( "Arial", 9 ); + mTransformParamLabel = new QLabel( statusBar() ); + mTransformParamLabel->setFont( myFont ); + mTransformParamLabel->setMinimumWidth( 10 ); + mTransformParamLabel->setMaximumHeight( 20 ); + mTransformParamLabel->setMargin( 3 ); + mTransformParamLabel->setAlignment( Qt::AlignCenter ); + mTransformParamLabel->setFrameStyle( QFrame::NoFrame ); + mTransformParamLabel->setText( tr( "Transform: " ) + convertTransformEnumToString( mTransformParam ) ); + mTransformParamLabel->setToolTip( tr( "Current transform parametrisation" ) ); + statusBar()->addPermanentWidget( mTransformParamLabel, 0 ); + mCoordsLabel = new QLabel( QString(), statusBar() ); mCoordsLabel->setFont( myFont ); mCoordsLabel->setMinimumWidth( 10 ); @@ -907,17 +922,6 @@ mCoordsLabel->setText( tr( "Coordinate: " ) ); mCoordsLabel->setToolTip( tr( "Current map coordinate" ) ); statusBar()->addPermanentWidget( mCoordsLabel, 0 ); - - mTransformParamLabel = new QLabel( statusBar() ); - mTransformParamLabel->setFont( myFont ); - mTransformParamLabel->setMinimumWidth( 10 ); - mTransformParamLabel->setMaximumHeight( 20 ); - mTransformParamLabel->setMargin( 3 ); - mTransformParamLabel->setAlignment( Qt::AlignCenter ); - mTransformParamLabel->setFrameStyle( QFrame::NoFrame ); - mTransformParamLabel->setText( tr( "Transform: " ) + convertTransformEnumToString( mTransformParam ) ); - mTransformParamLabel->setToolTip( tr( "Current transform parametrisation" ) ); - statusBar()->addPermanentWidget( mTransformParamLabel, 0 ); } void QgsGeorefPluginGui::setupConnections() @@ -1168,6 +1172,51 @@ return true; } +bool QgsGeorefPluginGui::calculateMeanError( double& error ) const +{ + if ( mGeorefTransform.transformParametrisation() == QgsGeorefTransform::InvalidTransform ) + { + return false; + } + + int nPointsEnabled = 0; + QgsGCPList::const_iterator gcpIt = mPoints.constBegin(); + for ( ; gcpIt != mPoints.constEnd(); ++gcpIt ) + { + if (( *gcpIt )->isEnabled() ) + { + ++nPointsEnabled; + } + } + + if ( nPointsEnabled == mGeorefTransform.getMinimumGCPCount() ) + { + error = 0; + return true; + } + else if ( nPointsEnabled < mGeorefTransform.getMinimumGCPCount() ) + { + return false; + } + + double sumVxSquare = 0; + double sumVySquare = 0; + double resXMap, resYMap; + + gcpIt = mPoints.constBegin(); + for ( ; gcpIt != mPoints.constEnd(); ++gcpIt ) + { + if (( *gcpIt )->isEnabled() ) + { + sumVxSquare += (( *gcpIt )->residual().x() * ( *gcpIt )->residual().x() ); + sumVySquare += (( *gcpIt )->residual().y() * ( *gcpIt )->residual().y() ); + } + } + + error = sqrt(( sumVxSquare + sumVySquare ) / ( 2 * ( nPointsEnabled - mGeorefTransform.getMinimumGCPCount() ) ) ) * sqrt( 2.0 ); + return true; +} + bool QgsGeorefPluginGui::writePDFReportFile( const QString& fileName, const QgsGeorefTransform& transform ) { if ( !mCanvas ) @@ -1210,7 +1259,24 @@ titleLabel->setFrame( false ); //composer map - QgsComposerMap* composerMap = new QgsComposerMap( composition, 2, titleLabel->rect().bottom() + titleLabel->transform().dy(), 206, 277 ); + QgsRectangle canvasExtent = mCanvas->extent(); + //calculate width and height considering extent aspect ratio and max Width 206, maxHeight 70 + double widthExtentRatio = 206 / canvasExtent.width(); + double heightExtentRatio = 70 / canvasExtent.height(); + double mapWidthMM = 0; + double mapHeightMM = 0; + if ( widthExtentRatio < heightExtentRatio ) + { + mapWidthMM = 206; + mapHeightMM = 206 / canvasExtent.width() * canvasExtent.height(); + } + else + { + mapHeightMM = 70; + mapWidthMM = 70 / canvasExtent.height() * canvasExtent.width(); + } + + QgsComposerMap* composerMap = new QgsComposerMap( composition, 2, titleLabel->rect().bottom() + titleLabel->transform().dy(), mapWidthMM, mapHeightMM ); composerMap->setLayerSet( canvasRenderer->layerSet() ); composerMap->setNewExtent( mCanvas->extent() ); composerMap->setMapCanvas( mCanvas ); @@ -1226,26 +1292,9 @@ //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 ) { - QString parameterTitle = tr( "Transformation parameters" ); - if ( transform.transformParametrisation() == QgsGeorefTransform::Helmert ) - { - parameterTitle += " (Helmert)"; - } - else if ( transform.transformParametrisation() == QgsGeorefTransform::Linear ) - { - parameterTitle += " (Linear)"; - } + QString parameterTitle = tr( "Transformation parameters" ) + QString( " (" ) + convertTransformEnumToString( transform.transformParametrisation() ) + QString( ")" ); parameterLabel = new QgsComposerLabel( composition ); parameterLabel->setFont( titleFont ); parameterLabel->setText( parameterTitle ); @@ -1264,30 +1313,10 @@ } } - //calculate mean error (in map units) + //calculate mean error double meanError = 0; - if ( nPointsEnabled > 2 ) - { - double sumVxSquare = 0; - double sumVySquare = 0; - double resXMap, resYMap; + calculateMeanError( meanError ); - QgsGCPList::const_iterator gcpIt = mPoints.constBegin(); - for ( ; gcpIt != mPoints.constEnd(); ++gcpIt ) - { - if (( *gcpIt )->isEnabled() ) - { - resXMap = ( *gcpIt )->residual().x() * wldScaleX; - resYMap = ( *gcpIt )->residual().y() * wldScaleY; - sumVxSquare += ( resXMap * resXMap ); - sumVySquare += ( resYMap * resYMap ); - } - } - - meanError = sqrt(( sumVxSquare + sumVySquare ) / ( 2 * nPointsEnabled - 4 ) ) * sqrt( 2.0 ); - } - - parameterTable = new QgsComposerTextTable( composition ); parameterTable->setHeaderFont( tableHeaderFont ); parameterTable->setContentFont( tableContentFont ); @@ -1326,7 +1355,7 @@ //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 ) ) + if ( doubleNear( scaleX, scaleX ) ) { resPlotItem->setPixelToMapUnits( scaleX ); resPlotItem->setConvertScaleToMapUnits( true ); @@ -1354,17 +1383,7 @@ { 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 ); + double residualTot = sqrt( residual.x() * residual.x() + residual.y() * residual.y() ); currentGCPStrings << QString::number(( *gcpIt )->id() ); if (( *gcpIt )->isEnabled() ) @@ -1376,7 +1395,7 @@ currentGCPStrings << tr( "no" ); } currentGCPStrings << QString::number(( *gcpIt )->pixelCoords().x(), 'f', 2 ) << QString::number(( *gcpIt )->pixelCoords().y(), 'f', 2 ) << QString::number(( *gcpIt )->mapCoords().x(), 'f', 2 )\ - << QString::number(( *gcpIt )->mapCoords().y(), 'f', 2 ) << QString::number( residualX ) << QString::number( residualY ) << QString::number( residualTot ); + << QString::number(( *gcpIt )->mapCoords().y(), 'f', 2 ) << QString::number( residual.x() ) << QString::number( residual.y() ) << QString::number( residualTot ); gcpTable->addRow( currentGCPStrings ); } @@ -1403,6 +1422,35 @@ return true; } +void QgsGeorefPluginGui::updateTransformParamLabel() +{ + if ( !mTransformParamLabel ) + { + return; + } + + QString transformName = convertTransformEnumToString( mGeorefTransform.transformParametrisation() ); + QString labelString = tr( "Transform: " ) + transformName; + + QgsPoint origin; + double scaleX, scaleY, rotation; + if ( mGeorefTransform.getOriginScaleRotation( origin, scaleX, scaleY, rotation ) ) + { + labelString += " "; + labelString += tr( "Translation (%1, %2)" ).arg( origin.x() ).arg( origin.y() ); labelString += " "; + labelString += tr( "Scale (%1, %2)" ).arg( scaleX ).arg( scaleY ); labelString += " "; + labelString += tr( "Rotation: %1" ).arg( rotation ); + } + + double meanError = 0; + if ( calculateMeanError( meanError ) ) + { + labelString += " "; + labelString += tr( "Mean error: %1" ).arg( meanError ); + } + mTransformParamLabel->setText( labelString ); +} + // Gdal script void QgsGeorefPluginGui::showGDALScript( int argNum... ) { @@ -1565,22 +1613,20 @@ bool QgsGeorefPluginGui::updateGeorefTransform() { - if ( mGCPsDirty || !mGeorefTransform.parametersInitialized() ) + std::vector mapCoords, pixelCoords; + if ( mGCPListWidget->gcpList() ) + mGCPListWidget->gcpList()->createGCPVectors( mapCoords, pixelCoords ); + else + return false; + + // Parametrize the transform with GCPs + if ( !mGeorefTransform.updateParametersFromGCPs( mapCoords, pixelCoords ) ) { - std::vector mapCoords, pixelCoords; - if ( mGCPListWidget->gcpList() ) - mGCPListWidget->gcpList()->createGCPVectors( mapCoords, pixelCoords ); - else - return false; + return false; + } - // Parametrize the transform with GCPs - if ( !mGeorefTransform.updateParametersFromGCPs( mapCoords, pixelCoords ) ) - { - return false; - } - - mGCPsDirty = false; - } + mGCPsDirty = false; + updateTransformParamLabel(); return true; }