mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
[FEATURE][expression] add raster_value() function (#7487)
This commit is contained in:
parent
2692de6ed0
commit
2d964919f6
10
resources/function_help/json/raster_value
Normal file
10
resources/function_help/json/raster_value
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "raster_value",
|
||||
"type": "function",
|
||||
"description": "Returns the raster value found at the provided point.",
|
||||
"arguments": [ {"arg":"layer","description":"the name or id of a raster layer"},
|
||||
{"arg":"band","description":"the band number to sample the value from."},
|
||||
{"arg":"point","description":"point geometry (for multipart geometries having more than one part, a null value will be returned)"}],
|
||||
"examples": [ { "expression":"raster_value('dem', 1, make_point(1,1))", "returns":"25"}]
|
||||
}
|
||||
|
@ -1283,6 +1283,48 @@ static QVariant fcnFeatureId( const QVariantList &, const QgsExpressionContext *
|
||||
return QVariant( static_cast< int >( f.id() ) );
|
||||
}
|
||||
|
||||
static QVariant fcnRasterValue( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
QgsRasterLayer *layer = QgsExpressionUtils::getRasterLayer( values.at( 0 ), parent );
|
||||
if ( !layer || !layer->dataProvider() )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Function `raster_value` requires a valid raster layer." ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int bandNb = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
|
||||
if ( bandNb < 1 || bandNb > layer->bandCount() )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Function `raster_value` requires a valid raster band number." ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
|
||||
if ( geom.isNull() || geom.type() != QgsWkbTypes::PointGeometry )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Function `raster_value` requires a valid point geometry." ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QgsPointXY point = geom.asPoint();
|
||||
if ( geom.isMultipart() )
|
||||
{
|
||||
QgsMultiPointXY multiPoint = geom.asMultiPoint();
|
||||
if ( multiPoint.count() == 1 )
|
||||
{
|
||||
point = multiPoint[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
// if the geometry contains more than one part, return an undefined value
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
double value = layer->dataProvider()->sample( point, bandNb );
|
||||
return std::isnan( value ) ? QVariant() : value;
|
||||
}
|
||||
|
||||
static QVariant fcnFeature( const QVariantList &, const QgsExpressionContext *context, QgsExpression *, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
if ( !context )
|
||||
@ -4559,7 +4601,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "layer_property" ), 2, fcnGetLayerProperty, QStringLiteral( "General" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "raster_statistic" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "band" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "statistic" ) ), fcnGetRasterBandStat, QStringLiteral( "General" ) );
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "statistic" ) ), fcnGetRasterBandStat, QStringLiteral( "Rasters" ) );
|
||||
|
||||
// **var** function
|
||||
QgsStaticExpressionFunction *varFunction = new QgsStaticExpressionFunction( QStringLiteral( "var" ), 1, fcnGetVariable, QStringLiteral( "General" ) );
|
||||
@ -4617,6 +4659,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "env" ), 1, fcnEnvVar, QStringLiteral( "General" ), QString() )
|
||||
<< new QgsWithVariableExpressionFunction()
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "attribute" ), 2, fcnAttribute, QStringLiteral( "Record and Attributes" ), QString(), false, QSet<QString>() << QgsFeatureRequest::ALL_ATTRIBUTES )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "raster_value" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "band" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "point" ) ), fcnRasterValue, QStringLiteral( "Rasters" ) )
|
||||
|
||||
// functions for arrays
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "array" ), -1, fcnArray, QStringLiteral( "Arrays" ), QString(), false, QSet<QString>(), false, QStringList(), true )
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "qgsexpression.h"
|
||||
#include "qgscolorramp.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsrasterlayer.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgsrelationmanager.h"
|
||||
|
||||
@ -355,6 +356,10 @@ class QgsExpressionUtils
|
||||
return qobject_cast<QgsVectorLayer *>( getMapLayer( value, e ) );
|
||||
}
|
||||
|
||||
static QgsRasterLayer *getRasterLayer( const QVariant &value, QgsExpression *e )
|
||||
{
|
||||
return qobject_cast<QgsRasterLayer *>( getMapLayer( value, e ) );
|
||||
}
|
||||
|
||||
static QVariantList getListValue( const QVariant &value, QgsExpression *parent )
|
||||
{
|
||||
|
@ -1246,6 +1246,15 @@ class TestQgsExpression: public QObject
|
||||
QTest::newRow( "raster_statistic range" ) << QStringLiteral( "raster_statistic('%1',1,'range')" ).arg( mRasterLayer->id() ) << false << QVariant( 9.0 );
|
||||
QTest::newRow( "raster_statistic sum" ) << QStringLiteral( "round(raster_statistic('%1',1,'sum'))" ).arg( mRasterLayer->id() ) << false << QVariant( 450 );
|
||||
|
||||
// raster_value tests
|
||||
QTest::newRow( "raster_value no layer" ) << "raster_value('',1,make_point(1,1))" << true << QVariant();
|
||||
QTest::newRow( "raster_value bad layer" ) << "raster_value('bad',1,make_point(1,1))" << true << QVariant();
|
||||
QTest::newRow( "raster_value bad band" ) << QStringLiteral( "raster_value('%1',0,make_point(1,1))" ).arg( mRasterLayer->name() ) << true << QVariant();
|
||||
QTest::newRow( "raster_value bad band 2" ) << QStringLiteral( "raster_value('%1',100,make_point(1,1))" ).arg( mRasterLayer->name() ) << true << QVariant();
|
||||
QTest::newRow( "raster_value invalid geometry" ) << QStringLiteral( "raster_value('%1',1,'invalid geom')" ).arg( mRasterLayer->name() ) << true << QVariant();
|
||||
QTest::newRow( "raster_value valid" ) << QStringLiteral( "raster_value('%1',1,make_point(1535390,5083270))" ).arg( mRasterLayer->name() ) << false << QVariant( 1.0 );
|
||||
QTest::newRow( "raster_value outside extent" ) << QStringLiteral( "raster_value('%1',1,make_point(1535370,5083250))" ).arg( mRasterLayer->name() ) << false << QVariant();
|
||||
|
||||
//test conversions to bool
|
||||
QTest::newRow( "feature to bool false" ) << QStringLiteral( "case when get_feature('none','none',499) then true else false end" ) << false << QVariant( false );
|
||||
QTest::newRow( "feature to bool true" ) << QStringLiteral( "case when get_feature('test','col1',10) then true else false end" ) << false << QVariant( true );
|
||||
|
Loading…
x
Reference in New Issue
Block a user