Open mrouan opened 7 months ago
Le type de données OpenLayers concerné est le WebGL (GeoTiff) : https://openlayers.org/en/latest/apidoc/module-ol_layer_WebGLTile-WebGLTileLayer.html
Il permet d'utiliser une source de couche OpenLayers GeoTIFF via la librairie GeoTiff.js : https://geotiffjs.github.io/
En prérequis, un workshop permet de cerner la création / affichage / rendu de ce type de couche () :
https://openlayers.org/workshop/en/cog/colormap.html
La réalisation d'un style semble donc utiliser les "expressionValue" Openlayers qui est une syntaxe spécifique à OpenLayers. Cette syntaxe permet de réaliser un style via un ensemble d'expression logique.
On peut notamment faire une classification selon une liste de valeur, des croisements (opérations) entre plusieurs bands d'un raster, etc. (voir les URLs pour plus d'informations).
Si le flux est un WMS, il est possible d'utiliser un SLD avec GeoServer. Dans notre cas, c'est le WPS qui retourne un TIFF directement.
La documentation OpenLayers pour le type WebGL ne semble pas permettre l'utilisation d'un SLD.
Nous avons donc testés de reprendre la liste des valeurs du SLD, et de l'appliquer dans une expressionValue OpenLayers afin de représenter le TIFF.
Voici un exemple pour réaliser une classification à partir de valeurs d'une bande d'un TIFF :
const bandValue = ['band', 1];
const layer = new ol.layer.WebGLTile({
source: src,
style: {
color: [
'case',
// couleur si la valeur de band est == à -0
['==', bandValue, -0],
['color', 0, 0, 0, 0],
// couleur si la valeur de band est <= à -4
['<=', bandValue, -4],
['color', 62,55,144, 1],
['<=', bandValue, -3.75],
['color', 164, 252, 60, 1],
// valeurs par défaut
['color', 0, 0, 0, 1]
]
}
})
Le résultat n'étant pas satisfaisant pour LETG, cette issue à été créée.
Il est donc demander de créer un code complexe qui nécessite de :
En l'état, rien n'est prévu dans OpenLayers pour cette réalisation déjà annoncée comme complexe. Il semble qu'il serait toutefois possible d'avoir ce type de rendu avec une opération d'interpolation disponible dans les expressionValue OpenLayers. Mais ce code nécessite l'ajout d'une librairie externe type colormap.js inspirée de la librairie maplotLibre.
Des essais ont au préalable était réalisés en dehors du mviewer et avec un TIFF issue de la comparaison de 2 MNT avec SAGA :
https://codesandbox.io/p/sandbox/cog-no-data-interpolate-forked-j2n8qz?file=%2Fmain.js
new TileLayer({
source: source,
style: {
color: [
"interpolate",
["linear"],
layer,
// le nombre 40 correspond au nombre de couleurs différentes à obtenir par valeur
// c'est le nombre de valeurs qui existent entre -4 et +6 à des pas de 0,25:
// 10 / 0,25 = ~40
...getColorStops("jet", -4, 6, 40, false),
],
},
}),
La valeur "jet" correspond à la palette suivante dans colormap:
Ce code peut sembler intéressant, et nécessite un test dans mviewer.
Pour être utilisable dans mviewer, il faut créer une extension colormap qui n'est pas disponible directement en tant que librairie buildée (type CDN). Il faut donc utiliser une extension type "module" et recopier la librairie (ce qui n'est pas très long).
Ensuite, un test peut être réalisé dans un customLayer avec un TIFF issue d'une comparaison de 2 MNT SAGA.
Je viens de tester avec un POC accessible ici :
https://codesandbox.io/p/devbox/range-colormap-tiff-openlayers-dyp4y3?file=%2Fmain.js%3A108%2C1
Pour voir en plein écran :
Il permet de voir les valeurs obtenues sur le pixel et la palette associée sur la gauche pour vérification :
En complément, le test précédent utilise des valeurs min et max (série de -4 à +6) pour définir le nombre de couleur.
J'ai regardé pour calculer de manière automatique les limites de ces valeurs (-4 et +6) à partir du raster. OpenLayers semble permettre de lire les METADATA d'un raster TIFF via la librairie GeoTIFF.js:
import {fromUrl as tiffFromUrl} from 'geotiff';
let g = await tiffFromUrl(url);
let img = await g.getImage();
let metadata = [];
for(let i = 0; i < img.getSamplesPerPixel(); i++) {
metadata.push(img.getGDALMetadata(i));
}
Mais dans notre cas, aucune METADATA n'a été rajouté.
3 options s'offrent à nous :
On recherche comment rajouter dans le TIFF ces valeur MIN et MAX dans les métadata, ce qui implique de passer du temps supplémentaire dans la production de l'image TIFF de comparaison pour voir comment rajouter ces valeurs, et surtout comment le faire de la bonne manière (inconnu pour ce qui me concerne actuellement)
On décide de conserver des valeurs fixe en constante (on aura toujours -4 et +6 ou d'autres valeurs qui ne bougeront pas)
On modifie l'interface pour rajouter 2 champs qui permettent de modifier à la demande dans le module MADDOG ces valeurs et permettre ainsi à l'utilisateur de borner l'interpolation (pour rappel, entre -4 et +6 avec un step de 0.25, on aura 40 couleurs => le nombre de couleurs est défini selon le step et les valeurs MIN - MAX à représenter). Cette dernière option nécessite de passer du temps sur l'ajout dans l'interface de 3 INPUT type number pour pouvoir "jouer" avec le MIN / MAX / STEP de la représentation du TIFF.
@mrouan redis moi si ce n'est pas clair et ce qui te semble le plus intéressant. J'aime assez la 3è options. La seconde est la + rapide à mettre en oeuvre. La première comprend le plus d'incertitude sur le résultat final.
Dans tous les cas, je vais commencer à tester dans le mviewer pour voir le rendu avec l'exemple (POC) précédent afin d'avoir une idée du rendu / temps de réponse.
Complément sur les résultats, les couleurs ne correspondent pas exactement au besoin suivant :
du min à -0,02 : gamme de couleur allant du bleu foncé au vert clair par pas de 0,25 de 0,02 à max : gamme de couleur allant du jaune clair au rouge foncé par pas de 0,25
Après réflexion, il ne faudrait pas utiliser qu'une palette de couleurs mais une concaténation de plusieurs palettes si c'est possible.
Pour rappel, les palettes de la librairies colormap sont disponibles ici et on a utilisé "jet" dans l'exemple précédent :
https://github.com/bpostlethwaite/colormap
Il faudrait alors faire correspondre ces cas :
de min à -0.02 -> bleu foncé au vert clair par pas de 0,25 -> palette WINTER
de +0.02 à max -> du jaune clair au rouge foncé par pas de 0,25 -> palette OXYGEN ou HOT
Je viens de mettre en place un test qui prend compte de mon dernier commentaire (en utilisant 2 palettes donc) : https://codesandbox.io/p/devbox/range-colormap-tiff-openlayers-dyp4y3?file=%2Fmain.js%3A135%2C4
Pour jongler entre cette version et la précédent, il est possible d'inverser le commentaire entre la ligne 113 et 114 :
//...colorsBySteps("jet", valueMin, valueMax, steps, isTransparent, false),
...colorsFromManyRange(),
Les valeurs d'entrées peuvent être modifiées facilement en haut du fichier si besoin (et si le fichier est éditable par tous).
Description
La légende du résultat de comparaison devrait être calculée de la manière suivante de -0,02m à 0,02m : blanc ou transparent du min à -0,02 : gamme de couleur allant du bleu foncé au vert clair par pas de 0,25 de 0,02 à max : gamme de couleur allant du jaune clair au rouge foncé par pas de 0,25
min et max étant les valeurs minimum et maximum du MNT issu du résultat de la comparaison