I hope it’s OK to chime in here.
The values that are given in the arrays (elevationRamp
, slopeRamp
, and aspectRamp
) only define the color map. They are always in the range [0,1].
Cesium internally computes the elevation, slope, and aspect:
- The elevation is the actual elevation, based on the geo data. Here, this will be a value between roughly -414 and +8777 (meters), corresponding to the lowest and highest points on earth.
- The slope is a value between 0° and 90°.
- The aspect is a value between 0° and 360° (I think…)
In order to compute the color for these values, we need a value that we can use to look up the color in the color map. This must be a value in [0,1]. Let’s call it “lookupValue”
- For the elevation, we have lookupValue = (elevation - minHeight) / (maxHeight - minHeight)
- For the slope, we have lookupValue = slope / 90°
- For the aspect, we have lookupValue = aspect / 360°
This lookupValue is now always a value in [0,1], and can be used access the color map.
Disclaimer: No warranty that the following is all correct, but I tried to visualize it:
Here is an example of the result for the elevation: The x-axis shows the elevation, between -414 and 8777 meters. The y-axis shows the lookup value. The background shows the respective color.
This means that the Dead Sea would be painted in black, and Mount Everest would be painted in white. (Note that the color mapping is highly non-linear, to increase the “resolution” for non-extreme heights)
Here is the same for the slope:
And for the aspect:
In order to create a legend, you’ll need a function that can compute the color for a given elevation, slope, or aspect (depending on how many entries your legend should have).
A very quick+dirty implementation is shown here.
Note: In practice, this should be implemented differently. Right now, it creates the color array again each time when it is called, and covers the elevation, aspect and slope at the same time. But the main point is to show how the computation of the color for an arbitrary value can be done conceptually - namely, by using a binarySearch
of the lookupValue
in the “ramp” arrays, using the resulting index for accessing the two neighboring colors, and linearly interpolating between these colors using Color#lerp
.
function getColor(selectedShading, value) {
var minValue;
var maxValue;
var values;
if (selectedShading === "elevation") {
minValue = -414.0; // approximate dead sea elevation;
maxValue = 8777.0; // approximate everest elevation;
values = elevationRamp;
} else if (selectedShading === "slope") {
minValue = 0;
maxValue = Cesium.Math.PI / 2;
values = slopeRamp;
} else if (selectedShading === "aspect") {
minValue = 0;
maxValue = Cesium.Math.PI * 2;
values = aspectRamp;
}
var colors = [];
colors.push(Cesium.Color.fromCssColorString("#000000")); //black
colors.push(Cesium.Color.fromCssColorString("#2747E0")); //blue
colors.push(Cesium.Color.fromCssColorString("#D33B7D")); //pink
colors.push(Cesium.Color.fromCssColorString("#D33038")); //red
colors.push(Cesium.Color.fromCssColorString("#FF9742")); //orange
colors.push(Cesium.Color.fromCssColorString("#ffd700")); //yellow
colors.push(Cesium.Color.fromCssColorString("#ffffff")); //white
var lookupValue = (value - minValue) / (maxValue - minValue);
if (lookupValue <= 0) {
return colors[0];
}
if (lookupValue >= 1) {
return colors[colors.length-1];
}
function comparator(a, b) {
return a - b;
}
var index = Cesium.binarySearch(values, lookupValue, comparator);
if (index < 0) {
index = -index-2;
}
var color0 = colors[index];
var color1 = colors[index+1];
var value0 = values[index];
var value1 = values[index+1];
var relative = (lookupValue - value0) / (value1 - value0);
var result = Cesium.Color.lerp(color0, color1, relative, new Cesium.Color());
return result;
}
for (var e=-500; e<=9500; e+=1000) {
console.log("At elevation " + e + " color is " + getColor("elevation", e));
}
for (var s=-10; s<=100; s+=10) {
var sRad = Cesium.Math.toRadians(s);
console.log("At slope " + s + " (deg) color is " + getColor("slope", sRad));
}
for (var a=-50; a<=400; a+=50) {
var aRad = Cesium.Math.toRadians(a);
console.log("At aspect " + a + " (deg) color is " + getColor("aspect", aRad));
}