mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-11-04 00:04:25 -05:00 
			
		
		
		
	Color work, some tests
This commit is contained in:
		
							parent
							
								
									96c2ddbade
								
							
						
					
					
						commit
						c4858b4231
					
				@ -23,7 +23,7 @@ settings.
 | 
			
		||||
%End
 | 
			
		||||
  public:
 | 
			
		||||
 | 
			
		||||
    QgsMapBoxGlStyleConverter( const QVariantMap &style );
 | 
			
		||||
    QgsMapBoxGlStyleConverter( const QVariantMap &style, const QString &styleName = QString() );
 | 
			
		||||
%Docstring
 | 
			
		||||
Constructor for QgsMapBoxGlStyleConverter.
 | 
			
		||||
 | 
			
		||||
@ -53,7 +53,51 @@ or ``None`` if the style could not be converted successfully.
 | 
			
		||||
 | 
			
		||||
  protected:
 | 
			
		||||
 | 
			
		||||
    void parseLayers( const QVariantList &layers );
 | 
			
		||||
    void parseLayers( const QVariantList &layers, const QString &styleName );
 | 
			
		||||
%Docstring
 | 
			
		||||
Parse list of ``layers`` from JSON
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
    static bool parseFillLayer( const QVariantMap &jsonLayer, const QString &styleName, QgsVectorTileBasicRendererStyle &style /Out/ );
 | 
			
		||||
%Docstring
 | 
			
		||||
Parses a fill layer.
 | 
			
		||||
 | 
			
		||||
:param jsonLayer: fill layer to parse
 | 
			
		||||
:param styleName: style name
 | 
			
		||||
 | 
			
		||||
:return: - ``True`` if the layer was successfully parsed.
 | 
			
		||||
         - style: generated QGIS vector tile style
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
    static QgsProperty parseInterpolateColorByZoom( const QVariantMap &json );
 | 
			
		||||
 | 
			
		||||
    static QColor parseColor( const QVariant &color );
 | 
			
		||||
%Docstring
 | 
			
		||||
Parses a ``color`` in one of these supported formats:
 | 
			
		||||
 | 
			
		||||
- #fff or #ffffff
 | 
			
		||||
- hsl(30, 19%, 90%) or hsla(30, 19%, 90%, 0.4)
 | 
			
		||||
- rgb(10, 20, 30) or rgba(10, 20, 30, 0.5)
 | 
			
		||||
 | 
			
		||||
Returns an invalid color if the color could not be parsed.
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
    static void colorAsHslaComponents( const QColor &color, int &hue, int &saturation, int &lightness, int &alpha );
 | 
			
		||||
%Docstring
 | 
			
		||||
Takes a QColor object and returns HSLA components in required format for QGIS :py:func:`~QgsMapBoxGlStyleConverter.color_hsla` expression function.
 | 
			
		||||
 | 
			
		||||
:param color: input color
 | 
			
		||||
:param hue: an integer value from 0 to 360
 | 
			
		||||
:param saturation: an integer value from 0 to 100
 | 
			
		||||
:param lightness: an integer value from 0 to 100
 | 
			
		||||
:param alpha: an integer value from 0 (completely transparent) to 255 (opaque).
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
    static QString interpolateExpression( int zoomMin, int zoomMax, double valueMin, double valueMax, double base );
 | 
			
		||||
%Docstring
 | 
			
		||||
Generates an interpolation for values between ``valueMin`` and ``valueMax``, scaled between the
 | 
			
		||||
ranges ``zoomMin`` to ``zoomMax``.
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    QgsMapBoxGlStyleConverter( const QgsMapBoxGlStyleConverter &other );
 | 
			
		||||
 | 
			
		||||
@ -16,13 +16,17 @@
 | 
			
		||||
#include "qgsmapboxglstyleconverter.h"
 | 
			
		||||
#include "qgsvectortilebasicrenderer.h"
 | 
			
		||||
#include "qgsvectortilebasiclabeling.h"
 | 
			
		||||
#include "qgssymbollayer.h"
 | 
			
		||||
#include "qgssymbollayerutils.h"
 | 
			
		||||
#include "qgslogger.h"
 | 
			
		||||
 | 
			
		||||
QgsMapBoxGlStyleConverter::QgsMapBoxGlStyleConverter( const QVariantMap &style )
 | 
			
		||||
 | 
			
		||||
QgsMapBoxGlStyleConverter::QgsMapBoxGlStyleConverter( const QVariantMap &style, const QString &styleName )
 | 
			
		||||
  : mStyle( style )
 | 
			
		||||
{
 | 
			
		||||
  if ( mStyle.contains( QStringLiteral( "layers" ) ) )
 | 
			
		||||
  {
 | 
			
		||||
    parseLayers( mStyle.value( QStringLiteral( "layers" ) ).toList() );
 | 
			
		||||
    parseLayers( mStyle.value( QStringLiteral( "layers" ) ).toList(), styleName );
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
@ -32,9 +36,254 @@ QgsMapBoxGlStyleConverter::QgsMapBoxGlStyleConverter( const QVariantMap &style )
 | 
			
		||||
 | 
			
		||||
QgsMapBoxGlStyleConverter::~QgsMapBoxGlStyleConverter() = default;
 | 
			
		||||
 | 
			
		||||
void QgsMapBoxGlStyleConverter::parseLayers( const QVariantList &layers )
 | 
			
		||||
void QgsMapBoxGlStyleConverter::parseLayers( const QVariantList &layers, const QString &styleName )
 | 
			
		||||
{
 | 
			
		||||
  QList<QgsVectorTileBasicRendererStyle> rendererStyles;
 | 
			
		||||
  QList<QgsVectorTileBasicLabelingStyle> labelingStyles;
 | 
			
		||||
 | 
			
		||||
  for ( const QVariant &layer : layers )
 | 
			
		||||
  {
 | 
			
		||||
    const QVariantMap jsonLayer = layer.toMap();
 | 
			
		||||
 | 
			
		||||
    const QString layerType = jsonLayer.value( QStringLiteral( "type" ) ).toString();
 | 
			
		||||
    if ( layerType == QLatin1String( "background" ) )
 | 
			
		||||
      continue;
 | 
			
		||||
 | 
			
		||||
    const QString styleId = jsonLayer.value( QStringLiteral( "id" ) ).toString();
 | 
			
		||||
    const QString layerName = jsonLayer.value( QStringLiteral( "source-layer" ) ).toString();
 | 
			
		||||
 | 
			
		||||
    const int minZoom = jsonLayer.value( QStringLiteral( "minzoom" ), QStringLiteral( "-1" ) ).toInt();
 | 
			
		||||
    const int maxZoom = jsonLayer.value( QStringLiteral( "maxzoom" ), QStringLiteral( "-1" ) ).toInt();
 | 
			
		||||
 | 
			
		||||
    const bool enabled = jsonLayer.value( QStringLiteral( "visibility" ) ).toString() != QLatin1String( "none" );
 | 
			
		||||
 | 
			
		||||
    QString filterExpression;
 | 
			
		||||
    if ( jsonLayer.contains( QStringLiteral( "filter" ) ) )
 | 
			
		||||
    {
 | 
			
		||||
      // filterExpression = parseExpression( jsonLayer.value( QStringLiteral( "filter" ) ) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QgsVectorTileBasicRendererStyle rendererStyle;
 | 
			
		||||
    QgsVectorTileBasicLabelingStyle labelingStyle;
 | 
			
		||||
 | 
			
		||||
    bool hasRendererStyle = false;
 | 
			
		||||
    bool hasLabelingStyle = false;
 | 
			
		||||
    if ( layerType == QLatin1String( "fill" ) )
 | 
			
		||||
    {
 | 
			
		||||
      hasRendererStyle = parseFillLayer( jsonLayer, styleName, rendererStyle );
 | 
			
		||||
    }
 | 
			
		||||
    else if ( layerType == QLatin1String( "line" ) )
 | 
			
		||||
    {
 | 
			
		||||
      // hasRendererStyle = parseLineLayer( jsonLayer, styleName );
 | 
			
		||||
    }
 | 
			
		||||
    else if ( layerType == QLatin1String( "symbol" ) )
 | 
			
		||||
    {
 | 
			
		||||
      // hasLabelingStyle = parseSymbolLayer( jsonLayer, styleName );
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      QgsDebugMsg( QStringLiteral( "Skipping unknown layer type: %1" ).arg( layerType ) );
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ( hasRendererStyle )
 | 
			
		||||
    {
 | 
			
		||||
      rendererStyle.setStyleName( styleId );
 | 
			
		||||
      rendererStyle.setLayerName( layerName );
 | 
			
		||||
      rendererStyle.setFilterExpression( filterExpression );
 | 
			
		||||
      rendererStyle.setMinZoomLevel( minZoom );
 | 
			
		||||
      rendererStyle.setMaxZoomLevel( maxZoom );
 | 
			
		||||
      rendererStyle.setEnabled( enabled );
 | 
			
		||||
      rendererStyles.append( rendererStyle );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ( hasLabelingStyle )
 | 
			
		||||
    {
 | 
			
		||||
      labelingStyle.setStyleName( styleId );
 | 
			
		||||
      labelingStyle.setLayerName( layerName );
 | 
			
		||||
      labelingStyle.setFilterExpression( filterExpression );
 | 
			
		||||
      labelingStyle.setMinZoomLevel( minZoom );
 | 
			
		||||
      labelingStyle.setMaxZoomLevel( maxZoom );
 | 
			
		||||
      labelingStyle.setEnabled( enabled );
 | 
			
		||||
      labelingStyles.append( labelingStyle );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  mRenderer = qgis::make_unique< QgsVectorTileBasicRenderer >();
 | 
			
		||||
  QgsVectorTileBasicRenderer *renderer = dynamic_cast< QgsVectorTileBasicRenderer *>( mRenderer.get() );
 | 
			
		||||
  renderer->setStyles( rendererStyles );
 | 
			
		||||
 | 
			
		||||
  mLabeling = qgis::make_unique< QgsVectorTileBasicLabeling >();
 | 
			
		||||
  QgsVectorTileBasicLabeling *labeling = dynamic_cast< QgsVectorTileBasicLabeling * >( mLabeling.get() );
 | 
			
		||||
  labeling->setStyles( labelingStyles );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QgsMapBoxGlStyleConverter::parseFillLayer( const QVariantMap &jsonLayer, const QString &styleName, QgsVectorTileBasicRendererStyle &style )
 | 
			
		||||
{
 | 
			
		||||
  if ( !jsonLayer.contains( QStringLiteral( "paint" ) ) )
 | 
			
		||||
  {
 | 
			
		||||
    QgsDebugMsg( QStringLiteral( "Style layer %1 has no paint property, skipping" ).arg( jsonLayer.value( QStringLiteral( "id" ) ).toString() ) );
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const QVariantMap jsonPaint = jsonLayer.value( QStringLiteral( "paint" ) ).toMap();
 | 
			
		||||
 | 
			
		||||
  QgsPropertyCollection ddProperties;
 | 
			
		||||
 | 
			
		||||
  // fill color
 | 
			
		||||
  QColor fillColor;
 | 
			
		||||
  if ( jsonLayer.contains( QStringLiteral( "fill-color" ) ) )
 | 
			
		||||
  {
 | 
			
		||||
    const QVariant jsonFillColor = jsonPaint.value( QStringLiteral( "fill-color" ) );
 | 
			
		||||
    switch ( jsonFillColor.type() )
 | 
			
		||||
    {
 | 
			
		||||
      case QVariant::Map:
 | 
			
		||||
        ddProperties.setProperty( QgsSymbolLayer::PropertyFillColor, parseInterpolateColorByZoom( jsonFillColor.toMap() ) );
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case QVariant::List:
 | 
			
		||||
      case QVariant::StringList:
 | 
			
		||||
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case QVariant::String:
 | 
			
		||||
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      default:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QgsProperty QgsMapBoxGlStyleConverter::parseInterpolateColorByZoom( const QVariantMap &json )
 | 
			
		||||
{
 | 
			
		||||
  const double base = json.value( QStringLiteral( "base" ), QStringLiteral( "1" ) ).toDouble();
 | 
			
		||||
  const QVariantList stops = json.value( QStringLiteral( "stops" ) ).toList();
 | 
			
		||||
  if ( stops.empty() )
 | 
			
		||||
    return QgsProperty();
 | 
			
		||||
 | 
			
		||||
  QString caseString = QStringLiteral( "CASE " );
 | 
			
		||||
 | 
			
		||||
  if ( base == 1 )
 | 
			
		||||
  {
 | 
			
		||||
    // base = 1 -> scale linear
 | 
			
		||||
    for ( int i = 0; i < stops.length() - 1; ++i )
 | 
			
		||||
    {
 | 
			
		||||
      // step bottom zoom
 | 
			
		||||
      const QString bz = stops.at( i ).toList().value( 0 ).toString();
 | 
			
		||||
      // step top zoom
 | 
			
		||||
      const QString tz = stops.at( i + 1 ).toList().value( 0 ).toString();
 | 
			
		||||
 | 
			
		||||
      const QColor bottomColor = parseColor( stops.at( i ).toList().value( 1 ) );
 | 
			
		||||
      const QColor topColor = parseColor( stops.at( i + 1 ).toList().value( 1 ) );
 | 
			
		||||
 | 
			
		||||
      int bcHue;
 | 
			
		||||
      int bcSat;
 | 
			
		||||
      int bcLight;
 | 
			
		||||
      int bcAlpha;
 | 
			
		||||
      colorAsHslaComponents( bottomColor, bcHue, bcSat, bcLight, bcAlpha );
 | 
			
		||||
      int tcHue;
 | 
			
		||||
      int tcSat;
 | 
			
		||||
      int tcLight;
 | 
			
		||||
      int tcAlpha;
 | 
			
		||||
      colorAsHslaComponents( topColor, tcHue, tcSat, tcLight, tcAlpha );
 | 
			
		||||
 | 
			
		||||
      caseString += QStringLiteral( "WHEN @zoom_level >= %1 AND @zoom_level < %2 THEN color_hsla("
 | 
			
		||||
                                    "scale_linear(@zoom_level, %1, %2, %3, %4), "
 | 
			
		||||
                                    "scale_linear(@zoom_level, %1, %2, %5, %6), "
 | 
			
		||||
                                    "scale_linear(@zoom_level, %1, %2, %7, %8), "
 | 
			
		||||
                                    "scale_linear(@zoom_level, %1, %2, %9, %10)) "
 | 
			
		||||
                                  ).arg( bz, tz )
 | 
			
		||||
                    .arg( bcHue )
 | 
			
		||||
                    .arg( tcHue )
 | 
			
		||||
                    .arg( bcSat )
 | 
			
		||||
                    .arg( tcSat )
 | 
			
		||||
                    .arg( bcLight )
 | 
			
		||||
                    .arg( tcLight )
 | 
			
		||||
                    .arg( bcAlpha )
 | 
			
		||||
                    .arg( tcAlpha );
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    // Base != 1 -> scale_exp()
 | 
			
		||||
    for ( int i = 0; i < stops.length() - 1; ++i )
 | 
			
		||||
    {
 | 
			
		||||
      // step bottom zoom
 | 
			
		||||
      const QString bz = stops.at( i ).toList().value( 0 ).toString();
 | 
			
		||||
      // step top zoom
 | 
			
		||||
      const QString tz = stops.at( i + 1 ).toList().value( 0 ).toString();
 | 
			
		||||
 | 
			
		||||
      const QColor bottomColor = parseColor( stops.at( i ).toList().value( 1 ) );
 | 
			
		||||
      const QColor topColor = parseColor( stops.at( i + 1 ).toList().value( 1 ) );
 | 
			
		||||
 | 
			
		||||
      int bcHue;
 | 
			
		||||
      int bcSat;
 | 
			
		||||
      int bcLight;
 | 
			
		||||
      int bcAlpha;
 | 
			
		||||
      colorAsHslaComponents( bottomColor, bcHue, bcSat, bcLight, bcAlpha );
 | 
			
		||||
      int tcHue;
 | 
			
		||||
      int tcSat;
 | 
			
		||||
      int tcLight;
 | 
			
		||||
      int tcAlpha;
 | 
			
		||||
      colorAsHslaComponents( topColor, tcHue, tcSat, tcLight, tcAlpha );
 | 
			
		||||
 | 
			
		||||
      caseString += QStringLiteral( "WHEN @zoom_level >= %1 AND @zoom_level < %2 THEN color_hsla("
 | 
			
		||||
                                    "%3, %4, %5, %6) " ).arg( bz, tz,
 | 
			
		||||
                                        interpolateExpression( bz.toInt(), tz.toInt(), bcHue, tcHue, base ),
 | 
			
		||||
                                        interpolateExpression( bz.toInt(), tz.toInt(), bcSat, tcSat, base ),
 | 
			
		||||
                                        interpolateExpression( bz.toInt(), tz.toInt(), bcLight, tcLight, base ),
 | 
			
		||||
                                        interpolateExpression( bz.toInt(), tz.toInt(), bcAlpha, tcAlpha, base ) );
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // top color
 | 
			
		||||
  const QString tz = stops.last().toList().value( 0 ).toString();
 | 
			
		||||
  const QColor topColor = parseColor( stops.last().toList().value( 1 ) );
 | 
			
		||||
  int tcHue;
 | 
			
		||||
  int tcSat;
 | 
			
		||||
  int tcLight;
 | 
			
		||||
  int tcAlpha;
 | 
			
		||||
  colorAsHslaComponents( topColor, tcHue, tcSat, tcLight, tcAlpha );
 | 
			
		||||
 | 
			
		||||
  caseString += QStringLiteral( "WHEN @zoom_level >= %1 THEN color_hsla(%2, %3, %4, %5) "
 | 
			
		||||
                                "ELSE color_hsla(%2, %3, %4, %5) END" ).arg( tz )
 | 
			
		||||
                .arg( tcHue ).arg( tcSat ).arg( tcLight ).arg( tcAlpha );
 | 
			
		||||
 | 
			
		||||
  return QgsProperty::fromExpression( caseString );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QColor QgsMapBoxGlStyleConverter::parseColor( const QVariant &color )
 | 
			
		||||
{
 | 
			
		||||
  if ( color.type() != QVariant::String )
 | 
			
		||||
  {
 | 
			
		||||
    QgsDebugMsg( QStringLiteral( "Could not parse non-string color %1, skipping" ).arg( color.toString() ) );
 | 
			
		||||
    return QColor();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return QgsSymbolLayerUtils::parseColor( color.toString() );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QgsMapBoxGlStyleConverter::colorAsHslaComponents( const QColor &color, int &hue, int &saturation, int &lightness, int &alpha )
 | 
			
		||||
{
 | 
			
		||||
  hue = std::max( 0, color.hslHue() );
 | 
			
		||||
  saturation = color.hslSaturation() / 255.0 * 100;
 | 
			
		||||
  lightness = color.lightness() / 255.0 * 100;
 | 
			
		||||
  alpha = color.alpha();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString QgsMapBoxGlStyleConverter::interpolateExpression( int zoomMin, int zoomMax, double valueMin, double valueMax, double base )
 | 
			
		||||
{
 | 
			
		||||
  return QStringLiteral( "%1 + %2 * (%3^(@zoom_level-%4)-1)/(%3^(%5-%4)-1)" ).arg( valueMin )
 | 
			
		||||
         .arg( valueMax - valueMin )
 | 
			
		||||
         .arg( base )
 | 
			
		||||
         .arg( zoomMin )
 | 
			
		||||
         .arg( zoomMax );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QgsVectorTileRenderer *QgsMapBoxGlStyleConverter::renderer() const
 | 
			
		||||
 | 
			
		||||
@ -18,11 +18,13 @@
 | 
			
		||||
 | 
			
		||||
#include "qgis_core.h"
 | 
			
		||||
#include "qgis_sip.h"
 | 
			
		||||
#include "qgsproperty.h"
 | 
			
		||||
#include <QVariantMap>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
class QgsVectorTileRenderer;
 | 
			
		||||
class QgsVectorTileLabeling;
 | 
			
		||||
class QgsVectorTileBasicRendererStyle;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \ingroup core
 | 
			
		||||
@ -40,7 +42,7 @@ class CORE_EXPORT QgsMapBoxGlStyleConverter
 | 
			
		||||
     *
 | 
			
		||||
     * The specified MapBox GL \a style configuration will be converted.
 | 
			
		||||
     */
 | 
			
		||||
    QgsMapBoxGlStyleConverter( const QVariantMap &style );
 | 
			
		||||
    QgsMapBoxGlStyleConverter( const QVariantMap &style, const QString &styleName = QString() );
 | 
			
		||||
 | 
			
		||||
    //! QgsMapBoxGlStyleConverter cannot be copied
 | 
			
		||||
    QgsMapBoxGlStyleConverter( const QgsMapBoxGlStyleConverter &other ) = delete;
 | 
			
		||||
@ -69,7 +71,49 @@ class CORE_EXPORT QgsMapBoxGlStyleConverter
 | 
			
		||||
 | 
			
		||||
  protected:
 | 
			
		||||
 | 
			
		||||
    void parseLayers( const QVariantList &layers );
 | 
			
		||||
    /**
 | 
			
		||||
     * Parse list of \a layers from JSON
 | 
			
		||||
     */
 | 
			
		||||
    void parseLayers( const QVariantList &layers, const QString &styleName );
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Parses a fill layer.
 | 
			
		||||
     *
 | 
			
		||||
     * \param jsonLayer fill layer to parse
 | 
			
		||||
     * \param styleName style name
 | 
			
		||||
     * \param style generated QGIS vector tile style
 | 
			
		||||
     * \returns TRUE if the layer was successfully parsed.
 | 
			
		||||
     */
 | 
			
		||||
    static bool parseFillLayer( const QVariantMap &jsonLayer, const QString &styleName, QgsVectorTileBasicRendererStyle &style SIP_OUT );
 | 
			
		||||
 | 
			
		||||
    static QgsProperty parseInterpolateColorByZoom( const QVariantMap &json );
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Parses a \a color in one of these supported formats:
 | 
			
		||||
     *
 | 
			
		||||
     * - #fff or #ffffff
 | 
			
		||||
     * - hsl(30, 19%, 90%) or hsla(30, 19%, 90%, 0.4)
 | 
			
		||||
     * - rgb(10, 20, 30) or rgba(10, 20, 30, 0.5)
 | 
			
		||||
     *
 | 
			
		||||
     * Returns an invalid color if the color could not be parsed.
 | 
			
		||||
     */
 | 
			
		||||
    static QColor parseColor( const QVariant &color );
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Takes a QColor object and returns HSLA components in required format for QGIS color_hsla() expression function.
 | 
			
		||||
     * \param color input color
 | 
			
		||||
     * \param hue an integer value from 0 to 360
 | 
			
		||||
     * \param saturation an integer value from 0 to 100
 | 
			
		||||
     * \param lightness an integer value from 0 to 100
 | 
			
		||||
     * \param alpha an integer value from 0 (completely transparent) to 255 (opaque).
 | 
			
		||||
     */
 | 
			
		||||
    static void colorAsHslaComponents( const QColor &color, int &hue, int &saturation, int &lightness, int &alpha );
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Generates an interpolation for values between \a valueMin and \a valueMax, scaled between the
 | 
			
		||||
     * ranges \a zoomMin to \a zoomMax.
 | 
			
		||||
     */
 | 
			
		||||
    static QString interpolateExpression( int zoomMin, int zoomMax, double valueMin, double valueMax, double base );
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
 | 
			
		||||
@ -78,7 +122,6 @@ class CORE_EXPORT QgsMapBoxGlStyleConverter
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    QVariantMap mStyle;
 | 
			
		||||
    QString mError;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -44,12 +44,36 @@ TEST_DATA_DIR = unitTestDataPath()
 | 
			
		||||
 | 
			
		||||
class TestQgsMapBoxGlStyleConverter(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    maxDiff = 100000
 | 
			
		||||
 | 
			
		||||
    def testNoLayer(self):
 | 
			
		||||
        c = QgsMapBoxGlStyleConverter({'x': 'y'})
 | 
			
		||||
        self.assertEqual(c.errorMessage(), 'Could not find layers list in JSON')
 | 
			
		||||
        self.assertIsNone(c.renderer())
 | 
			
		||||
        self.assertIsNone(c.labeling())
 | 
			
		||||
 | 
			
		||||
    def testInterpolateExpression(self):
 | 
			
		||||
        self.assertEqual(QgsMapBoxGlStyleConverter.interpolateExpression(5, 13, 27, 29, 1),
 | 
			
		||||
                         '27 + 2 * (1^(@zoom_level-5)-1)/(1^(13-5)-1)')
 | 
			
		||||
        self.assertEqual(QgsMapBoxGlStyleConverter.interpolateExpression(5, 13, 27, 29, 1.5),
 | 
			
		||||
                         '27 + 2 * (1.5^(@zoom_level-5)-1)/(1.5^(13-5)-1)')
 | 
			
		||||
 | 
			
		||||
    def testColorAsHslaComponents(self):
 | 
			
		||||
        self.assertEqual(QgsMapBoxGlStyleConverter.colorAsHslaComponents(QColor.fromHsl(30, 50, 70)), (30, 19, 27, 255))
 | 
			
		||||
 | 
			
		||||
    def testParseInterpolateColorByZoom(self):
 | 
			
		||||
        self.assertEqual(QgsMapBoxGlStyleConverter.parseInterpolateColorByZoom({}).isActive(), False)
 | 
			
		||||
        self.assertEqual(QgsMapBoxGlStyleConverter.parseInterpolateColorByZoom({'base': 1,
 | 
			
		||||
                                                                                'stops': [[0, '#f1f075'],
 | 
			
		||||
                                                                                          [150, '#b52e3e'],
 | 
			
		||||
                                                                                          [250, '#e55e5e']]
 | 
			
		||||
                                                                                }).expressionString(), 'CASE WHEN @zoom_level >= 0 AND @zoom_level < 150 THEN color_hsla(scale_linear(@zoom_level, 0, 150, 59, 352), scale_linear(@zoom_level, 0, 150, 81, 59), scale_linear(@zoom_level, 0, 150, 70, 44), scale_linear(@zoom_level, 0, 150, 255, 255)) WHEN @zoom_level >= 150 AND @zoom_level < 250 THEN color_hsla(scale_linear(@zoom_level, 150, 250, 352, 0), scale_linear(@zoom_level, 150, 250, 59, 72), scale_linear(@zoom_level, 150, 250, 44, 63), scale_linear(@zoom_level, 150, 250, 255, 255)) WHEN @zoom_level >= 250 THEN color_hsla(0, 72, 63, 255) ELSE color_hsla(0, 72, 63, 255) END')
 | 
			
		||||
        self.assertEqual(QgsMapBoxGlStyleConverter.parseInterpolateColorByZoom({'base': 2,
 | 
			
		||||
                                                                                'stops': [[0, '#f1f075'],
 | 
			
		||||
                                                                                          [150, '#b52e3e'],
 | 
			
		||||
                                                                                          [250, '#e55e5e']]
 | 
			
		||||
                                                                                }).expressionString(), 'CASE WHEN @zoom_level >= 0 AND @zoom_level < 150 THEN color_hsla(59 + 293 * (2^(@zoom_level-0)-1)/(2^(150-0)-1), 81 + -22 * (2^(@zoom_level-0)-1)/(2^(150-0)-1), 70 + -26 * (2^(@zoom_level-0)-1)/(2^(150-0)-1), 255 + 0 * (2^(@zoom_level-0)-1)/(2^(150-0)-1)) WHEN @zoom_level >= 150 AND @zoom_level < 250 THEN color_hsla(352 + -352 * (2^(@zoom_level-150)-1)/(2^(250-150)-1), 59 + 13 * (2^(@zoom_level-150)-1)/(2^(250-150)-1), 44 + 19 * (2^(@zoom_level-150)-1)/(2^(250-150)-1), 255 + 0 * (2^(@zoom_level-150)-1)/(2^(250-150)-1)) WHEN @zoom_level >= 250 THEN color_hsla(0, 72, 63, 255) ELSE color_hsla(0, 72, 63, 255) END')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    unittest.main()
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user