From c50d775330a763ca93e3aefb5adeb4763c459536 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Fri, 26 Jun 2015 16:33:58 -0600 Subject: [PATCH] Vertical exaggeration control --- examples/shaded-relief.css | 4 +++ examples/shaded-relief.html | 20 +++++++++---- examples/shaded-relief.js | 59 +++++++++++++++++++++---------------- 3 files changed, 51 insertions(+), 32 deletions(-) create mode 100644 examples/shaded-relief.css diff --git a/examples/shaded-relief.css b/examples/shaded-relief.css new file mode 100644 index 0000000000..f829965da2 --- /dev/null +++ b/examples/shaded-relief.css @@ -0,0 +1,4 @@ +table.controls td { + text-align: center; + padding: 2px 5px; +} diff --git a/examples/shaded-relief.html b/examples/shaded-relief.html index ffe416692c..bd8fe05cd9 100644 --- a/examples/shaded-relief.html +++ b/examples/shaded-relief.html @@ -28,11 +28,19 @@ tags: "raster, shaded relief"
-
- - - - -
+ + + + + + + + + + + + + +
vertical exaggeration: x
sun elevation: °
sun azimuth: °
diff --git a/examples/shaded-relief.js b/examples/shaded-relief.js index ff33184fc0..4d9456173b 100644 --- a/examples/shaded-relief.js +++ b/examples/shaded-relief.js @@ -1,8 +1,9 @@ goog.require('ol.Map'); goog.require('ol.View'); +goog.require('ol.layer.Image'); goog.require('ol.layer.Tile'); -goog.require('ol.source.TileJSON'); goog.require('ol.source.Raster'); +goog.require('ol.source.TileJSON'); goog.require('ol.source.XYZ'); @@ -10,7 +11,7 @@ goog.require('ol.source.XYZ'); * Generates a shaded relief image given elevation data. Uses a 3x3 * neighborhood for determining slope and aspect. * @param {Array.} inputs Array of input images. - * @param {Object} data Data with resolution property. + * @param {Object} data Data added in the "beforeoperations" event. * @return {Array.} Output images (only the first is rendered). */ function shade(inputs, data) { @@ -19,14 +20,16 @@ function shade(inputs, data) { var height = elevationImage.height; var elevationData = elevationImage.data; var shadeData = new Uint8ClampedArray(elevationData.length); - var dx = dy = data.resolution * 2; + var dp = data.resolution * 2; var maxX = width - 1; var maxY = height - 1; var pixel = [0, 0, 0, 0]; var twoPi = 2 * Math.PI; var halfPi = Math.PI / 2; - var cosSunEl = Math.cos(data.sunEl); - var sinSunEl = Math.sin(data.sunEl); + var sunEl = Math.PI * data.sunEl / 180; + var sunAz = Math.PI * data.sunAz / 180; + var cosSunEl = Math.cos(sunEl); + var sinSunEl = Math.sin(sunEl); var pixelX, pixelY, x0, x1, y0, y1, offset, z0, z1, dzdx, dzdy, slope, aspect, cosIncidence, scaled; for (pixelY = 0; pixelY <= maxY; ++pixelY) { @@ -42,7 +45,7 @@ function shade(inputs, data) { pixel[1] = elevationData[offset + 1]; pixel[2] = elevationData[offset + 2]; pixel[3] = elevationData[offset + 3]; - z0 = pixel[0] + pixel[1] * 2 + pixel[2] * 3; + z0 = data.vert * (pixel[0] + pixel[1] * 2 + pixel[2] * 3); // determine elevation for (x1, pixelY) offset = (pixelY * width + x1) * 4; @@ -50,9 +53,9 @@ function shade(inputs, data) { pixel[1] = elevationData[offset + 1]; pixel[2] = elevationData[offset + 2]; pixel[3] = elevationData[offset + 3]; - z1 = pixel[0] + pixel[1] * 2 + pixel[2] * 3; + z1 = data.vert * (pixel[0] + pixel[1] * 2 + pixel[2] * 3); - dzdx = (z1 - z0) / dx; + dzdx = (z1 - z0) / dp; // determine elevation for (pixelX, y0) offset = (y0 * width + pixelX) * 4; @@ -60,7 +63,7 @@ function shade(inputs, data) { pixel[1] = elevationData[offset + 1]; pixel[2] = elevationData[offset + 2]; pixel[3] = elevationData[offset + 3]; - z0 = pixel[0] + pixel[1] * 2 + pixel[2] * 3; + z0 = data.vert * (pixel[0] + pixel[1] * 2 + pixel[2] * 3); // determine elevation for (pixelX, y1) offset = (y1 * width + pixelX) * 4; @@ -68,9 +71,9 @@ function shade(inputs, data) { pixel[1] = elevationData[offset + 1]; pixel[2] = elevationData[offset + 2]; pixel[3] = elevationData[offset + 3]; - z1 = pixel[0] + pixel[1] * 2 + pixel[2] * 3; + z1 = data.vert * (pixel[0] + pixel[1] * 2 + pixel[2] * 3); - dzdy = (z1 - z0) / dy; + dzdy = (z1 - z0) / dp; slope = Math.atan(Math.sqrt(dzdx * dzdx + dzdy * dzdy)); @@ -84,7 +87,7 @@ function shade(inputs, data) { } cosIncidence = sinSunEl * Math.cos(slope) + - cosSunEl * Math.sin(slope) * Math.cos(data.sunAz - aspect); + cosSunEl * Math.sin(slope) * Math.cos(sunAz - aspect); offset = (pixelY * width + pixelX) * 4; scaled = 255 * cosIncidence; @@ -124,27 +127,31 @@ var map = new ol.Map({ ], view: new ol.View({ extent: [-13675026, 4439648, -13580856, 4580292], - center: [-13606539, 4492849], + center: [-13615645, 4497969], minZoom: 10, maxZoom: 16, - zoom: 12 + zoom: 13 }) }); -var sunElevationInput = document.getElementById('sun-el'); -var sunAzimuthInput = document.getElementById('sun-az'); - -sunElevationInput.addEventListener('input', function() { - raster.changed(); -}); - -sunAzimuthInput.addEventListener('input', function() { - raster.changed(); +var controlIds = ['vert', 'sunEl', 'sunAz']; +var controls = {}; +controlIds.forEach(function(id) { + var control = document.getElementById(id); + var output = document.getElementById(id + 'Out'); + control.addEventListener('input', function() { + output.innerText = control.value; + raster.changed(); + }); + output.innerText = control.value; + controls[id] = control; }); raster.on('beforeoperations', function(event) { // the event.data object will be passed to operations - event.data.resolution = event.resolution; - event.data.sunEl = Math.PI * sunElevationInput.value / 180; - event.data.sunAz = Math.PI * sunAzimuthInput.value / 180; + var data = event.data; + data.resolution = event.resolution; + for (var id in controls) { + data[id] = Number(controls[id].value); + } });