Isobands are the regions where the raster values are in an interval. It’s useful to simplify the visualized data, since the method shown at the drawing raster data section can create confusing images.

Calculating these isobands can be a bit difficult, that’s why I adapted the MarchingSquares.js library to use with a geoPath: raster-marching-squares

The important code parts are these. You can find the whole code here.

var projection = d3.geoAzimuthalEqualArea()
    .rotate([-55.5, -24])
  • The projection is set to geoAzimuthalEqualArea, but the nice thing about D3js is that this could be changed and the result would change accordingly
  .get(function(error, tiffData){
d3.json("world-110m.json", function(error, topojsonData) {
  • Note that, as explained in the reading a raster page, the request is a bit different for the GeoTIFF
  var tiff = GeoTIFF.parse(tiffData.response);
  var image = tiff.getImage();
  var rasters = image.readRasters();
  var tiepoint = image.getTiePoints()[0];
  var pixelScale = image.getFileDirectory().ModelPixelScale;
  var geoTransform = [tiepoint.x, pixelScale[0], 0, tiepoint.y, 0, -1*pixelScale[1]];
  var invGeoTransform = [-geoTransform[0]/geoTransform[1], 1/geoTransform[1],0,-geoTransform[3]/geoTransform[5],0,1/geoTransform[5]];

  var tempData = new Array(image.getHeight());
  for (var j = 0; j<image.getHeight(); j++){
      tempData[j] = new Array(image.getWidth());
      for (var i = 0; i<image.getWidth(); i++){
          tempData[j][i] = rasters[1][i + j*image.getWidth()];
var intervalsTemp = [14,17,20,23,26,29, 32, 35, 38];
var bandsTemp = rastertools.isobands(tempData, geoTransform, intervalsTemp);
var colorScale = d3.scaleSequential(d3.interpolateRdBu)
    .domain([38, 14]);
bandsTemp.features.forEach(function(d, i) {
    context.globalAlpha = 0.8;
    context.fillStyle = colorScale(intervalsTemp[i]);
  • Call the function isobands of the raster-marching-squares library
  • The color scale is taken from the d3 library setting a scaleSequential with the minimum and maximum values we want to show


Using an SVG can be useful if we want the user to know the band value by selecting it, for instance.

The code is similar to the one at the Canvas version. You can find the whole code here.

The most important part is:

bandsTemp.features.forEach(function(d, i) {
  svg.insert("path", ".streamline")
      .attr("d", path)
      .style("fill", colorScale(intervalsTemp[i]))
      .style("stroke", "None");