Skip to content
Permalink
Browse files

Add missing files

  • Loading branch information
nyalldawson committed Jun 8, 2018
1 parent dafa384 commit 059f343903997d2f7724005372334eec710a7c02
Showing with 217 additions and 0 deletions.
  1. +102 −0 src/analysis/processing/qgsreclassifyutils.cpp
  2. +115 −0 src/analysis/processing/qgsreclassifyutils.h
@@ -0,0 +1,102 @@
/***************************************************************************
qgsreclassifyutils.cpp
---------------------
begin : June, 2018
copyright : (C) 2018 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsreclassifyutils.h"
#include "qgsrasterinterface.h"
#include "qgsrasteriterator.h"
#include "qgsrasterblock.h"
#include "qgsprocessingfeedback.h"
#include "qgsrasterdataprovider.h"

#include "qgis.h"

///@cond PRIVATE

void QgsReclassifyUtils::reclassify(const QVector<QgsReclassifyUtils::RasterClass> &classes, QgsRasterInterface *sourceRaster, int band,
const QgsRectangle &extent, int sourceWidthPixels, int sourceHeightPixels,
QgsRasterDataProvider *destinationRaster, double destNoDataValue, bool useNoDataForMissingValues,
QgsProcessingFeedback *feedback )
{
int maxWidth = 4000;
int maxHeight = 4000;

QgsRasterIterator iter( sourceRaster );
iter.setMaximumTileWidth( maxWidth );
iter.setMaximumTileHeight( maxHeight );
iter.startRasterRead( band, sourceWidthPixels, sourceHeightPixels, extent );

int nbBlocksWidth = std::ceil( 1.0 * sourceWidthPixels / maxWidth );
int nbBlocksHeight = std::ceil( 1.0 * sourceHeightPixels / maxHeight );
int nbBlocks = nbBlocksWidth * nbBlocksHeight;

int iterLeft = 0;
int iterTop = 0;
int iterCols = 0;
int iterRows = 0;
destinationRaster->setEditable( true );
QgsRasterBlock *rasterBlock = nullptr;
bool reclassed = false;
while ( iter.readNextRasterPart( band, iterCols, iterRows, &rasterBlock, iterLeft, iterTop ) )
{
if ( feedback )
feedback->setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
std::unique_ptr< QgsRasterBlock > reclassifiedBlock = qgis::make_unique< QgsRasterBlock >( Qgis::Float32, iterCols, iterRows );

for ( int row = 0; row < iterRows; row++ )
{
if ( feedback && feedback->isCanceled() )
break;
for ( int column = 0; column < iterCols; column++ )
{
if ( rasterBlock->isNoData( row, column ) )
reclassifiedBlock->setValue( row, column, destNoDataValue );
else
{
double value = rasterBlock->value( row, column );
double newValue = reclassifyValue( classes, value, reclassed );
if ( reclassed )
reclassifiedBlock->setValue( row, column, newValue );
else
reclassifiedBlock->setValue( row, column, useNoDataForMissingValues ? destNoDataValue : value );
}
}
}
destinationRaster->writeBlock( reclassifiedBlock.get(), 1, iterLeft, iterTop );

delete rasterBlock;
}
destinationRaster->setEditable( false );
}

double QgsReclassifyUtils::reclassifyValue(const QVector<QgsReclassifyUtils::RasterClass> &classes, double input, bool &reclassified)
{
reclassified = false;
for ( const QgsReclassifyUtils::RasterClass &c : classes )
{
if ( c.contains( input ) )
{
reclassified = true;
return c.value;
}
}
return input;
}

///@endcond



@@ -0,0 +1,115 @@
/***************************************************************************
qgsreclassifyutils.h
---------------------
begin : June, 2018
copyright : (C) 2018 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSRECLASSIFYUTILS
#define QGSRECLASSIFYUTILS

#define SIP_NO_FILE

#include "qgis.h"
#include "qgis_analysis.h"
#include "qgsrasterrange.h"

class QgsRasterInterface;
class QgsProcessingFeedback;
class QgsRasterDataProvider;
class QgsRectangle;

///@cond PRIVATE

/**
* Utility functions for reclassifying raster layers.
* \ingroup analysis
* \since QGIS 3.4
*/
class ANALYSIS_EXPORT QgsReclassifyUtils
{

public:

/**
* Represents a single class for a reclassification operation.
*/
class RasterClass : public QgsRasterRange
{
public:

//! Default constructor for an empty class
RasterClass() = default;

/**
* Constructor for RasterClass, with the specified range of min to max values.
* The \a value argument gives the desired output value for this raster class.
*/
RasterClass( double minValue, double maxValue, QgsRasterRange::BoundsType type, double value )
: QgsRasterRange( minValue, maxValue, type )
, value( value )
{}

//! Desired output value for class
double value = 0;
};

/**
* Performs a reclassification operation on a raster source \a sourceRaster, reclassifying to the given
* list of \a classes.
*
* Parameters of the raster must be given by the \a band, \a extent, \a sourceWidthPixels and
* \a sourceHeightPixels values.
*
* The raster data provider \a destinationRaster will be used to save the result of the
* reclassification operation. The caller is responsible for ensuring that this data provider
* has been created with the same extent, pixel dimensions and CRS as the input raster.
*
* The nodata value for the destination should be specified via \a destNoDataValue. This
* will be used wherever the source raster has a no data value or a source pixel value
* does not have a matching class.
*
* If \a useNoDataForMissingValues is true, then any raster values which do not match to
* a class will be changed to the no data value. Otherwise they are saved unchanged.
*
* The \a feedback argument gives an optional processing feedback, for progress reports
* and cancelation.
*/
static void reclassify(const QVector< RasterClass > &classes,
QgsRasterInterface *sourceRaster,
int band,
const QgsRectangle& extent,
int sourceWidthPixels,
int sourceHeightPixels,
QgsRasterDataProvider *destinationRaster,
double destNoDataValue, bool useNoDataForMissingValues,
QgsProcessingFeedback *feedback = nullptr );

/**
* Reclassifies a single \a input value, using the specified list of \a classes.
*
* If a matching class was found, then \a reclassified will be set to true and the
* class output value returned.
*
* If no matching class was found then \a reclassified will be set to false, and the
* original \a input value returned unchanged.
*/
static double reclassifyValue( const QVector< RasterClass > &classes, double input, bool& reclassified );

};

///@endcond PRIVATE

#endif // QGSRECLASSIFYUTILS


0 comments on commit 059f343

Please sign in to comment.
You can’t perform that action at this time.