Show legend on cesium slope, aspect and elevation

Dear All,

I’ve found the slope, aspect and elevation map of cesium through given link:- https://sandcastle.cesium.com/?src=Globe%20Materials.html
But legends are not available here. Is there any way to show the legends on map so that user can understand the meaning of the colors.

Thanks in Advance

You can use normal css/html to show legends on your application. The UI you see in the linked Sandcastle is some built-in UI elements we created for demo purposes. There is not an equivalent for legends.

1 Like

Thanks, yeah I can use css /html to show the legends but problem is here, how i’ll get the value respect to the colors and meaning of the colors in given example.

Extracting the meaning of the colors will require closer inspection of the code. For instance, if you are looking at the shading for elevation, you can see that on line 78, there are certain values for the elevation ramp:

[0.0, 0.045, 0.1, 0.15, 0.37, 0.54, 1.0]

These correspond to the colors represented from lines 97 to 103. You will need to match those colors up with the elevation ranges.

We are currently making improvements to our Sandcastle user experience. I will add this to our discussion to create better descriptions of Sandcastle examples, which will hopefully help you do the steps above.

1 Like

Dear dzung,

Thank you so much to make it very clear. It’s very helpful to me.

Thanks & Regards
Shashi

1 Like

Hi Dzung,
Already we had a discussion regarding the elevation/slope/aspect maps in the given sandcastle.
https://sandcastle.cesium.com/?src=Globe%20Materials.html.
I had issue with how to show legends and u suggest to show the values [0.0, 0.045, 0.1, 0.15, 0.37, 0.54, 1.0] using html/css it’s ok.

But problem is that it doesn’t make very clear to my client they want legends something like given images.
Aspect-Map-Legend

.
But I’ve not found any value like that in cesium sandcastle map. If it’s possible to kindly make it possible.

With best regards
Shashi

Dear Dzung,
Kindly do the needful help if it is possible.
Thanks
Shashi

The elevation ramp Sandcastle example is similar to this example you attached, where the colors are based on altitude.

If you check out the code on line 111 and 112, there are two values:

var minHeight = -414.0; // approximate Dead Sea elevation
var maxHeight = 8777.0; // approximate Everest elevation

We also know that the elevation ramp ranges from 0 to 1 with the following values:

var elevationRamp = [0.0, 0.045, 0.1, 0.15, 0.37, 0.54, 1.0];

In this case, 0 maps to -414 and 1 maps to 8777 (in meters). You can map the other values using a ratio. For instance, 0.1 maps to 505.1 because:

0.1*[8777-(-414)] + (-414) = 505.1

0.15 maps to 964.65. Looking at the colors from lines 97 to 103, we know the elevations are mapped to the colors as follows:

  grd.addColorStop(values[0], "#000000"); //black at 0.0
  grd.addColorStop(values[1], "#2747E0"); //blue at 0.045
  grd.addColorStop(values[2], "#D33B7D"); //pink at 0.1
  grd.addColorStop(values[3], "#D33038"); //red at 0.15
  grd.addColorStop(values[4], "#FF9742"); //orange at 0.37
  grd.addColorStop(values[5], "#ffd700"); //yellow at 0.54
  grd.addColorStop(values[6], "#ffffff"); //white at 1.0

Knowing that 0.1 maps to ~505 and 0.15 maps to ~965, you can then create a legend for values between 505 and 965, where 505 to 735 (halfway between 505 and 965) is a pink color and 735 to 965 is a red color.

Does that help?

1 Like

First of all, I’m very thankful to you to help me out and for explaining very well it is useful but still, I’ve few queries which I need to explain to my client like:-

  1. Can u pls send me the origin of given formula if it is available - 0.1*[8777-(-414)] + (-414) = 505.1
    // elevationRamp * [maxHeight-(minHeight)]+(minHeight)
  2. In the same manner how I’ll get slope in degree and aspect sides(like north, south, east, west, north-south, etc.) as given in images I sent you, is there any formula for the slope and aspect.
    Aspect-Map-Legend SlopeMap

Thanks in Advance
Shashi

Hi Dzung,

Pls, do the needful help if it’s possible.

Thanks
Shashi

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));
}
2 Likes

Thank u so much i’ll try it. But it seems fine i guess it’ll solve my problem.