Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Allow for custom setting of cell size / grid offset in GUI
  • Loading branch information
wonder-sk committed Jun 29, 2015
1 parent 3d290ef commit 06b4ad8
Show file tree
Hide file tree
Showing 7 changed files with 253 additions and 109 deletions.
23 changes: 15 additions & 8 deletions python/analysis/raster/qgsalignraster.sip
Expand Up @@ -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;
Expand Down Expand Up @@ -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 );
Expand All @@ -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())
Expand Down
91 changes: 77 additions & 14 deletions src/analysis/raster/qgsalignraster.cpp
Expand Up @@ -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 = customCRSWkt.toAscii();

mCrsWkt = destWkt.toAscii();
mCellSizeX = cs.width();
mCellSizeY = cs.height();
mGridOffsetX = go.x();
mGridOffsetY = go.y();
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;
}
Expand All @@ -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." );
Expand Down Expand Up @@ -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------------------" );
Expand Down
19 changes: 15 additions & 4 deletions src/analysis/raster/qgsalignraster.h
Expand Up @@ -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;
Expand Down Expand Up @@ -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())
Expand Down
139 changes: 102 additions & 37 deletions src/app/qgsalignrasterdialog.cpp
Expand Up @@ -73,19 +73,33 @@ 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

connect( buttonBox, SIGNAL( accepted() ), this, SLOT( runAlign() ) );

populateLayersView();

updateCustomCRS();
updateCustomCellSize();
updateCustomGridOffset();
}

QgsAlignRasterDialog::~QgsAlignRasterDialog()
Expand Down Expand Up @@ -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()
{
Expand Down Expand Up @@ -185,7 +260,7 @@ void QgsAlignRasterDialog::editLayer()
populateLayersView();
}

void QgsAlignRasterDialog::updateConfigFromReferenceLayer()
void QgsAlignRasterDialog::referenceLayerChanged()
{
int index = mCboReferenceLayer->currentIndex();
if ( index < 0 )
Expand All @@ -195,25 +270,11 @@ void QgsAlignRasterDialog::updateConfigFromReferenceLayer()
if ( !refInfo.isValid() )
return;

mAlign->setParametersFromRaster( refInfo );

QgsCoordinateReferenceSystem destCRS( mAlign->destinationCRS() );
mCrsSelector->setCrs( destCRS );

QSizeF cellSize = mAlign->cellSize();
mSpinCellSizeX->setValue( cellSize.width() );
mSpinCellSizeY->setValue( cellSize.height() );
QgsCoordinateReferenceSystem layerCRS( QString::fromAscii( refInfo.crs() ) );
mCrsSelector->setLayerCrs( layerCRS );
mClipExtentGroupBox->setOriginalExtent( refInfo.extent(), layerCRS );

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();
}


Expand All @@ -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()
Expand All @@ -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()
{
Expand Down

0 comments on commit 06b4ad8

Please sign in to comment.