Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Use shorter expression if values in opacity interpolation are both nu…
…meric
  • Loading branch information
mhugent committed Sep 15, 2021
1 parent 2f274f0 commit e097f6f
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 10 deletions.
32 changes: 28 additions & 4 deletions src/core/vectortile/qgsmapboxglstyleconverter.cpp
Expand Up @@ -2121,11 +2121,16 @@ QgsProperty QgsMapBoxGlStyleConverter::parseInterpolateOpacityByZoom( const QVar
QString scaleExpression;
if ( stops.length() <= 2 )
{
const QVariant bv = stops.value( 0 ).toList().value( 1 );
const QVariant tv = stops.last().toList().value( 1 );
double bottom = 0.0;
double top = 0.0;
const bool numeric = numericArgumentsOnly( bv, tv, bottom, top );
scaleExpression = QStringLiteral( "set_color_part(@symbol_color, 'alpha', %1)" )
.arg( interpolateExpression( stops.value( 0 ).toList().value( 0 ).toDouble(),
stops.last().toList().value( 0 ).toDouble(),
QString( "(%1) * %2" ).arg( parseValue( stops.value( 0 ).toList().value( 1 ), context ) ).arg( maxOpacity ),
QString( "(%1) * %2" ).arg( parseValue( stops.last().toList().value( 1 ), context ) ).arg( maxOpacity ), base, 1, &context ) );
numeric ? QString::number( bottom * maxOpacity ) : QString( "(%1) * %2" ).arg( parseValue( bv, context ) ).arg( maxOpacity ),
numeric ? QString::number( top * maxOpacity ) : QString( "(%1) * %2" ).arg( parseValue( tv, context ) ).arg( maxOpacity ), base, 1, &context ) );
}
else
{
Expand All @@ -2142,14 +2147,21 @@ QString QgsMapBoxGlStyleConverter::parseOpacityStops( double base, const QVarian

for ( int i = 0; i < stops.size() - 1; ++i )
{
const QVariant bv = stops.value( i ).toList().value( 1 );
const QVariant tv = stops.value( i + 1 ).toList().value( 1 );
double bottom = 0.0;
double top = 0.0;
const bool numeric = numericArgumentsOnly( bv, tv, bottom, top );

caseString += QStringLiteral( " WHEN @vector_tile_zoom >= %1 AND @vector_tile_zoom < %2 "
"THEN set_color_part(@symbol_color, 'alpha', %3)" )
.arg( stops.value( i ).toList().value( 0 ).toString(),
stops.value( i + 1 ).toList().value( 0 ).toString(),
interpolateExpression( stops.value( i ).toList().value( 0 ).toDouble(),
stops.value( i + 1 ).toList().value( 0 ).toDouble(),
QString( "(%1) * %2" ).arg( parseValue( stops.value( i ).toList().value( 1 ), context ) ).arg( maxOpacity ),
QString( "(%1) * %2" ).arg( parseValue( stops.value( i + 1 ).toList().value( 1 ), context ) ).arg( maxOpacity ), base, 1, &context ) );
numeric ? QString::number( bottom * maxOpacity ) : QString( "(%1) * %2" ).arg( parseValue( bv, context ) ).arg( maxOpacity ),
numeric ? QString::number( top * maxOpacity ) : QString( "(%1) * %2" ).arg( parseValue( tv, context ) ).arg( maxOpacity ),
base, 1, &context ) );
}

caseString += QStringLiteral( " WHEN @vector_tile_zoom >= %1 "
Expand Down Expand Up @@ -3036,6 +3048,18 @@ QgsVectorTileLabeling *QgsMapBoxGlStyleConverter::labeling() const
return mLabeling ? mLabeling->clone() : nullptr;
}

bool QgsMapBoxGlStyleConverter::numericArgumentsOnly( const QVariant &bottomVariant, const QVariant &topVariant, double &bottom, double &top )
{
if ( bottomVariant.canConvert( QMetaType::Double ) && topVariant.canConvert( QMetaType::Double ) )
{
bool bDoubleOk, tDoubleOk;
bottom = bottomVariant.toDouble( &bDoubleOk );
top = topVariant.toDouble( &tDoubleOk );
return ( bDoubleOk && tDoubleOk );
}
return false;
}

//
// QgsMapBoxGlStyleConversionContext
//
Expand Down
10 changes: 10 additions & 0 deletions src/core/vectortile/qgsmapboxglstyleconverter.h
Expand Up @@ -538,6 +538,16 @@ class CORE_EXPORT QgsMapBoxGlStyleConverter
static QString parseValue( const QVariant &value, QgsMapBoxGlStyleConversionContext &context );
static QString parseKey( const QVariant &value );

/**
* \Checks if interpolation bottom/top values are numeric values
* \param bottomVariant bottom value
* \param topVariant top value
* \param bottom out: bottom value converted to double
* \param top out: top value converted to double
* \return true if both bottom and top value are numeric. False else (e.g. if one of the values is an expression)
*/
static bool numericArgumentsOnly( const QVariant &bottomVariant, const QVariant &topVariant, double &bottom, double &top );

QString mError;
QStringList mWarnings;

Expand Down
12 changes: 6 additions & 6 deletions tests/src/python/test_qgsmapboxglconverter.py
Expand Up @@ -234,28 +234,28 @@ def testInterpolateOpacityByZoom(self):
[150, 0.15],
[250, 0.2]]
}, 255, conversion_context).expressionString(),
"CASE WHEN @vector_tile_zoom < 0 THEN set_color_part(@symbol_color, 'alpha', 25.5) WHEN @vector_tile_zoom >= 0 AND @vector_tile_zoom < 150 THEN set_color_part(@symbol_color, 'alpha', scale_linear(@vector_tile_zoom,0,150,(0.1) * 255,(0.15) * 255)) WHEN @vector_tile_zoom >= 150 AND @vector_tile_zoom < 250 THEN set_color_part(@symbol_color, 'alpha', scale_linear(@vector_tile_zoom,150,250,(0.15) * 255,(0.2) * 255)) WHEN @vector_tile_zoom >= 250 THEN set_color_part(@symbol_color, 'alpha', 51) END")
"CASE WHEN @vector_tile_zoom < 0 THEN set_color_part(@symbol_color, 'alpha', 25.5) WHEN @vector_tile_zoom >= 0 AND @vector_tile_zoom < 150 THEN set_color_part(@symbol_color, 'alpha', scale_linear(@vector_tile_zoom,0,150,25.5,38.25)) WHEN @vector_tile_zoom >= 150 AND @vector_tile_zoom < 250 THEN set_color_part(@symbol_color, 'alpha', scale_linear(@vector_tile_zoom,150,250,38.25,51)) WHEN @vector_tile_zoom >= 250 THEN set_color_part(@symbol_color, 'alpha', 51) END")
self.assertEqual(QgsMapBoxGlStyleConverter.parseInterpolateOpacityByZoom({'base': 1,
'stops': [[0, 0.1],
[150, 0.15],
[250, 0.2]]
}, 100, conversion_context).expressionString(),
"CASE WHEN @vector_tile_zoom < 0 THEN set_color_part(@symbol_color, 'alpha', 10) WHEN @vector_tile_zoom >= 0 AND @vector_tile_zoom < 150 THEN set_color_part(@symbol_color, 'alpha', scale_linear(@vector_tile_zoom,0,150,(0.1) * 100,(0.15) * 100)) WHEN @vector_tile_zoom >= 150 AND @vector_tile_zoom < 250 THEN set_color_part(@symbol_color, 'alpha', scale_linear(@vector_tile_zoom,150,250,(0.15) * 100,(0.2) * 100)) WHEN @vector_tile_zoom >= 250 THEN set_color_part(@symbol_color, 'alpha', 20) END")
"CASE WHEN @vector_tile_zoom < 0 THEN set_color_part(@symbol_color, 'alpha', 10) WHEN @vector_tile_zoom >= 0 AND @vector_tile_zoom < 150 THEN set_color_part(@symbol_color, 'alpha', scale_linear(@vector_tile_zoom,0,150,10,15)) WHEN @vector_tile_zoom >= 150 AND @vector_tile_zoom < 250 THEN set_color_part(@symbol_color, 'alpha', scale_linear(@vector_tile_zoom,150,250,15,20)) WHEN @vector_tile_zoom >= 250 THEN set_color_part(@symbol_color, 'alpha', 20) END")
self.assertEqual(QgsMapBoxGlStyleConverter.parseInterpolateOpacityByZoom({'base': 1,
'stops': [[0, 0.1],
[150, 0.15]]
}, 255, conversion_context).expressionString(),
"set_color_part(@symbol_color, 'alpha', scale_linear(@vector_tile_zoom,0,150,(0.1) * 255,(0.15) * 255))")
"set_color_part(@symbol_color, 'alpha', scale_linear(@vector_tile_zoom,0,150,25.5,38.25))")
self.assertEqual(QgsMapBoxGlStyleConverter.parseInterpolateOpacityByZoom({'base': 2,
'stops': [[0, 0.1],
[150, 0.15]]
}, 255, conversion_context).expressionString(),
"set_color_part(@symbol_color, 'alpha', scale_exp(@vector_tile_zoom,0,150,(0.1) * 255,(0.15) * 255,2))")
"set_color_part(@symbol_color, 'alpha', scale_exp(@vector_tile_zoom,0,150,25.5,38.25,2))")
self.assertEqual(QgsMapBoxGlStyleConverter.parseInterpolateOpacityByZoom({'base': 2,
'stops': [[0, 0.1],
[150, 0.1]]
}, 255, conversion_context).expressionString(),
"set_color_part(@symbol_color, 'alpha', (0.1) * 255)")
"set_color_part(@symbol_color, 'alpha', 25.5)")

def testInterpolateListByZoom(self):
conversion_context = QgsMapBoxGlStyleConversionContext()
Expand All @@ -271,7 +271,7 @@ def testInterpolateListByZoom(self):
0.6
], QgsMapBoxGlStyleConverter.Opacity, conversion_context, 2)
self.assertEqual(prop.expressionString(),
"CASE WHEN @vector_tile_zoom < 10 THEN set_color_part(@symbol_color, 'alpha', 25.5) WHEN @vector_tile_zoom >= 10 AND @vector_tile_zoom < 15 THEN set_color_part(@symbol_color, 'alpha', scale_linear(@vector_tile_zoom,10,15,(0.1) * 255,(0.3) * 255)) WHEN @vector_tile_zoom >= 15 AND @vector_tile_zoom < 18 THEN set_color_part(@symbol_color, 'alpha', scale_linear(@vector_tile_zoom,15,18,(0.3) * 255,(0.6) * 255)) WHEN @vector_tile_zoom >= 18 THEN set_color_part(@symbol_color, 'alpha', 153) END")
"CASE WHEN @vector_tile_zoom < 10 THEN set_color_part(@symbol_color, 'alpha', 25.5) WHEN @vector_tile_zoom >= 10 AND @vector_tile_zoom < 15 THEN set_color_part(@symbol_color, 'alpha', scale_linear(@vector_tile_zoom,10,15,25.5,76.5)) WHEN @vector_tile_zoom >= 15 AND @vector_tile_zoom < 18 THEN set_color_part(@symbol_color, 'alpha', scale_linear(@vector_tile_zoom,15,18,76.5,153)) WHEN @vector_tile_zoom >= 18 THEN set_color_part(@symbol_color, 'alpha', 153) END")

prop, default_color, default_val = QgsMapBoxGlStyleConverter.parseInterpolateListByZoom([
"interpolate",
Expand Down

0 comments on commit e097f6f

Please sign in to comment.