diff --git a/python/analysis/raster/qgsalignraster.sip b/python/analysis/raster/qgsalignraster.sip index d8f7611534b..e133a015f66 100644 --- a/python/analysis/raster/qgsalignraster.sip +++ b/python/analysis/raster/qgsalignraster.sip @@ -31,6 +31,8 @@ class QgsAlignRaster QPointF gridOffset() const; //! Return extent of the raster QgsRectangle extent() const; + //! Return origin of the raster + QPointF origin() const; //! write contents of the object to standard error stream - for debugging void dump() const; @@ -109,10 +111,6 @@ class QgsAlignRaster //! Get the output CRS in WKT format QString destinationCRS() const; - // TODO: first need to run determineTransformAndSize() before this - //QSize rasterSize() const { return QSize(mXSize, mYSize); } - // TODO: add method for access to final extent - //! Configure clipping extent (region of interest). //! No extra clipping is done if the rectangle is null void setClipExtent( double xmin, double ymin, double xmax, double ymax ); @@ -123,10 +121,19 @@ class QgsAlignRaster //! No extra clipping is done if the rectangle is null QgsRectangle clipExtent() const; - //! Set destination CRS, cell size and grid offset from a raster file - bool setParametersFromRaster( const RasterInfo& rasterInfo, const QString& destWkt = QString() ); - //! Set destination CRS, cell size and grid offset from a raster file - bool setParametersFromRaster( const QString& filename, const QString& destWkt = QString() ); + //! Set destination CRS, cell size and grid offset from a raster file. + //! The user may provide custom values for some of the parameters - in such case + //! only the remaining parameters are calculated. + //! + //! If default CRS is used, the parameters are set according to the raster file's geo-transform. + //! If a custom CRS is provided, suggested reprojection is calculated first (using GDAL) in order + //! to determine suitable defaults for cell size and grid offset. + //! + //! @return true on success (may fail if it is not possible to reproject raster to given CRS) + bool setParametersFromRaster( const RasterInfo& rasterInfo, const QString& customCRSWkt = QString(), QSizeF customCellSize = QSizeF(), QPointF customGridOffset = QPointF( -1, -1 ) ); + //! Overridden variant for convenience, taking filename instead RasterInfo object. + //! See the other variant for details. + bool setParametersFromRaster( const QString& filename, const QString& customCRSWkt = QString(), QSizeF customCellSize = QSizeF(), QPointF customGridOffset = QPointF( -1, -1 ) ); //! Determine destination extent from the input rasters and calculate derived values //! @return true on success, sets error on error (see errorMessage()) diff --git a/src/analysis/raster/qgsalignraster.cpp b/src/analysis/raster/qgsalignraster.cpp index e126205c2a3..f307209d963 100644 --- a/src/analysis/raster/qgsalignraster.cpp +++ b/src/analysis/raster/qgsalignraster.cpp @@ -149,34 +149,86 @@ QgsRectangle QgsAlignRaster::clipExtent() const } -bool QgsAlignRaster::setParametersFromRaster( const QString& filename, const QString& destWkt ) +bool QgsAlignRaster::setParametersFromRaster( const QString& filename, const QString& destWkt, QSizeF customCellSize, QPointF customGridOffset ) { - return setParametersFromRaster( RasterInfo( filename ), destWkt ); + return setParametersFromRaster( RasterInfo( filename ), destWkt, customCellSize, customGridOffset ); } -bool QgsAlignRaster::setParametersFromRaster( const RasterInfo& rasterInfo, const QString& destWkt ) +bool QgsAlignRaster::setParametersFromRaster( const RasterInfo& rasterInfo, const QString& customCRSWkt, QSizeF customCellSize, QPointF customGridOffset ) { - if ( destWkt.isEmpty() || destWkt.toAscii() == rasterInfo.crs() ) + if ( customCRSWkt.isEmpty() || customCRSWkt.toAscii() == rasterInfo.crs() ) { // use ref. layer to init input mCrsWkt = rasterInfo.crs(); - mCellSizeX = rasterInfo.cellSize().width(); - mCellSizeY = rasterInfo.cellSize().height(); - mGridOffsetX = rasterInfo.gridOffset().x(); - mGridOffsetY = rasterInfo.gridOffset().y(); + + if ( !customCellSize.isValid() ) + { + mCellSizeX = rasterInfo.cellSize().width(); + mCellSizeY = rasterInfo.cellSize().height(); + } + else + { + mCellSizeX = customCellSize.width(); + mCellSizeY = customCellSize.height(); + } + + if ( customGridOffset.x() < 0 || customGridOffset.y() < 0 ) + { + if ( !customCellSize.isValid() ) + { + // using original raster's grid offset to be aligned with origin + mGridOffsetX = rasterInfo.gridOffset().x(); + mGridOffsetY = rasterInfo.gridOffset().y(); + } + else + { + // if using custom cell size: offset so that we are aligned + // with the original raster's origin point + mGridOffsetX = fmod_with_tolerance( rasterInfo.origin().x(), customCellSize.width() ); + mGridOffsetY = fmod_with_tolerance( rasterInfo.origin().y(), customCellSize.height() ); + } + } + else + { + mGridOffsetX = customGridOffset.x(); + mGridOffsetY = customGridOffset.x(); + } } else { QSizeF cs; QPointF go; - if ( !suggestedWarpOutput( rasterInfo, destWkt.toAscii(), &cs, &go ) ) + if ( !suggestedWarpOutput( rasterInfo, customCRSWkt.toAscii(), &cs, &go ) ) + { + mCrsWkt = "_error_"; + mCellSizeX = mCellSizeY = 0; + mGridOffsetX = mGridOffsetY = 0; return false; + } - mCrsWkt = destWkt.toAscii(); - mCellSizeX = cs.width(); - mCellSizeY = cs.height(); - mGridOffsetX = go.x(); - mGridOffsetY = go.y(); + mCrsWkt = customCRSWkt.toAscii(); + + if ( !customCellSize.isValid() ) + { + mCellSizeX = cs.width(); + mCellSizeY = cs.height(); + } + else + { + mCellSizeX = customCellSize.width(); + mCellSizeY = customCellSize.height(); + } + + if ( customGridOffset.x() < 0 || customGridOffset.y() < 0 ) + { + mGridOffsetX = go.x(); + mGridOffsetY = go.y(); + } + else + { + mGridOffsetX = customGridOffset.x(); + mGridOffsetY = customGridOffset.x(); + } } return true; } @@ -186,6 +238,12 @@ bool QgsAlignRaster::checkInputParameters() { mErrorMessage.clear(); + if ( mCrsWkt == "_error_" ) + { + mErrorMessage = QObject::tr( "Unable to reproject." ); + return false; + } + if ( mCellSizeX == 0 || mCellSizeY == 0 ) { mErrorMessage = QObject::tr( "Cell size must not be zero." ); @@ -502,6 +560,11 @@ QgsRectangle QgsAlignRaster::RasterInfo::extent() const return transform_to_extent( mGeoTransform, mXSize, mYSize ); } +QPointF QgsAlignRaster::RasterInfo::origin() const +{ + return QPointF( mGeoTransform[0], mGeoTransform[3] ); +} + void QgsAlignRaster::RasterInfo::dump() const { qDebug( "---RASTER INFO------------------" ); diff --git a/src/analysis/raster/qgsalignraster.h b/src/analysis/raster/qgsalignraster.h index c72185fa9e8..0d311c589ad 100644 --- a/src/analysis/raster/qgsalignraster.h +++ b/src/analysis/raster/qgsalignraster.h @@ -63,6 +63,8 @@ class ANALYSIS_EXPORT QgsAlignRaster QPointF gridOffset() const; //! Return extent of the raster QgsRectangle extent() const; + //! Return origin of the raster + QPointF origin() const; //! write contents of the object to standard error stream - for debugging void dump() const; @@ -167,10 +169,19 @@ class ANALYSIS_EXPORT QgsAlignRaster //! No extra clipping is done if the rectangle is null QgsRectangle clipExtent() const; - //! Set destination CRS, cell size and grid offset from a raster file - bool setParametersFromRaster( const RasterInfo& rasterInfo, const QString& destWkt = QString() ); - //! Set destination CRS, cell size and grid offset from a raster file - bool setParametersFromRaster( const QString& filename, const QString& destWkt = QString() ); + //! Set destination CRS, cell size and grid offset from a raster file. + //! The user may provide custom values for some of the parameters - in such case + //! only the remaining parameters are calculated. + //! + //! If default CRS is used, the parameters are set according to the raster file's geo-transform. + //! If a custom CRS is provided, suggested reprojection is calculated first (using GDAL) in order + //! to determine suitable defaults for cell size and grid offset. + //! + //! @return true on success (may fail if it is not possible to reproject raster to given CRS) + bool setParametersFromRaster( const RasterInfo& rasterInfo, const QString& customCRSWkt = QString(), QSizeF customCellSize = QSizeF(), QPointF customGridOffset = QPointF( -1, -1 ) ); + //! Overridden variant for convenience, taking filename instead RasterInfo object. + //! See the other variant for details. + bool setParametersFromRaster( const QString& filename, const QString& customCRSWkt = QString(), QSizeF customCellSize = QSizeF(), QPointF customGridOffset = QPointF( -1, -1 ) ); //! Determine destination extent from the input rasters and calculate derived values //! @return true on success, sets error on error (see errorMessage()) diff --git a/src/app/qgsalignrasterdialog.cpp b/src/app/qgsalignrasterdialog.cpp index 16838b7f07a..343164e6725 100644 --- a/src/app/qgsalignrasterdialog.cpp +++ b/src/app/qgsalignrasterdialog.cpp @@ -73,12 +73,22 @@ QgsAlignRasterDialog::QgsAlignRasterDialog( QWidget *parent ) connect( mBtnRemove, SIGNAL( clicked( bool ) ), this, SLOT( removeLayer() ) ); connect( mBtnEdit, SIGNAL( clicked( bool ) ), this, SLOT( editLayer() ) ); - connect( mCboReferenceLayer, SIGNAL( currentIndexChanged( int ) ), this, SLOT( updateConfigFromReferenceLayer() ) ); + connect( mCboReferenceLayer, SIGNAL( currentIndexChanged( int ) ), this, SLOT( referenceLayerChanged() ) ); connect( mCrsSelector, SIGNAL( crsChanged( QgsCoordinateReferenceSystem ) ), this, SLOT( destinationCrsChanged() ) ); + connect( mSpinCellSizeX, SIGNAL( valueChanged( double ) ), this, SLOT( updateParametersFromReferenceLayer() ) ); + connect( mSpinCellSizeY, SIGNAL( valueChanged( double ) ), this, SLOT( updateParametersFromReferenceLayer() ) ); + connect( mSpinGridOffsetX, SIGNAL( valueChanged( double ) ), this, SLOT( updateParametersFromReferenceLayer() ) ); + connect( mSpinGridOffsetY, SIGNAL( valueChanged( double ) ), this, SLOT( updateParametersFromReferenceLayer() ) ); + + connect( mChkCustomCRS, SIGNAL( clicked( bool ) ), this, SLOT( updateCustomCRS() ) ); + connect( mChkCustomCellSize, SIGNAL( clicked( bool ) ), this, SLOT( updateCustomCellSize() ) ); + connect( mChkCustomGridOffset, SIGNAL( clicked( bool ) ), this, SLOT( updateCustomGridOffset() ) ); mClipExtentGroupBox->setChecked( false ); mClipExtentGroupBox->setCollapsed( true ); mClipExtentGroupBox->setTitleBase( tr( "Clip to Extent" ) ); + QgsMapCanvas* mc = QgisApp::instance()->mapCanvas(); + mClipExtentGroupBox->setCurrentExtent( mc->extent(), mc->mapSettings().destinationCrs() ); connect( mClipExtentGroupBox, SIGNAL( extentChanged( QgsRectangle ) ), this, SLOT( clipExtentChanged() ) ); // TODO: auto-detect reference layer @@ -86,6 +96,10 @@ QgsAlignRasterDialog::QgsAlignRasterDialog( QWidget *parent ) connect( buttonBox, SIGNAL( accepted() ), this, SLOT( runAlign() ) ); populateLayersView(); + + updateCustomCRS(); + updateCustomCellSize(); + updateCustomGridOffset(); } QgsAlignRasterDialog::~QgsAlignRasterDialog() @@ -130,6 +144,67 @@ void QgsAlignRasterDialog::updateAlignedRasterInfo() mEditOutputSize->setText( msg ); } +void QgsAlignRasterDialog::updateParametersFromReferenceLayer() +{ + QString customCRSWkt; + QSizeF customCellSize; + QPointF customGridOffset( -1, -1 ); + + int index = mCboReferenceLayer->currentIndex(); + if ( index < 0 ) + return; + + QgsAlignRaster::RasterInfo refInfo( mAlign->rasters().at( index ).inputFilename ); + if ( !refInfo.isValid() ) + return; + + // get custom values from the GUI (if any) + if ( mChkCustomCRS->isChecked() ) + { + QgsCoordinateReferenceSystem refCRS( QString::fromAscii( refInfo.crs() ) ); + if ( refCRS != mCrsSelector->crs() ) + customCRSWkt = mCrsSelector->crs().toWkt(); + } + + if ( mChkCustomCellSize->isChecked() ) + { + customCellSize = QSizeF( mSpinCellSizeX->value(), mSpinCellSizeY->value() ); + } + + if ( mChkCustomGridOffset->isChecked() ) + { + customGridOffset = QPointF( mSpinGridOffsetX->value(), mSpinGridOffsetY->value() ); + } + + // calculate the parameters which are not customized already + bool res = mAlign->setParametersFromRaster( refInfo, customCRSWkt, customCellSize, customGridOffset ); + + // refresh values that may have changed + if ( res ) + { + QgsCoordinateReferenceSystem destCRS( mAlign->destinationCRS() ); + mClipExtentGroupBox->setOutputCrs( destCRS ); + if ( !mChkCustomCRS->isChecked() ) + { + mCrsSelector->setCrs( destCRS ); + } + } + if ( !mChkCustomCellSize->isChecked() ) + { + QSizeF cellSize = mAlign->cellSize(); + mSpinCellSizeX->setValue( cellSize.width() ); + mSpinCellSizeY->setValue( cellSize.height() ); + } + if ( !mChkCustomGridOffset->isChecked() ) + { + QPointF gridOffset = mAlign->gridOffset(); + mSpinGridOffsetX->setValue( gridOffset.x() ); + mSpinGridOffsetY->setValue( gridOffset.y() ); + } + + updateAlignedRasterInfo(); +} + void QgsAlignRasterDialog::addLayer() { @@ -185,7 +260,7 @@ void QgsAlignRasterDialog::editLayer() populateLayersView(); } -void QgsAlignRasterDialog::updateConfigFromReferenceLayer() +void QgsAlignRasterDialog::referenceLayerChanged() { int index = mCboReferenceLayer->currentIndex(); if ( index < 0 ) @@ -195,25 +270,11 @@ void QgsAlignRasterDialog::updateConfigFromReferenceLayer() if ( !refInfo.isValid() ) return; - mAlign->setParametersFromRaster( refInfo ); + QgsCoordinateReferenceSystem layerCRS( QString::fromAscii( refInfo.crs() ) ); + mCrsSelector->setLayerCrs( layerCRS ); + mClipExtentGroupBox->setOriginalExtent( refInfo.extent(), layerCRS ); - QgsCoordinateReferenceSystem destCRS( mAlign->destinationCRS() ); - mCrsSelector->setCrs( destCRS ); - - QSizeF cellSize = mAlign->cellSize(); - mSpinCellSizeX->setValue( cellSize.width() ); - mSpinCellSizeY->setValue( cellSize.height() ); - - QPointF gridOffset = mAlign->gridOffset(); - mSpinGridOffsetX->setValue( gridOffset.x() ); - mSpinGridOffsetY->setValue( gridOffset.y() ); - - QgsMapCanvas* mc = QgisApp::instance()->mapCanvas(); - mClipExtentGroupBox->setCurrentExtent( mc->extent(), mc->mapSettings().destinationCrs() ); - mClipExtentGroupBox->setOriginalExtent( refInfo.extent(), QgsCoordinateReferenceSystem( QString::fromAscii( refInfo.crs() ) ) ); - mClipExtentGroupBox->setOutputCrs( destCRS ); - - updateAlignedRasterInfo(); + updateParametersFromReferenceLayer(); } @@ -230,23 +291,7 @@ void QgsAlignRasterDialog::destinationCrsChanged() if ( !refInfo.isValid() ) return; - if ( !mAlign->setParametersFromRaster( refInfo, mCrsSelector->crs().toWkt() ) ) - { - QMessageBox::warning( this, tr( "Align Rasters" ), tr( "Cannot reproject reference layer to the chosen destination CRS.\n\nPlease select a different CRS" ) ); - return; - } - - QSizeF cellSize = mAlign->cellSize(); - mSpinCellSizeX->setValue( cellSize.width() ); - mSpinCellSizeY->setValue( cellSize.height() ); - - QPointF gridOffset = mAlign->gridOffset(); - mSpinGridOffsetX->setValue( gridOffset.x() ); - mSpinGridOffsetY->setValue( gridOffset.y() ); - - mClipExtentGroupBox->setOutputCrs( mCrsSelector->crs() ); - - updateAlignedRasterInfo(); + updateParametersFromReferenceLayer(); } void QgsAlignRasterDialog::clipExtentChanged() @@ -256,6 +301,26 @@ void QgsAlignRasterDialog::clipExtentChanged() updateAlignedRasterInfo(); } +void QgsAlignRasterDialog::updateCustomCRS() +{ + mCrsSelector->setEnabled( mChkCustomCRS->isChecked() ); + updateParametersFromReferenceLayer(); +} + +void QgsAlignRasterDialog::updateCustomCellSize() +{ + mSpinCellSizeX->setEnabled( mChkCustomCellSize->isChecked() ); + mSpinCellSizeY->setEnabled( mChkCustomCellSize->isChecked() ); + updateParametersFromReferenceLayer(); +} + +void QgsAlignRasterDialog::updateCustomGridOffset() +{ + mSpinGridOffsetX->setEnabled( mChkCustomGridOffset->isChecked() ); + mSpinGridOffsetY->setEnabled( mChkCustomGridOffset->isChecked() ); + updateParametersFromReferenceLayer(); +} + void QgsAlignRasterDialog::runAlign() { diff --git a/src/app/qgsalignrasterdialog.h b/src/app/qgsalignrasterdialog.h index ce9ee987647..2184c4f6e96 100644 --- a/src/app/qgsalignrasterdialog.h +++ b/src/app/qgsalignrasterdialog.h @@ -22,7 +22,7 @@ class QgsAlignRasterDialog : public QDialog, private Ui::QgsAlignRasterDialog void removeLayer(); void editLayer(); - void updateConfigFromReferenceLayer(); + void referenceLayerChanged(); void runAlign(); @@ -30,6 +30,12 @@ class QgsAlignRasterDialog : public QDialog, private Ui::QgsAlignRasterDialog void clipExtentChanged(); + void updateCustomCRS(); + void updateCustomCellSize(); + void updateCustomGridOffset(); + + void updateParametersFromReferenceLayer(); + protected: void populateLayersView(); void updateAlignedRasterInfo(); diff --git a/src/ui/qgsalignrasterdialog.ui b/src/ui/qgsalignrasterdialog.ui index f97a9c5e303..ab10c31daa4 100644 --- a/src/ui/qgsalignrasterdialog.ui +++ b/src/ui/qgsalignrasterdialog.ui @@ -80,44 +80,27 @@ </item> <item> <layout class="QGridLayout" name="gridLayout"> - <item row="5" column="0"> + <item row="5" column="1"> <widget class="QLabel" name="label_6"> <property name="text"> <string>Output Size</string> </property> </widget> </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_5"> - <property name="text"> - <string>Grid Offset</string> - </property> - </widget> - </item> - <item row="0" column="0"> + <item row="0" column="1"> <widget class="QLabel" name="label_3"> <property name="text"> <string>Reference Layer</string> </property> </widget> </item> - <item row="0" column="1"> + <item row="0" column="2"> <widget class="QComboBox" name="mCboReferenceLayer"/> </item> - <item row="1" column="1"> + <item row="1" column="2"> <widget class="QgsProjectionSelectionWidget" name="mCrsSelector" native="true"/> </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Cell Size</string> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> - </property> - </widget> - </item> - <item row="2" column="1"> + <item row="2" column="2"> <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> <widget class="QDoubleSpinBox" name="mSpinCellSizeX"> @@ -141,14 +124,7 @@ </item> </layout> </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string>CRS</string> - </property> - </widget> - </item> - <item row="3" column="1"> + <item row="3" column="2"> <layout class="QHBoxLayout" name="horizontalLayout_4"> <item> <widget class="QDoubleSpinBox" name="mSpinGridOffsetX"> @@ -172,7 +148,7 @@ </item> </layout> </item> - <item row="7" column="0" colspan="2"> + <item row="7" column="1" colspan="2"> <widget class="QCheckBox" name="mChkAddToCanvas"> <property name="text"> <string>Add aligned rasters to map canvas</string> @@ -182,7 +158,7 @@ </property> </widget> </item> - <item row="4" column="0" colspan="2"> + <item row="4" column="1" colspan="2"> <widget class="QgsExtentGroupBox" name="mClipExtentGroupBox"> <property name="checkable"> <bool>true</bool> @@ -190,13 +166,34 @@ <layout class="QGridLayout" name="gridLayout_2"/> </widget> </item> - <item row="5" column="1"> + <item row="5" column="2"> <widget class="QLineEdit" name="mEditOutputSize"> <property name="readOnly"> <bool>true</bool> </property> </widget> </item> + <item row="1" column="1"> + <widget class="QCheckBox" name="mChkCustomCRS"> + <property name="text"> + <string>CRS</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QCheckBox" name="mChkCustomCellSize"> + <property name="text"> + <string>Cell Size</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QCheckBox" name="mChkCustomGridOffset"> + <property name="text"> + <string>Grid Offset</string> + </property> + </widget> + </item> </layout> </item> <item> @@ -239,10 +236,15 @@ <tabstop>mBtnRemove</tabstop> <tabstop>mViewLayers</tabstop> <tabstop>mCboReferenceLayer</tabstop> + <tabstop>mChkCustomCRS</tabstop> + <tabstop>mChkCustomCellSize</tabstop> <tabstop>mSpinCellSizeX</tabstop> <tabstop>mSpinCellSizeY</tabstop> + <tabstop>mChkCustomGridOffset</tabstop> <tabstop>mSpinGridOffsetX</tabstop> <tabstop>mSpinGridOffsetY</tabstop> + <tabstop>mClipExtentGroupBox</tabstop> + <tabstop>mEditOutputSize</tabstop> <tabstop>mChkAddToCanvas</tabstop> <tabstop>buttonBox</tabstop> </tabstops> diff --git a/tests/src/analysis/testqgsalignraster.cpp b/tests/src/analysis/testqgsalignraster.cpp index 073afde0af0..38c46f5271b 100644 --- a/tests/src/analysis/testqgsalignraster.cpp +++ b/tests/src/analysis/testqgsalignraster.cpp @@ -171,12 +171,7 @@ class TestAlignRaster : public QObject rasters << QgsAlignRaster::Item( SRC_FILE, tmpFile ); rasters[0].resampleMethod = QgsAlignRaster::RA_Bilinear; align.setRasters( rasters ); - align.setParametersFromRaster( SRC_FILE ); - align.setCellSize( 0.4, 0.4 ); - // a technicality: the raster's origin is at y=-7 so we need to shift the offset, - // because with zero Y offset the grid goes -6.8 ... -7.2 - with offset of 0.2 - // the grid will start at -7 (with X axis no need for shift as 106 % 0.4 == 0) - align.setGridOffset( QPointF( 0.0, 0.2 ) ); + align.setParametersFromRaster( SRC_FILE, QString(), QSizeF( 0.4, 0.4 ) ); bool res = align.run(); QVERIFY( res ); @@ -198,12 +193,7 @@ class TestAlignRaster : public QObject rasters[0].resampleMethod = QgsAlignRaster::RA_Bilinear; rasters[0].rescaleValues = true; align.setRasters( rasters ); - align.setParametersFromRaster( SRC_FILE ); - align.setCellSize( 0.4, 0.4 ); - // a technicality: the raster's origin is at y=-7 so we need to shift the offset, - // because with zero Y offset the grid goes -6.8 ... -7.2 - with offset of 0.2 - // the grid will start at -7 (with X axis no need for shift as 106 % 0.4 == 0) - align.setGridOffset( QPointF( 0.0, 0.2 ) ); + align.setParametersFromRaster( SRC_FILE, QString(), QSizeF( 0.4, 0.4 ) ); bool res = align.run(); QVERIFY( res );