mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-24 00:47:57 -05:00
Add clamp and scale_exp functions
This commit is contained in:
parent
db619edcb4
commit
10acbe017e
19
resources/function_help/clamp-en_US
Normal file
19
resources/function_help/clamp-en_US
Normal file
@ -0,0 +1,19 @@
|
||||
<h3>clamp() function</h3>
|
||||
Restricts an input value to a specified range.
|
||||
|
||||
<p><h4>Syntax</h4>
|
||||
clamp(<i>minimum</i>,<i>input</i>,<i>maximum</i>)</p>
|
||||
|
||||
<p><h4>Arguments</h4>
|
||||
<!-- List args for functions here-->
|
||||
<i> minimum</i> → The smallest value <i>input</i> is allowed to take.<br>
|
||||
<i> input</i> → a value which will be restricted to the range specified by <i>minimum</i> and <i>maximum</i>.<br>
|
||||
<i> maximum</i> → The largest value <i>input</i> is allowed to take.<br>
|
||||
|
||||
<h4>Example</h4>
|
||||
<!-- Show example of function.-->
|
||||
clamp(1,5,10) → 5 (<i>input</i> is between 1 and 10 so is returned unchanged)<br>
|
||||
clamp(1,0,10) → 1 (<i>input</i> is less than minimum value of 1, so function returns 1)<br>
|
||||
clamp(1,11,10) → 10 (<i>input</i> is greater than maximum value of 10, so function returns 11)<br>
|
||||
|
||||
|
28
resources/function_help/scale_exp-en_US
Normal file
28
resources/function_help/scale_exp-en_US
Normal file
@ -0,0 +1,28 @@
|
||||
<h3>scale_exp() function</h3>
|
||||
Transforms a given value from an input domain to an output range using an exponential curve. This function can be used to ease values in or out
|
||||
of the specified output range.
|
||||
|
||||
<p><h4>Syntax</h4>
|
||||
scale_exp(<i>val</i>,<i>domain_min</i>,<i>domain_max</i>,<i>range_min</i>,<i>range_max</i>,<i>exponent</i>)</p>
|
||||
|
||||
<p><h4>Arguments</h4>
|
||||
<!-- List args for functions here-->
|
||||
<i> val</i> → is a value in the input domain. The function will return a corresponding scaled value in the output range.<br>
|
||||
<i> domain_min, domain_max</i> → specify the input domain, the smallest and largest values the input <i>val</i> should take.<br>
|
||||
<i> range_min, range_max</i> → specify the output range, the smallest and largest values which should be output by the function.<br>
|
||||
<i> exponent</i> → a positive value (greater than 0), which dictates the way input values are mapped to the output range. Large exponents will cause the output values to 'ease in', starting slowly before
|
||||
accelerating as the input values approach the domain maximum. Smaller exponents (less than 1) will cause output values to 'ease out', where the mapping starts quickly but slows as it approaches the domain maximum.<br>
|
||||
|
||||
<h4>Example</h4>
|
||||
<!-- Show example of function.-->
|
||||
<b>Easing in, using an exponent of 2:</b><br>
|
||||
scale_exp(5,0,10,0,100,2) → 25<br>
|
||||
scale_exp(7.5,0,10,0,100,2) → 56.25<br>
|
||||
scale_exp(9.5,0,10,0,100,2) → 90.25<br>
|
||||
<br>
|
||||
<b>Easing out, using an exponent of 0.5:</b><br>
|
||||
scale_exp(3,0,10,0,100,0.5) → 54.772<br>
|
||||
scale_exp(6,0,10,0,100,0.5) → 77.459<br>
|
||||
scale_exp(9,0,10,0,100,0.5) → 94.868<br>
|
||||
|
||||
|
@ -442,29 +442,69 @@ static QVariant fcnRnd( const QVariantList& values, QgsFeature* , QgsExpression*
|
||||
static QVariant fcnLinearScale( const QVariantList& values, QgsFeature* , QgsExpression* parent )
|
||||
{
|
||||
double val = getDoubleValue( values.at( 0 ), parent );
|
||||
double domain_min = getDoubleValue( values.at( 1 ), parent );
|
||||
double domain_max = getDoubleValue( values.at( 2 ), parent );
|
||||
double range_min = getDoubleValue( values.at( 3 ), parent );
|
||||
double range_max = getDoubleValue( values.at( 4 ), parent );
|
||||
double domainMin = getDoubleValue( values.at( 1 ), parent );
|
||||
double domainMax = getDoubleValue( values.at( 2 ), parent );
|
||||
double rangeMin = getDoubleValue( values.at( 3 ), parent );
|
||||
double rangeMax = getDoubleValue( values.at( 4 ), parent );
|
||||
|
||||
if ( domainMin >= domainMax )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Domain max must be greater than domain min" ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
// outside of domain?
|
||||
if ( val >= domain_max )
|
||||
if ( val >= domainMax )
|
||||
{
|
||||
return range_max;
|
||||
return rangeMax;
|
||||
}
|
||||
else if ( val <= domain_min )
|
||||
else if ( val <= domainMin )
|
||||
{
|
||||
return range_min;
|
||||
return rangeMin;
|
||||
}
|
||||
|
||||
// calculate linear scale
|
||||
double m = ( range_max - range_min ) / ( domain_max - domain_min );
|
||||
double c = range_min - ( domain_min * m );
|
||||
double m = ( rangeMax - rangeMin ) / ( domainMax - domainMin );
|
||||
double c = rangeMin - ( domainMin * m );
|
||||
|
||||
// Return linearly scaled value
|
||||
return QVariant( m * val + c );
|
||||
}
|
||||
|
||||
static QVariant fcnExpScale( const QVariantList& values, QgsFeature* , QgsExpression* parent )
|
||||
{
|
||||
double val = getDoubleValue( values.at( 0 ), parent );
|
||||
double domainMin = getDoubleValue( values.at( 1 ), parent );
|
||||
double domainMax = getDoubleValue( values.at( 2 ), parent );
|
||||
double rangeMin = getDoubleValue( values.at( 3 ), parent );
|
||||
double rangeMax = getDoubleValue( values.at( 4 ), parent );
|
||||
double exponent = getDoubleValue( values.at( 5 ), parent );
|
||||
|
||||
if ( domainMin >= domainMax )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Domain max must be greater than domain min" ) );
|
||||
return QVariant();
|
||||
}
|
||||
if ( exponent <= 0 )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Exponent must be greater than 0" ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
// outside of domain?
|
||||
if ( val >= domainMax )
|
||||
{
|
||||
return rangeMax;
|
||||
}
|
||||
else if ( val <= domainMin )
|
||||
{
|
||||
return rangeMin;
|
||||
}
|
||||
|
||||
// Return exponentially scaled value
|
||||
return QVariant((( rangeMax - rangeMin ) / pow( domainMax - domainMin, exponent ) ) * pow( val - domainMin, exponent ) + rangeMin );
|
||||
}
|
||||
|
||||
static QVariant fcnMax( const QVariantList& values, QgsFeature* , QgsExpression *parent )
|
||||
{
|
||||
//initially set max as first value
|
||||
@ -501,6 +541,27 @@ static QVariant fcnMin( const QVariantList& values, QgsFeature* , QgsExpression
|
||||
return QVariant( minVal );
|
||||
}
|
||||
|
||||
static QVariant fcnClamp( const QVariantList& values, QgsFeature* , QgsExpression* parent )
|
||||
{
|
||||
double minValue = getDoubleValue( values.at( 0 ), parent );
|
||||
double testValue = getDoubleValue( values.at( 1 ), parent );
|
||||
double maxValue = getDoubleValue( values.at( 2 ), parent );
|
||||
|
||||
// force testValue to sit inside the range specified by the min and max value
|
||||
if ( testValue <= minValue )
|
||||
{
|
||||
return QVariant( minValue );
|
||||
}
|
||||
else if ( testValue >= maxValue )
|
||||
{
|
||||
return QVariant( maxValue );
|
||||
}
|
||||
else
|
||||
{
|
||||
return QVariant( testValue );
|
||||
}
|
||||
}
|
||||
|
||||
static QVariant fcnFloor( const QVariantList& values, QgsFeature* , QgsExpression* parent )
|
||||
{
|
||||
double x = getDoubleValue( values.at( 0 ), parent );
|
||||
@ -1342,8 +1403,8 @@ const QStringList &QgsExpression::BuiltinFunctions()
|
||||
<< "abs" << "sqrt" << "cos" << "sin" << "tan"
|
||||
<< "asin" << "acos" << "atan" << "atan2"
|
||||
<< "exp" << "ln" << "log10" << "log"
|
||||
<< "round" << "rand" << "randf" << "max" << "min"
|
||||
<< "scale_linear" << "floor" << "ceil"
|
||||
<< "round" << "rand" << "randf" << "max" << "min" << "clamp"
|
||||
<< "scale_linear" << "scale_exp" << "floor" << "ceil"
|
||||
<< "toint" << "toreal" << "tostring"
|
||||
<< "todatetime" << "todate" << "totime" << "tointerval"
|
||||
<< "coalesce" << "regexp_match" << "$now" << "age" << "year"
|
||||
@ -1389,7 +1450,9 @@ const QList<QgsExpression::Function*> &QgsExpression::Functions()
|
||||
<< new StaticFunction( "randf", 2, fcnRndF, QObject::tr( "Math" ) )
|
||||
<< new StaticFunction( "max", -1, fcnMax, QObject::tr( "Math" ) )
|
||||
<< new StaticFunction( "min", -1, fcnMin, QObject::tr( "Math" ) )
|
||||
<< new StaticFunction( "clamp", 3, fcnClamp, QObject::tr( "Math" ) )
|
||||
<< new StaticFunction( "scale_linear", 5, fcnLinearScale, QObject::tr( "Math" ) )
|
||||
<< new StaticFunction( "scale_exp", 6, fcnExpScale, QObject::tr( "Math" ) )
|
||||
<< new StaticFunction( "floor", 1, fcnFloor, QObject::tr( "Math" ) )
|
||||
<< new StaticFunction( "ceil", 1, fcnCeil, QObject::tr( "Math" ) )
|
||||
<< new StaticFunction( "$pi", 0, fcnPi, QObject::tr( "Math" ) )
|
||||
|
@ -260,6 +260,9 @@ class TestQgsExpression: public QObject
|
||||
QTest::newRow( "max(1,3.5,-2.1)" ) << "max(1,3.5,-2.1)" << false << QVariant( 3.5 );
|
||||
QTest::newRow( "min(-1.5)" ) << "min(-1.5)" << false << QVariant( -1.5 );
|
||||
QTest::newRow( "min(-16.6,3.5,-2.1)" ) << "min(-16.6,3.5,-2.1)" << false << QVariant( -16.6 );
|
||||
QTest::newRow( "clamp(-2,1,5)" ) << "clamp(-2,1,5)" << false << QVariant( 1.0 );
|
||||
QTest::newRow( "clamp(-2,-10,5)" ) << "clamp(-2,-10,5)" << false << QVariant( -2.0 );
|
||||
QTest::newRow( "clamp(-2,100,5)" ) << "clamp(-2,100,5)" << false << QVariant( 5.0 );
|
||||
QTest::newRow( "floor(4.9)" ) << "floor(4.9)" << false << QVariant( 4. );
|
||||
QTest::newRow( "floor(-4.9)" ) << "floor(-4.9)" << false << QVariant( -5. );
|
||||
QTest::newRow( "ceil(4.9)" ) << "ceil(4.9)" << false << QVariant( 5. );
|
||||
@ -271,6 +274,13 @@ class TestQgsExpression: public QObject
|
||||
QTest::newRow( "scale_linear(-1,0,10,100,200)" ) << "scale_linear(-1,0,10,100,200)" << false << QVariant( 100. );
|
||||
QTest::newRow( "scale_linear(11,0,10,100,200)" ) << "scale_linear(11,0,10,100,200)" << false << QVariant( 200. );
|
||||
|
||||
QTest::newRow( "scale_exp(0.5,0,1,0,1,2)" ) << "scale_exp(0.5,0,1,0,1,2)" << false << QVariant( 0.25 );
|
||||
QTest::newRow( "scale_exp(0,0,10,100,200,2)" ) << "scale_exp(0,0,10,100,200,2)" << false << QVariant( 100. );
|
||||
QTest::newRow( "scale_exp(5,0,10,100,200,2)" ) << "scale_exp(5,0,10,100,200,2)" << false << QVariant( 125. );
|
||||
QTest::newRow( "scale_exp(10,0,10,100,200,0.5)" ) << "scale_exp(10,0,10,100,200,0.5)" << false << QVariant( 200. );
|
||||
QTest::newRow( "scale_exp(-1,0,10,100,200,0.5)" ) << "scale_exp(-1,0,10,100,200,0.5)" << false << QVariant( 100. );
|
||||
QTest::newRow( "scale_exp(4,0,9,0,90,0.5)" ) << "scale_exp(4,0,9,0,90,0.5)" << false << QVariant( 60. );
|
||||
|
||||
// cast functions
|
||||
QTest::newRow( "double to int" ) << "toint(3.2)" << false << QVariant( 3 );
|
||||
QTest::newRow( "text to int" ) << "toint('53')" << false << QVariant( 53 );
|
||||
|
Loading…
x
Reference in New Issue
Block a user