Skip to content

Commit

Permalink
[processing] port zonal statistics to C++
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbruy committed Dec 9, 2019
1 parent 4622661 commit cc5b6e7
Show file tree
Hide file tree
Showing 12 changed files with 354 additions and 164 deletions.
18 changes: 18 additions & 0 deletions python/analysis/auto_generated/vector/qgszonalstatistics.sip.in
Expand Up @@ -100,6 +100,24 @@ added to ``polygonLayer`` for each statistic calculated.
Starts the calculation

:return: 0 in case of success
%End

static QString displayName( QgsZonalStatistics::Statistic statistic );
%Docstring
Returns the friendly display name for a ``statistic``.

.. seealso:: :py:func:`shortName`

.. versionadded:: 3.12
%End

static QString shortName( QgsZonalStatistics::Statistic statistic );
%Docstring
Returns a short, friendly display name for a ``statistic``, suitable for use in a field name.

.. seealso:: :py:func:`displayName`

.. versionadded:: 3.12
%End

public:
Expand Down
3 changes: 0 additions & 3 deletions python/plugins/processing/algs/help/qgis.yaml
Expand Up @@ -445,6 +445,3 @@ qgis:vectorlayerscatterplot: >

qgis:voronoipolygons: >
This algorithm takes a points layer and generates a polygon layer containing the voronoi polygons corresponding to those input points.

qgis:zonalstatistics: >
This algorithm calculates statistics of a raster layer for each feature of an overlapping polygon vector layer.
2 changes: 0 additions & 2 deletions python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py
Expand Up @@ -102,7 +102,6 @@
from .VectorLayerScatterplot3D import VectorLayerScatterplot3D
from .VectorSplit import VectorSplit
from .VoronoiPolygons import VoronoiPolygons
from .ZonalStatistics import ZonalStatistics


class QgisAlgorithmProvider(QgsProcessingProvider):
Expand Down Expand Up @@ -189,7 +188,6 @@ def getAlgs(self):
VectorLayerScatterplot3D(),
VectorSplit(),
VoronoiPolygons(),
ZonalStatistics()
]

return algs
Expand Down
144 changes: 0 additions & 144 deletions python/plugins/processing/algs/qgis/ZonalStatistics.py

This file was deleted.

Expand Up @@ -89,8 +89,8 @@ tests:
fields:
fid: skip

- algorithm: qgis:zonalstatistics
name: simple zonal statistics
- algorithm: native:zonalstatistics
name: Zonal statistics
params:
COLUMN_PREFIX: _
INPUT_RASTER:
Expand All @@ -115,7 +115,7 @@ tests:
precision: 5

- algorithm: qgis:zonalhistogram
name: zonal histogram
name: Zonal histogram
params:
COLUMN_PREFIX: HISTO_
INPUT_RASTER:
Expand Down
1 change: 1 addition & 0 deletions src/analysis/CMakeLists.txt
Expand Up @@ -153,6 +153,7 @@ SET(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmvectorize.cpp
processing/qgsalgorithmwedgebuffers.cpp
processing/qgsalgorithmzonalhistogram.cpp
processing/qgsalgorithmzonalstatistics.cpp
processing/qgsbookmarkalgorithms.cpp
processing/qgsprojectstylealgorithms.cpp
processing/qgsstylealgorithms.cpp
Expand Down
153 changes: 153 additions & 0 deletions src/analysis/processing/qgsalgorithmzonalstatistics.cpp
@@ -0,0 +1,153 @@
/***************************************************************************
qgsalgorithmzonalstatistics.cpp
---------------------
begin : December 2019
copyright : (C) 2019 by Alexander Bruy
email : alexander dot bruy 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 "qgsalgorithmzonalstatistics.h"

///@cond PRIVATE

const std::vector< QgsZonalStatistics::Statistic > STATS
{
QgsZonalStatistics::Count,
QgsZonalStatistics::Sum,
QgsZonalStatistics::Mean,
QgsZonalStatistics::Median,
QgsZonalStatistics::StDev,
QgsZonalStatistics::Min,
QgsZonalStatistics::Max,
QgsZonalStatistics::Range,
QgsZonalStatistics::Minority,
QgsZonalStatistics::Majority,
QgsZonalStatistics::Variety,
QgsZonalStatistics::Variance,
};

QString QgsZonalStatisticsAlgorithm::name() const
{
return QStringLiteral( "zonalstatistics" );
}

QString QgsZonalStatisticsAlgorithm::displayName() const
{
return QObject::tr( "Zonal statistics" );
}

QStringList QgsZonalStatisticsAlgorithm::tags() const
{
return QObject::tr( "stats,statistics,zones,layer,sum,maximum,minimum,mean,count,standard,deviation,"
"median,range,majority,minority,variety,variance,summary,raster" ).split( ',' );
}

QString QgsZonalStatisticsAlgorithm::group() const
{
return QObject::tr( "Raster analysis" );
}

QString QgsZonalStatisticsAlgorithm::groupId() const
{
return QStringLiteral( "rasteranalysis" );
}

QString QgsZonalStatisticsAlgorithm::shortHelpString() const
{
return QObject::tr( "This algorithm calculates statistics of a raster layer for each feature "
"of an overlapping polygon vector layer." );
}

QgsProcessingAlgorithm::Flags QgsZonalStatisticsAlgorithm::flags() const
{
return QgsProcessingAlgorithm::flags() | QgsProcessingAlgorithm::FlagNoThreading;
}

QgsZonalStatisticsAlgorithm *QgsZonalStatisticsAlgorithm::createInstance() const
{
return new QgsZonalStatisticsAlgorithm();
}

void QgsZonalStatisticsAlgorithm::initAlgorithm( const QVariantMap & )
{
QStringList statChoices;
statChoices.reserve( STATS.size() );
for ( QgsZonalStatistics::Statistic stat : STATS )
{
statChoices << QgsZonalStatistics::displayName( stat );
}

addParameter( new QgsProcessingParameterRasterLayer( QStringLiteral( "INPUT_RASTER" ), QObject::tr( "Raster layer" ) ) );
addParameter( new QgsProcessingParameterBand( QStringLiteral( "RASTER_BAND" ),
QObject::tr( "Raster band" ), 1, QStringLiteral( "INPUT_RASTER" ) ) );
addParameter( new QgsProcessingParameterVectorLayer( QStringLiteral( "INPUT_VECTOR" ), QObject::tr( "Vector layer containing zones" ),
QList< int >() << QgsProcessing::TypeVectorPolygon ) );
addParameter( new QgsProcessingParameterString( QStringLiteral( "COLUMN_PREFIX" ), QObject::tr( "Output column prefix" ), QStringLiteral( "_" ) ) );

addParameter( new QgsProcessingParameterEnum( QStringLiteral( "STATISTICS" ), QObject::tr( "Statistics to calculate" ),
statChoices, true, QVariantList() << 0 << 1 << 2 ) );

addOutput( new QgsProcessingOutputVectorLayer( QStringLiteral( "INPUT_VECTOR" ), QObject::tr( "Zonal statistics" ), QgsProcessing::TypeVectorPolygon ) );
}

bool QgsZonalStatisticsAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
{
QgsRasterLayer *rasterLayer = parameterAsRasterLayer( parameters, QStringLiteral( "INPUT_RASTER" ), context );
if ( !rasterLayer )
throw QgsProcessingException( invalidRasterError( parameters, QStringLiteral( "INPUT_RASTER" ) ) );

mBand = parameterAsInt( parameters, QStringLiteral( "RASTER_BAND" ), context );
if ( mBand < 1 || mBand > rasterLayer->bandCount() )
throw QgsProcessingException( QObject::tr( "Invalid band number for BAND (%1): Valid values for input raster are 1 to %2" ).arg( mBand )
.arg( rasterLayer->bandCount() ) );

mInterface.reset( rasterLayer->dataProvider()->clone() );
mCrs = rasterLayer->crs();
mPixelSizeX = rasterLayer->rasterUnitsPerPixelX();
mPixelSizeY = rasterLayer->rasterUnitsPerPixelY();

mPrefix = parameterAsString( parameters, QStringLiteral( "COLUMN_PREFIX" ), context );

const QList< int > stats = parameterAsEnums( parameters, QStringLiteral( "STATISTICS" ), context );
mStats = nullptr;
for ( int s : stats )
{
mStats |= STATS.at( s );
}

return true;
}

QVariantMap QgsZonalStatisticsAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
QgsVectorLayer *layer = parameterAsVectorLayer( parameters, QStringLiteral( "INPUT_VECTOR" ), context );
if ( !layer )
throw QgsProcessingException( QObject::tr( "Invalid zones layer" ) );

QgsZonalStatistics zs( layer,
mInterface.get(),
mCrs,
mPixelSizeX,
mPixelSizeY,
mPrefix,
mBand,
QgsZonalStatistics::Statistics( mStats )
);

zs.calculateStatistics( feedback );

QVariantMap outputs;
outputs.insert( QStringLiteral( "INPUT_VECTOR" ), layer->id() );
return outputs;
}

///@endcond

0 comments on commit cc5b6e7

Please sign in to comment.