Skip to content

Commit

Permalink
Interpolate regular color stops from interpolated psuedocolor renderers
Browse files Browse the repository at this point in the history
And handle exact interpolation modes too

Fixes felt/qgis-plugin-discussion#70
  • Loading branch information
nyalldawson committed May 21, 2024
1 parent 8391894 commit dfe9fc5
Show file tree
Hide file tree
Showing 2 changed files with 413 additions and 3 deletions.
114 changes: 113 additions & 1 deletion felt/core/fsl_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@
QgsPalettedRasterRenderer,
QgsSingleBandGrayRenderer,
QgsRasterPipe,
QgsRasterDataProvider
QgsRasterDataProvider,
QgsColorRampShader
)

from .map_utils import MapUtils
Expand Down Expand Up @@ -90,6 +91,7 @@ def push_warning(self, warning: str, level: LogLevel = LogLevel.Warning):

class FslConverter:
NULL_COLOR = "rgba(0, 0, 0, 0)"
COLOR_RAMP_INTERPOLATION_STEPS = 30

@staticmethod
def create_symbol_dict() -> Dict[str, object]:
Expand Down Expand Up @@ -1599,6 +1601,30 @@ def singleband_pseudocolor_renderer_to_fsl(
Converts a singleband pseudocolor renderer to FSL
"""

shader = renderer.shader()
shader_function = shader.rasterShaderFunction()
if shader_function.colorRampType() == QgsColorRampShader.Discrete:
return FslConverter.discrete_pseudocolor_renderer_to_fsl(
renderer, context, opacity
)
elif shader_function.colorRampType() == QgsColorRampShader.Interpolated:
return FslConverter.continuous_pseudocolor_renderer_to_fsl(
renderer, context, opacity
)

return FslConverter.exact_pseudocolor_renderer_to_fsl(
renderer, context, opacity
)

@staticmethod
def discrete_pseudocolor_renderer_to_fsl(
renderer: QgsSingleBandPseudoColorRenderer,
context: ConversionContext,
opacity: float = 1
):
"""
Converts a discrete singleband pseudocolor renderer to FSL
"""
shader = renderer.shader()
shader_function = shader.rasterShaderFunction()
steps = [shader_function.minimumValue()]
Expand Down Expand Up @@ -1628,6 +1654,92 @@ def singleband_pseudocolor_renderer_to_fsl(
"type": "numeric"
}

@staticmethod
def exact_pseudocolor_renderer_to_fsl(
renderer: QgsSingleBandPseudoColorRenderer,
context: ConversionContext,
opacity: float = 1
):
"""
Converts an exact singleband pseudocolor renderer to FSL
"""
shader = renderer.shader()
shader_function = shader.rasterShaderFunction()

categories = []
colors = []
labels = {}
for i, item in enumerate(shader_function.colorRampItemList()):
if math.isinf(item.value):
continue

categories.append(str(item.value))
colors.append(item.color.name())
labels[str(i)] = item.label

return {
"config": {
"band": renderer.band(),
"categories": categories
},
"legend": {
"displayName": labels
},

"style": {
"isSandwiched": False,
"opacity": opacity,
"color": colors
},
"type": "categorical"
}

@staticmethod
def continuous_pseudocolor_renderer_to_fsl(
renderer: QgsSingleBandPseudoColorRenderer,
context: ConversionContext,
opacity: float = 1
):
"""
Converts a continuous singleband pseudocolor renderer to FSL
"""
shader = renderer.shader()
shader_function = shader.rasterShaderFunction()

min_value = shader_function.minimumValue()
max_value = shader_function.maximumValue()

# build 30 linear color steps between min and max value
steps = [shader_function.minimumValue()]
colors = []
labels = {}
for i in range(FslConverter.COLOR_RAMP_INTERPOLATION_STEPS):
val = (i * (max_value - min_value)
/ FslConverter.COLOR_RAMP_INTERPOLATION_STEPS + min_value)
ok, red, green, blue, alpha = shader_function.shade(val)
if ok:
steps.append(val)
colors.append(FslConverter.color_to_fsl(
QColor(red, green, blue, alpha), context, opacity))
labels[str(i)] = str(round(val, 3))

return {
"config": {
"band": renderer.band(),
"steps": steps
},
"legend": {
"displayName": labels
},

"style": {
"isSandwiched": False,
"opacity": opacity,
"color": colors
},
"type": "numeric"
}

@staticmethod
def singleband_gray_renderer_to_fsl(
renderer: QgsSingleBandGrayRenderer,
Expand Down
Loading

0 comments on commit dfe9fc5

Please sign in to comment.