diff --git a/examples/3dtiles_ion.html b/examples/3dtiles_ion.html index a33bd62710..3ef10b4227 100644 --- a/examples/3dtiles_ion.html +++ b/examples/3dtiles_ion.html @@ -77,8 +77,8 @@ new itowns.ElevationLayer(config.id, config), ); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); // ---------- ADD 3D TILES MODEL FROM CESIUM ION SERVER : ---------- diff --git a/examples/effects_split.html b/examples/effects_split.html index 4f77d2d78f..de753803e5 100644 --- a/examples/effects_split.html +++ b/examples/effects_split.html @@ -84,8 +84,8 @@ var layer = new itowns.ElevationLayer(config.id, config); view.addLayer(layer); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); // Slide handling function splitSliderMove(evt) { diff --git a/examples/effects_stereo.html b/examples/effects_stereo.html index 8a34317780..dc9cdda2a6 100644 --- a/examples/effects_stereo.html +++ b/examples/effects_stereo.html @@ -72,8 +72,8 @@ var layer = new itowns.ElevationLayer(config.id, config); view.addLayer(layer).then(menuGlobe.addLayerGUI.bind(menuGlobe)); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); /* eslint-disable no-unused-vars */ function updateEyeSep(value) { diff --git a/examples/entwine_3d_loader.html b/examples/entwine_3d_loader.html index f01f724eed..1b9f303a41 100644 --- a/examples/entwine_3d_loader.html +++ b/examples/entwine_3d_loader.html @@ -51,8 +51,8 @@ var layer = new itowns.ElevationLayer(config.id, config); view.addLayer(layer); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); var eptLayer, eptSource; diff --git a/examples/geoid_geoidLayer.html b/examples/geoid_geoidLayer.html index e1888c7873..ab7cc2220b 100644 --- a/examples/geoid_geoidLayer.html +++ b/examples/geoid_geoidLayer.html @@ -63,8 +63,8 @@ new itowns.ElevationLayer(config.id, config), ).then(debugMenu.addLayerGUI.bind(debugMenu)); } - itowns.Fetcher.json('layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); diff --git a/examples/itowns-potree.html b/examples/itowns-potree.html index 58f8888cbb..c9f3dd89c0 100644 --- a/examples/itowns-potree.html +++ b/examples/itowns-potree.html @@ -208,8 +208,8 @@ new itowns.ElevationLayer(config.id, config), ); } - itowns.Fetcher.json('layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); diff --git a/examples/layers/JSONLayers/IGN_MNT_HIGHRES.json b/examples/layers/JSONLayers/IGN_MNT_HIGHRES.json index 88af0c1402..caace6ea7a 100644 --- a/examples/layers/JSONLayers/IGN_MNT_HIGHRES.json +++ b/examples/layers/JSONLayers/IGN_MNT_HIGHRES.json @@ -1,6 +1,9 @@ { "id": "IGN_MNT_HIGHRES", "noDataValue" : -99999, + "clampValues": { + "min": 0 + }, "updateStrategy": { "type": 1, "options": { diff --git a/examples/misc_camera_animation.html b/examples/misc_camera_animation.html index abde202d33..c3c4eda405 100644 --- a/examples/misc_camera_animation.html +++ b/examples/misc_camera_animation.html @@ -66,8 +66,8 @@ new itowns.ElevationLayer(config.id, config), ); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); diff --git a/examples/misc_camera_traveling.html b/examples/misc_camera_traveling.html index 3a2274a5b5..156ad31e27 100644 --- a/examples/misc_camera_traveling.html +++ b/examples/misc_camera_traveling.html @@ -68,8 +68,8 @@ let layer = new itowns.ElevationLayer(config.id, config); view.addLayer(layer); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); // ---------- Select camera positions and travel through these positions : ---------- diff --git a/examples/misc_clamp_ground.html b/examples/misc_clamp_ground.html index 3133ec04ec..1e5317d0c8 100644 --- a/examples/misc_clamp_ground.html +++ b/examples/misc_clamp_ground.html @@ -50,8 +50,8 @@ var layer = new itowns.ElevationLayer(config.id, config); view.addLayer(layer).then(menuGlobe.addLayerGUI.bind(menuGlobe)); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); function addMeshToScene() { // creation of the new mesh (a cylinder) diff --git a/examples/misc_collada.html b/examples/misc_collada.html index 948ad90ee0..cb0205a0b6 100644 --- a/examples/misc_collada.html +++ b/examples/misc_collada.html @@ -60,8 +60,8 @@ var layer = new itowns.ElevationLayer(config.id, config); view.addLayer(layer).then(menuGlobe.addLayerGUI.bind(menuGlobe)); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); // ThreeLoader can load each format proposed in ThreeJs examples loaders : https://github.com/mrdoob/three.js/tree/dev/examples/js/loaders var promiseCollada = ThreeLoader.load('Collada', 'https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/models/collada/building.dae') diff --git a/examples/misc_colorlayer_visibility.html b/examples/misc_colorlayer_visibility.html index e9ef8a53d2..22129be348 100644 --- a/examples/misc_colorlayer_visibility.html +++ b/examples/misc_colorlayer_visibility.html @@ -41,8 +41,8 @@ itowns.Fetcher.json('./layers/JSONLayers/Ortho.json').then(addColorLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/Cada.json').then(addColorLayerFromConfig); - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); view.addEventListener(itowns.GLOBE_VIEW_EVENTS.GLOBE_INITIALIZED, function _() { // eslint-disable-next-line no-console diff --git a/examples/misc_custom_controls.html b/examples/misc_custom_controls.html index 604f0a87fc..fba92648d9 100644 --- a/examples/misc_custom_controls.html +++ b/examples/misc_custom_controls.html @@ -52,8 +52,8 @@ new itowns.ElevationLayer(config.id, config), ); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); const customControls = { // Disable pan movement diff --git a/examples/misc_custom_label.html b/examples/misc_custom_label.html index 592a484c59..efc0d32b03 100644 --- a/examples/misc_custom_label.html +++ b/examples/misc_custom_label.html @@ -57,8 +57,8 @@ config.source = new itowns.WMTSSource(config.source); view.addLayer(new itowns.ElevationLayer(config.id, config)); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); debug.createTileDebugUI(menuGlobe.gui, view); // Create a custom div which will be displayed as a label diff --git a/examples/misc_georeferenced_images.html b/examples/misc_georeferenced_images.html index 7659433ee5..02627efbab 100644 --- a/examples/misc_georeferenced_images.html +++ b/examples/misc_georeferenced_images.html @@ -71,8 +71,8 @@ var layer = new itowns.ElevationLayer(config.id, config); view.addLayer(layer).then(menuGlobe.addLayerGUI.bind(menuGlobe)); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); pictureInfos = { panoramic: { diff --git a/examples/plugins_drag_n_drop.html b/examples/plugins_drag_n_drop.html index dbe95d3ce8..7f15835ba1 100644 --- a/examples/plugins_drag_n_drop.html +++ b/examples/plugins_drag_n_drop.html @@ -50,8 +50,8 @@ var layer = new itowns.ElevationLayer(config.id, config); view.addLayer(layer); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); DragNDrop.setView(view); DragNDrop.register('geojson', DragNDrop.JSON, itowns.GeoJsonParser.parse, DragNDrop.COLOR); diff --git a/examples/source_file_geojson_3d.html b/examples/source_file_geojson_3d.html index 87789da023..08ff6df51f 100644 --- a/examples/source_file_geojson_3d.html +++ b/examples/source_file_geojson_3d.html @@ -43,8 +43,8 @@ var layer = new itowns.ElevationLayer(config.id, config); view.addLayer(layer).then(menuGlobe.addLayerGUI.bind(menuGlobe)); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); // Add a geometry layer, which will contain the multipolygon to display var marne = new itowns.FeatureGeometryLayer('Marne', { diff --git a/examples/source_file_geojson_raster.html b/examples/source_file_geojson_raster.html index b4ac0d5c7a..0a49b694a0 100644 --- a/examples/source_file_geojson_raster.html +++ b/examples/source_file_geojson_raster.html @@ -53,8 +53,8 @@ var layer = new itowns.ElevationLayer(config.id, config); view.addLayer(layer).then(menuGlobe.addLayerGUI.bind(menuGlobe)); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); // Display the content of two GeoJSON files on terrain with ColorLayer and FileSource. diff --git a/examples/source_file_gpx_3d.html b/examples/source_file_gpx_3d.html index 1b0cafc7ce..c42c04a315 100644 --- a/examples/source_file_gpx_3d.html +++ b/examples/source_file_gpx_3d.html @@ -44,8 +44,8 @@ var layer = new itowns.ElevationLayer(config.id, config); view.addLayer(layer); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); // update the waypoint var distance, scale, point = new itowns.THREE.Vector3(); diff --git a/examples/source_file_gpx_raster.html b/examples/source_file_gpx_raster.html index 076aa87164..ff813d5340 100644 --- a/examples/source_file_gpx_raster.html +++ b/examples/source_file_gpx_raster.html @@ -54,8 +54,8 @@ var layer = new itowns.ElevationLayer(config.id, config); view.addLayer(layer).then(menuGlobe.addLayerGUI.bind(menuGlobe)); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); const gpxSource = new itowns.FileSource({ diff --git a/examples/source_file_kml_raster.html b/examples/source_file_kml_raster.html index bc8947a904..75dfa9258d 100644 --- a/examples/source_file_kml_raster.html +++ b/examples/source_file_kml_raster.html @@ -53,8 +53,8 @@ var layer = new itowns.ElevationLayer(config.id, config); view.addLayer(layer).then(menuGlobe.addLayerGUI.bind(menuGlobe)); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); // Fetch, Parse and Convert by iTowns var kmlSource = new itowns.FileSource({ diff --git a/examples/source_stream_wfs_3d.html b/examples/source_stream_wfs_3d.html index 3f79b17597..64399fb9fb 100644 --- a/examples/source_stream_wfs_3d.html +++ b/examples/source_stream_wfs_3d.html @@ -59,8 +59,8 @@ var layer = new itowns.ElevationLayer(config.id, config); view.addLayer(layer).then(menuGlobe.addLayerGUI.bind(menuGlobe)); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); var color = new itowns.THREE.Color(); var tile; diff --git a/examples/source_stream_wfs_raster.html b/examples/source_stream_wfs_raster.html index 5e3eca36df..204b442738 100644 --- a/examples/source_stream_wfs_raster.html +++ b/examples/source_stream_wfs_raster.html @@ -50,8 +50,8 @@ var layer = new itowns.ElevationLayer(config.id, config); view.addLayer(layer).then(menuGlobe.addLayerGUI.bind(menuGlobe)); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); function isValidData(data) { if(data.features[0].geometries.length < 1000) { diff --git a/examples/vector_tile_3d_mesh.html b/examples/vector_tile_3d_mesh.html index 8522b69d64..f5d78b953a 100644 --- a/examples/vector_tile_3d_mesh.html +++ b/examples/vector_tile_3d_mesh.html @@ -61,8 +61,8 @@ new itowns.ElevationLayer(config.id, config), ).then(debugMenu.addLayerGUI.bind(debugMenu)); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); // ---------- DISPLAY VECTOR TILED MAP DATA AS A ColorLayer : ---------- diff --git a/examples/view_3d_map.html b/examples/view_3d_map.html index 77b1eb6361..7fe0dfd933 100644 --- a/examples/view_3d_map.html +++ b/examples/view_3d_map.html @@ -71,9 +71,8 @@ new itowns.ElevationLayer(config.id, config), ).then(debugMenu.addLayerGUI.bind(debugMenu)); } - itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); - + itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); // ---------- ADD SOME WIDGETS : ---------- diff --git a/examples/view_3d_mns_map.html b/examples/view_3d_mns_map.html index 3023d580d5..728d48ef90 100644 --- a/examples/view_3d_mns_map.html +++ b/examples/view_3d_mns_map.html @@ -72,8 +72,6 @@ new itowns.ElevationLayer(config.id, config), ).then(debugMenu.addLayerGUI.bind(debugMenu)); } - - itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/IGN_MNS_HIGHRES.json').then(addElevationLayerFromConfig); // ---------- ADD SOME WIDGETS : ---------- diff --git a/examples/widgets_minimap.html b/examples/widgets_minimap.html index f4fc76a504..b19b8177a7 100644 --- a/examples/widgets_minimap.html +++ b/examples/widgets_minimap.html @@ -78,8 +78,8 @@ new itowns.ElevationLayer(config.id, config), ).then(debugMenu.addLayerGUI.bind(debugMenu)); } - itowns.Fetcher.json('layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); diff --git a/examples/widgets_navigation.html b/examples/widgets_navigation.html index 97cac1c29e..c96c6552d6 100644 --- a/examples/widgets_navigation.html +++ b/examples/widgets_navigation.html @@ -72,8 +72,8 @@ new itowns.ElevationLayer(config.id, config), ).then(debugMenu.addLayerGUI.bind(debugMenu)); } - itowns.Fetcher.json('layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); diff --git a/examples/widgets_scale.html b/examples/widgets_scale.html index 617ac18c7d..22fd41c12b 100644 --- a/examples/widgets_scale.html +++ b/examples/widgets_scale.html @@ -73,8 +73,8 @@ new itowns.ElevationLayer(config.id, config), ).then(debugMenu.addLayerGUI.bind(debugMenu)); } - itowns.Fetcher.json('layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); diff --git a/examples/widgets_searchbar.html b/examples/widgets_searchbar.html index e6e4ff499c..5af4a201d0 100644 --- a/examples/widgets_searchbar.html +++ b/examples/widgets_searchbar.html @@ -73,8 +73,8 @@ new itowns.ElevationLayer(config.id, config), ).then(debugMenu.addLayerGUI.bind(debugMenu)); } - itowns.Fetcher.json('layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + itowns.Fetcher.json('layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); diff --git a/src/Layer/ElevationLayer.js b/src/Layer/ElevationLayer.js index f3c0bc02a0..e8e9d094b9 100644 --- a/src/Layer/ElevationLayer.js +++ b/src/Layer/ElevationLayer.js @@ -7,6 +7,8 @@ import { RasterElevationTile } from 'Renderer/RasterTile'; * an ElevationLayer. Default is true. You should not change this, as it is used * internally for optimisation. * @property {number} noDataValue - Used to specify a **null** or **no data value** in the elevation terrain. + * @property {number} [zmin] - Used to specify a minimum value for the elevation terrain (if the data goes lower, it will be clamped). + * @property {number} [zmax] - Used to specify a maximum value for the elevation terrain (if the data goes higher, it will be clamped) * @property {number} scale - Used to apply a scale on the elevation value. It * can be used for exageration of the elevation, like in [this * example](https://www.itowns-project.org/itowns/examples/#plugins_pyramidal_tiff). @@ -37,6 +39,11 @@ class ElevationLayer extends RasterLayer { * contains three elements `name, protocol, extent`, these elements will be * available using `layer.name` or something else depending on the property * name. + * @param {number} [config.noDataValue] The value coding the noData in the data set + * @param {Object} [config.clampValues] - Optional information for clamping + * the elevation between a minimum and a maximum value + * @param {number} [config.clampValues.min] The minimum value to clamp the elevation + * @param {number} [config.clampValues.max] The maximum value to clamp the elevation * * @example * // Create an ElevationLayer @@ -54,6 +61,11 @@ class ElevationLayer extends RasterLayer { */ constructor(id, config = {}) { super(id, config); + if (config.zmin || config.zmax) { + console.warn('Config using zmin and zmax are deprecated, use {clampValues: {min, max}} structure.'); + } + this.zmin = config.clampValues?.min ?? config.zmin; + this.zmax = config.clampValues?.max ?? config.zmax; this.isElevationLayer = true; this.defineLayerProperty('scale', this.scale || 1.0); } diff --git a/src/Parser/XbilParser.js b/src/Parser/XbilParser.js index 8291d9c86d..8ce7c7d588 100644 --- a/src/Parser/XbilParser.js +++ b/src/Parser/XbilParser.js @@ -1,30 +1,38 @@ import { readTextureValueWithBilinearFiltering } from 'Utils/DEMUtils'; -function minMax4Corners(texture, pitch, noDataValue) { +function minMax4Corners(texture, pitch, options) { const u = pitch.x; const v = pitch.y; const w = pitch.z; const z = [ - readTextureValueWithBilinearFiltering({ noDataValue }, texture, u, v), - readTextureValueWithBilinearFiltering({ noDataValue }, texture, u + w, v), - readTextureValueWithBilinearFiltering({ noDataValue }, texture, u + w, v + w), - readTextureValueWithBilinearFiltering({ noDataValue }, texture, u, v + w), - ].filter(v => v != undefined && v > -10); + readTextureValueWithBilinearFiltering(options, texture, u, v), + readTextureValueWithBilinearFiltering(options, texture, u + w, v), + readTextureValueWithBilinearFiltering(options, texture, u + w, v + w), + readTextureValueWithBilinearFiltering(options, texture, u, v + w), + ].filter(val => val != undefined); if (z.length) { return { min: Math.min(...z), max: Math.max(...z) }; + } else { + return { + min: Infinity, + max: -Infinity, + }; } } /** - * Calculates the minimum maximum texture elevation with xbil data - * - * @param {THREE.Texture} texture The texture to parse - * @param {THREE.Vector4} pitch The pitch, restrict zone to parse - * @param {number} noDataValue No data value - * @return {Object} The minimum maximum elevation. - */ -export function computeMinMaxElevation(texture, pitch, noDataValue) { + * Calculates the minimum maximum texture elevation with xbil data + * + * @param {THREE.Texture} texture The texture to parse + * @param {THREE.Vector4} pitch The pitch, restrict zone to parse + * @param {Object} options No data value and clamp values + * @param {number} options.noDataValue No data value + * @param {number} [options.zmin] The minimum elevation value after which it will be clamped + * @param {number} [options.zmax] The maximum elevation value after which it will be clamped + * @return {Object} The minimum and maximum elevation. + */ +export function computeMinMaxElevation(texture, pitch, options) { const { width, height, data } = texture.image; if (!data) { // Return null values means there's no elevation values. @@ -33,8 +41,8 @@ export function computeMinMaxElevation(texture, pitch, noDataValue) { return { min: null, max: null }; } - // compute extact minimum and maximum elvation on 4 corners texture. - let { min, max } = minMax4Corners(texture, pitch, noDataValue) || { max: -Infinity, min: Infinity }; + // compute the minimum and maximum elevation on the 4 corners texture. + let { min, max } = minMax4Corners(texture, pitch, options); const sizeX = Math.floor(pitch.z * width); @@ -50,12 +58,14 @@ export function computeMinMaxElevation(texture, pitch, noDataValue) { const limX = x + sizeX; for (x; x < limX; x += inc) { const val = data[x]; - if (val > -10 && val != noDataValue) { + if (val !== options.noDataValue) { max = Math.max(max, val); min = Math.min(min, val); } } } + if (options.zmin > min) { min = options.zmin; } + if (options.zmax < max) { max = options.zmax; } } if (max === -Infinity || min === Infinity) { @@ -77,21 +87,11 @@ export function checkNodeElevationTextureValidity(data, noDataValue) { data[l - Math.sqrt(l)] > noDataValue; } -function getIndiceWithPitch(i, pitch, w) { - // Return corresponding indice in parent tile using pitch - const currentX = (i % w) / w; // normalized - const currentY = Math.floor(i / w) / w; // normalized - const newX = pitch.x + currentX * pitch.z; - const newY = pitch.y + currentY * pitch.w; - const newIndice = Math.floor(newY * w) * w + Math.floor(newX * w); - return newIndice; -} - -// This function replaces noDataValue by significant values from parent texture -export function insertSignificantValuesFromParent(data, dataParent, noDataValue, pitch) { +// This function replaces noDataValue by significant values from parent texture (or 0) +export function insertSignificantValuesFromParent(data, dataParent = () => 0, noDataValue) { for (let i = 0, l = data.length; i < l; ++i) { if (data[i] === noDataValue) { - data[i] = dataParent[getIndiceWithPitch(i, pitch, 256)]; + data[i] = dataParent(i); } } } diff --git a/src/Renderer/LayeredMaterial.js b/src/Renderer/LayeredMaterial.js index e7cbe9c20d..6e34b79a8d 100644 --- a/src/Renderer/LayeredMaterial.js +++ b/src/Renderer/LayeredMaterial.js @@ -40,6 +40,7 @@ export const colorLayerEffects = { const defaultStructLayer = { bias: 0, + noDataValue: -99999, zmin: 0, zmax: 0, scale: 0, diff --git a/src/Renderer/RasterTile.js b/src/Renderer/RasterTile.js index 3e5215f623..5fc47207ff 100644 --- a/src/Renderer/RasterTile.js +++ b/src/Renderer/RasterTile.js @@ -7,6 +7,15 @@ export const EMPTY_TEXTURE_ZOOM = -1; const pitch = new THREE.Vector4(); +function getIndiceWithPitch(i, pitch, w) { + // Return corresponding indice in parent tile using pitch + const currentX = (i % w) / w; // normalized + const currentY = Math.floor(i / w) / w; // normalized + const newX = pitch.x + currentX * pitch.z; + const newY = pitch.y + currentY * pitch.w; + const newIndice = Math.floor(newY * w) * w + Math.floor(newX * w); + return newIndice; +} /** * A `RasterTile` is part of raster [`Layer`]{@link Layer} data. @@ -124,7 +133,7 @@ export class RasterElevationTile extends RasterTile { const defaultEle = { bias: 0, mode: ELEVATION_MODES.DATA, - zmin: 0, + zmin: -Infinity, zmax: Infinity, }; @@ -145,11 +154,10 @@ export class RasterElevationTile extends RasterTile { this.min = 0; this.max = 0; } - - this.bias = layer.bias || defaultEle.bias; - this.mode = layer.mode || defaultEle.mode; - this.zmin = layer.zmin || defaultEle.zmin; - this.zmax = layer.zmax || defaultEle.zmax; + this.bias = layer.bias ?? defaultEle.bias; + this.mode = layer.mode ?? defaultEle.mode; + this.zmin = layer.zmin ?? defaultEle.zmin; + this.zmax = layer.zmax ?? defaultEle.zmax; layer.addEventListener('scale-property-changed', this._handlerCBEvent); } @@ -186,7 +194,14 @@ export class RasterElevationTile extends RasterTile { updateMinMaxElevation() { if (this.textures[0] && !this.layer.useColorTextureElevation) { - const { min, max } = computeMinMaxElevation(this.textures[0], this.offsetScales[0], this.layer.noDataValue); + const { min, max } = computeMinMaxElevation( + this.textures[0], + this.offsetScales[0], + { + noDataValue: this.layer.noDataValue, + zmin: this.layer.zmin, + zmax: this.layer.zmax, + }); if (this.min != min || this.max != max) { this.min = min; this.max = max; @@ -199,13 +214,18 @@ export class RasterElevationTile extends RasterTile { if (nodatavalue == undefined) { return; } - // replace no datat value with parent texture value. + // replace no data value with parent texture value or 0 (if no significant value found). const parentTexture = this.textures[0]; const parentDataElevation = parentTexture && parentTexture.image && parentTexture.image.data; const dataElevation = texture.image && texture.image.data; - if (dataElevation && parentDataElevation && !checkNodeElevationTextureValidity(dataElevation, nodatavalue)) { - texture.extent.offsetToParent(parentTexture.extent, pitch); - insertSignificantValuesFromParent(dataElevation, parentDataElevation, nodatavalue, pitch); + + if (dataElevation && !checkNodeElevationTextureValidity(dataElevation, nodatavalue)) { + insertSignificantValuesFromParent(dataElevation, parentDataElevation && dataParent(texture, parentTexture, parentDataElevation, pitch), nodatavalue); } } } + +function dataParent(texture, parentTexture, parentDataElevation, pitch) { + texture.extent.offsetToParent(parentTexture.extent, pitch); + return i => parentDataElevation[getIndiceWithPitch(i, pitch, 256)]; +} diff --git a/src/Renderer/Shader/Chunk/elevation_pars_vertex.glsl b/src/Renderer/Shader/Chunk/elevation_pars_vertex.glsl index a6dff221ca..4738e0b13d 100644 --- a/src/Renderer/Shader/Chunk/elevation_pars_vertex.glsl +++ b/src/Renderer/Shader/Chunk/elevation_pars_vertex.glsl @@ -35,8 +35,7 @@ float getElevation(vec2 uv, sampler2D tex, vec4 offsetScale, Layer layer) { uv = uv * offsetScale.zw + offsetScale.xy; - float d = getElevationMode(uv, tex, layer.mode); - if (d < layer.zmin || d > layer.zmax) d = 0.; + float d = clamp(getElevationMode(uv, tex, layer.mode), layer.zmin, layer.zmax); return d * layer.scale + layer.bias; } #endif