Skip to content

Instantly share code, notes, and snippets.

@rveciana
Last active September 13, 2019 10:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rveciana/3753394b3b6fd22df2c867bb02b320b4 to your computer and use it in GitHub Desktop.
Save rveciana/3753394b3b6fd22df2c867bb02b320b4 to your computer and use it in GitHub Desktop.
Change shaded relief colors dynamically
licence: mit
var d3 = d3|| {};
d3.ColorScaleChooser = function(){
var squareWidth = 80, squareHeight = 30;
var scaleValues = [];
var parent = null;
var dispatcher = d3.dispatch("change");
var title = null;
var addText = "Add";
var yOffset = 0;
function ColorScaleChooser(g){
parent = g;
if(title){
g.append("text")
.attr("x", 5)
.attr("y", 15)
.style("fill", "#666")
.style("font-size", (0.6*squareHeight)+"px")
.style("font-family", "Verdana")
.text(title);
yOffset = 0.6*squareHeight;
}
var addGroup = g.append("g")
.attr("transform","translate(10, "+(10+yOffset)+")")
.on("click", function(){
var newValue = {value: 0, color: "#ffffff"};
scaleValues.push(newValue);
draw();
form(newValue);
});
addGroup.append("rect")
.attr("width", squareWidth)
.attr("height", squareHeight)
.attr("x", 0)
.attr("y", 0)
.style("fill","#ddd")
.style("stroke", "#666");
addGroup.append("path")
.attr("d", "m -4.5,-20.5 0,16 -16,0 0,7 16,0 0,16 7,0 0,-16 16,0 0,-7 -16,0 0,-16 -7,0 z")
.attr("transform","translate("+squareWidth/2+","+squareHeight/2+") scale("+(0.6*squareHeight/40)+")")
.style("stroke", "#666")
.style("fill", "#ffffff");
addGroup.append("text")
.attr("x", squareWidth + squareWidth/8)
.attr("y", 30*squareHeight/40)
.style("fill", "#666")
.style("font-size", (0.425*squareHeight)+"px")
.style("font-family", "Verdana")
.text(addText);
draw();
}
ColorScaleChooser.squareWidth = function(_){
squareWidth = _;
return ColorScaleChooser;
};
ColorScaleChooser.squareHeight = function(_){
squareHeight = _;
return ColorScaleChooser;
};
ColorScaleChooser.scaleValues = function(_){
scaleValues = _;
return ColorScaleChooser;
};
ColorScaleChooser.title = function(_){
title = _;
return ColorScaleChooser;
};
ColorScaleChooser.addText = function(_){
addText = _;
return ColorScaleChooser;
};
ColorScaleChooser.on = function(){
var value = dispatcher.on.apply(dispatcher, arguments);
return value === dispatcher ? ColorScaleChooser : value;
};
function draw(){
var colorSelection = parent.selectAll(".step")
.data(scaleValues.sort(function(a, b){
return a.value-b.value;
}), function(d) { return(d.value+d.color); });
var colorSelectionEnter = colorSelection
.enter()
.append("g")
.attr("class","step")
.attr("transform", function(d, i){return"translate(10, "+((i+1)*squareHeight*1.1 + 10 + yOffset)+")";})
.on("mouseover", function(){
d3.select(this)
.selectAll(".close")
.style("visibility", "visible");
})
.on("mouseout", function(){
d3.select(this)
.selectAll(".close")
.style("visibility", "hidden");
});
colorSelectionEnter.append("rect")
.attr("width", squareWidth)
.attr("height", squareHeight)
.attr("x", 0)
.attr("y", 0)
.style("fill",function(d){ return d.color;})
.style("stroke", "#000")
.on("click", function(d){ form(d);});
colorSelectionEnter.append("text")
.attr("x", squareWidth + squareWidth/8)
.attr("y", 30*squareHeight/40)
.style("fill", "#333")
.style("font-size", (0.425*squareHeight)+"px")
.style("font-family", "Verdana")
.text(function(d){return d.value;});
colorSelectionEnter.append("path")
.attr("class", "close")
.attr("d", "m 20.5,1.86 a 20,20 0 0 0 -20,20 20,20 0 0 0 20,20 20,20 0 0 0 20,-20 20,20 0 0 0 -20,-20 z m -9.88,9 4.24,0 5.8,7.79 5.8,-7.79 4.23,0 -7.9,10.64 8.32,11.23 -4.23,0 -6.36,-8.59 -6.36,8.59 -4.23,0 8.49,-11.4 -7.77,-10.42 z")
.style("fill", "#f00")
.style("stroke", "#000")
.style("visibility", "hidden")
.attr("transform", "translate(3,3) scale(0.5)")
.on("click", function(d){
scaleValues = scaleValues.filter(function ( obj ) {
return obj.value !== d.value;
});
draw();
});
colorSelection.exit()
.transition()
.duration(1000)
.style("opacity", 0)
.remove();
colorSelection
.transition()
.delay(1000)
.duration(1000)
.attr("transform", function(d, i){return"translate(10, "+((i+1)*squareHeight*1.1 + 10 + yOffset)+")";});
dispatcher.call("change", {},
scaleValues,
scaleValues.reduce(function(a, b){return a.value < b.value ? a : b ;}).value,
scaleValues.reduce(function(a, b){return a.value > b.value ? a : b ;}).value);
}
function form(obj){
d3.selectAll(".colorScaleForm")
.remove();
var formDiv = d3.select("body")
.append("div")
.attr("class", "colorScaleForm")
.style("position", "absolute")
.style("left", (20+d3.event.pageX)+"px")
.style("top", d3.event.pageY+"px")
.style("background-color","rgba(128, 128, 128, 0.55)")
.style("border-radius","5px")
.style("padding","5px");
formDiv.append("label")
.text("Value");
formDiv.append("input")
.attr("class", "valueField")
.attr("type", "number")
.attr("step", "any")
.attr("size", 10)
.attr("value", obj.value);
formDiv.append("label")
.text("Color");
formDiv.append("input")
.attr("class", "colorField")
.attr("type", "color")
.attr("value", obj.color);
formDiv.append("button")
.text("Set")
.on("click", function(){
scaleValues[scaleValues.indexOf(obj)] = {value: formDiv.select(".valueField").node().value,
color: formDiv.select(".colorField").node().value};
draw();
formDiv.transition()
.duration(1000)
.style("opacity", 0)
.remove();
});
}
return ColorScaleChooser;
};
d3.ColorScaleChooser.getA = function(){
};
!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){"use strict";function d(){}d.prototype={isAsync:function(){return"undefined"==typeof this.decodeBlock}},b.exports=d},{}],2:[function(a,b,c){"use strict";function d(){}var e=a("../abstractdecoder.js");d.prototype=Object.create(e.prototype),d.prototype.constructor=d,d.prototype.decodeBlockAsync=function(a,b){throw new Error("DeflateDecoder is not yet implemented.")},b.exports=d},{"../abstractdecoder.js":1}],3:[function(a,b,c){"use strict";function d(){}var e=a("../abstractdecoder.js");d.prototype=Object.create(e.prototype),d.prototype.constructor=d,d.prototype.decodeBlock=function(a){throw new Error("LZWDecoder is not yet implemented")},b.exports=d},{"../abstractdecoder.js":1}],4:[function(a,b,c){"use strict";function d(){}var e=a("../abstractdecoder.js");d.prototype=Object.create(e.prototype),d.prototype.constructor=d,d.prototype.decodeBlock=function(a){var b,c,d=new DataView(a),e=[];for(b=0;b<a.byteLength;++b){var f=d.getInt8(b);if(0>f){var g=d.getUint8(b+1);for(f=-f,c=0;f>=c;++c)e.push(g);b+=1}else{for(c=0;f>=c;++c)e.push(d.getUint8(b+c+1));b+=f+1}}return new Uint8Array(e).buffer},b.exports=d},{"../abstractdecoder.js":1}],5:[function(a,b,c){"use strict";function d(){}var e=a("../abstractdecoder.js");d.prototype=Object.create(e.prototype),d.prototype.constructor=d,d.prototype.decodeBlock=function(a){return a},b.exports=d},{"../abstractdecoder.js":1}],6:[function(a,b,c){"use strict";function d(a,b){if(!(a instanceof b))throw new TypeError("Cannot call a class as a function")}var e=function(){function a(a,b){for(var c=0;c<b.length;c++){var d=b[c];d.enumerable=d.enumerable||!1,d.configurable=!0,"value"in d&&(d.writable=!0),Object.defineProperty(a,d.key,d)}}return function(b,c,d){return c&&a(b.prototype,c),d&&a(b,d),b}}(),f=function(){function a(b){d(this,a),this._dataView=new DataView(b)}return e(a,[{key:"getUint64",value:function(a,b){var c=this.getUint32(a,b),d=this.getUint32(a+4,b);return b?c<<32|d:d<<32|c}},{key:"getInt64",value:function(a,b){var c,d;return b?(c=this.getInt32(a,b),d=this.getUint32(a+4,b),c<<32|d):(c=this.getUint32(a,b),d=this.getInt32(a+4,b),d<<32|c)}},{key:"getUint8",value:function(a,b){return this._dataView.getUint8(a,b)}},{key:"getInt8",value:function(a,b){return this._dataView.getInt8(a,b)}},{key:"getUint16",value:function(a,b){return this._dataView.getUint16(a,b)}},{key:"getInt16",value:function(a,b){return this._dataView.getInt16(a,b)}},{key:"getUint32",value:function(a,b){return this._dataView.getUint32(a,b)}},{key:"getInt32",value:function(a,b){return this._dataView.getInt32(a,b)}},{key:"getFloat32",value:function(a,b){return this._dataView.getFloat32(a,b)}},{key:"getFloat64",value:function(a,b){return this._dataView.getFloat64(a,b)}},{key:"buffer",get:function(){return this._dataView.buffer}}]),a}();b.exports=f},{}],7:[function(a,b,c){"use strict";function d(a,b){this.dataView=new g(a),b=b||{},this.cache=b.cache||!1;var c=this.dataView.getUint16(0,0);if(18761===c)this.littleEndian=!0;else{if(19789!==c)throw new TypeError("Invalid byte order value.");this.littleEndian=!1}var d=this.dataView.getUint16(2,this.littleEndian);if(42===this.dataView.getUint16(2,this.littleEndian))this.bigTiff=!1;else{if(43!==d)throw new TypeError("Invalid magic number.");this.bigTiff=!0;var e=this.dataView.getUint16(4,this.littleEndian);if(8!==e)throw new Error("Unsupported offset byte-size.")}this.fileDirectories=this.parseFileDirectories(this.getOffset(this.bigTiff?8:4))}var e=a("./globals.js"),f=a("./geotiffimage.js"),g=a("./dataview64.js"),h=e.fieldTypes,i=e.fieldTagNames,j=e.arrayFields,k=e.geoKeyNames;d.prototype={getOffset:function(a){return this.bigTiff?this.dataView.getUint64(a,this.littleEndian):this.dataView.getUint32(a,this.littleEndian)},getFieldTypeLength:function(a){switch(a){case h.BYTE:case h.ASCII:case h.SBYTE:case h.UNDEFINED:return 1;case h.SHORT:case h.SSHORT:return 2;case h.LONG:case h.SLONG:case h.FLOAT:return 4;case h.RATIONAL:case h.SRATIONAL:case h.DOUBLE:case h.LONG8:case h.SLONG8:case h.IFD8:return 8;default:throw new RangeError("Invalid field type: "+a)}},getValues:function(a,b,c){var d,e=null,f=null,g=this.getFieldTypeLength(a);switch(a){case h.BYTE:case h.ASCII:case h.UNDEFINED:e=new Uint8Array(b),f=this.dataView.getUint8;break;case h.SBYTE:e=new Int8Array(b),f=this.dataView.getInt8;break;case h.SHORT:e=new Uint16Array(b),f=this.dataView.getUint16;break;case h.SSHORT:e=new Int16Array(b),f=this.dataView.getInt16;break;case h.LONG:e=new Uint32Array(b),f=this.dataView.getUint32;break;case h.SLONG:e=new Int32Array(b),f=this.dataView.getInt32;break;case h.LONG8:case h.IFD8:e=new Array(b),f=this.dataView.getUint64;break;case h.SLONG8:e=new Array(b),f=this.dataView.getInt64;break;case h.RATIONAL:e=new Uint32Array(2*b),f=this.dataView.getUint32;break;case h.SRATIONAL:e=new Int32Array(2*b),f=this.dataView.getInt32;break;case h.FLOAT:e=new Float32Array(b),f=this.dataView.getFloat32;break;case h.DOUBLE:e=new Float64Array(b),f=this.dataView.getFloat64;break;default:throw new RangeError("Invalid field type: "+a)}if(a!==h.RATIONAL&&a!==h.SRATIONAL)for(d=0;b>d;++d)e[d]=f.call(this.dataView,c+d*g,this.littleEndian);else for(d=0;2*b>d;d+=2)e[d]=f.call(this.dataView,c+d*g,this.littleEndian),e[d+1]=f.call(this.dataView,c+(d+1)*g,this.littleEndian);return a===h.ASCII?String.fromCharCode.apply(null,e):e},getFieldValues:function(a,b,c,d){var e,f=this.getFieldTypeLength(b);if(f*c<=(this.bigTiff?8:4))e=this.getValues(b,c,d);else{var g=this.getOffset(d);e=this.getValues(b,c,g)}return 1===c&&-1===j.indexOf(a)&&b!==h.RATIONAL&&b!==h.SRATIONAL?e[0]:e},parseGeoKeyDirectory:function(a){var b=a.GeoKeyDirectory;if(!b)return null;for(var c={},d=4;d<4*b[3];d+=4){var e=k[b[d]],f=b[d+1]?i[b[d+1]]:null,g=b[d+2],h=b[d+3],j=null;if(f){if(j=a[f],"undefined"==typeof j||null===j)throw new Error("Could not get value of geoKey '"+e+"'.");"string"==typeof j?j=j.substring(h,h+g-1):j.subarray&&(j=j.subarray(h,h+g-1))}else j=h;c[e]=j}return c},parseFileDirectories:function(a){for(var b=a,c=[];0!==b;){for(var d=this.bigTiff?this.dataView.getUint64(b,this.littleEndian):this.dataView.getUint16(b,this.littleEndian),e={},f=a+(this.bigTiff?8:2),g=0;d>g;f+=this.bigTiff?20:12,++g){var h=this.dataView.getUint16(f,this.littleEndian),j=this.dataView.getUint16(f+2,this.littleEndian),k=this.bigTiff?this.dataView.getUint64(f+4,this.littleEndian):this.dataView.getUint32(f+4,this.littleEndian);e[i[h]]=this.getFieldValues(h,j,k,f+(this.bigTiff?12:8))}c.push([e,this.parseGeoKeyDirectory(e)]),b=this.getOffset(f)}return c},getImage:function(a){a=a||0;var b=this.fileDirectories[a];if(!b)throw new RangeError("Invalid image index");return new f(b[0],b[1],this.dataView,this.littleEndian,this.cache)},getImageCount:function(){return this.fileDirectories.length}},b.exports=d},{"./dataview64.js":6,"./geotiffimage.js":8,"./globals.js":9}],8:[function(a,b,c){"use strict";function d(a,b,c,d,e){this.fileDirectory=a,this.geoKeys=b,this.dataView=c,this.littleEndian=d,this.tiles=e?{}:null,this.isTiled=a.StripOffsets?!1:!0;var j=a.PlanarConfiguration;if(this.planarConfiguration="undefined"==typeof j?1:j,1!==this.planarConfiguration&&2!==this.planarConfiguration)throw new Error("Invalid planar configuration.");switch(this.fileDirectory.Compression){case void 0:case 1:this.decoder=new f;break;case 5:this.decoder=new g;break;case 6:throw new Error("JPEG compression not supported.");case 8:this.decoder=new h;break;case 32773:this.decoder=new i;break;default:throw new Error("Unknown compresseion method identifier: "+this.fileDirectory.Compression)}}var e=a("./globals.js"),f=a("./compression/raw.js"),g=a("./compression/lzw.js"),h=a("./compression/deflate.js"),i=a("./compression/packbits.js"),j=function(a,b,c){for(var d=0,e=b;c>e;++e)d+=a[e];return d},k=function(a,b,c){switch(a){case 1:switch(b){case 8:return new Uint8Array(c);case 16:return new Uint16Array(c);case 32:return new Uint32Array(c)}break;case 2:switch(b){case 8:return new Int8Array(c);case 16:return new Int16Array(c);case 32:return new Int32Array(c)}break;case 3:switch(b){case 32:return new Float32Array(c);case 64:return new Float64Array(c)}}throw Error("Unsupported data format/bitsPerSample")};d.prototype={getFileDirectory:function(){return this.fileDirectory},getGeoKeys:function(){return this.geoKeys},getWidth:function(){return this.fileDirectory.ImageWidth},getHeight:function(){return this.fileDirectory.ImageLength},getSamplesPerPixel:function(){return this.fileDirectory.SamplesPerPixel},getTileWidth:function(){return this.isTiled?this.fileDirectory.TileWidth:this.getWidth()},getTileHeight:function(){return this.isTiled?this.fileDirectory.TileLength:this.fileDirectory.RowsPerStrip},getBytesPerPixel:function(){for(var a=0,b=0;b<this.fileDirectory.BitsPerSample.length;++b){var c=this.fileDirectory.BitsPerSample[b];if(c%8!==0)throw new Error("Sample bit-width of "+c+" is not supported.");if(c!==this.fileDirectory.BitsPerSample[0])throw new Error("Differing size of samples in a pixel are not supported.");a+=c}return a/8},getSampleByteSize:function(a){if(a>=this.fileDirectory.BitsPerSample.length)throw new RangeError("Sample index "+a+" is out of range.");var b=this.fileDirectory.BitsPerSample[a];if(b%8!==0)throw new Error("Sample bit-width of "+b+" is not supported.");return b/8},getReaderForSample:function(a){var b=this.fileDirectory.SampleFormat?this.fileDirectory.SampleFormat[a]:1,c=this.fileDirectory.BitsPerSample[a];switch(b){case 1:switch(c){case 8:return DataView.prototype.getUint8;case 16:return DataView.prototype.getUint16;case 32:return DataView.prototype.getUint32}break;case 2:switch(c){case 8:return DataView.prototype.getInt8;case 16:return DataView.prototype.getInt16;case 32:return DataView.prototype.getInt32}break;case 3:switch(c){case 32:return DataView.prototype.getFloat32;case 64:return DataView.prototype.getFloat64}}},getArrayForSample:function(a,b){var c=this.fileDirectory.SampleFormat?this.fileDirectory.SampleFormat[a]:1,d=this.fileDirectory.BitsPerSample[a];return k(c,d,b)},getDecoder:function(){return this.decoder},getTileOrStrip:function(a,b,c,d){var e,f=Math.ceil(this.getWidth()/this.getTileWidth()),g=Math.ceil(this.getHeight()/this.getTileHeight()),h=this.tiles;if(1===this.planarConfiguration?e=b*f+a:2===this.planarConfiguration&&(e=c*f*g+b*f+a),null!==h&&e in h)return d?d(null,{x:a,y:b,sample:c,data:h[e]}):h[e];var i,j;this.isTiled?(i=this.fileDirectory.TileOffsets[e],j=this.fileDirectory.TileByteCounts[e]):(i=this.fileDirectory.StripOffsets[e],j=this.fileDirectory.StripByteCounts[e]);var k=this.dataView.buffer.slice(i,i+j);if(d)return this.getDecoder().decodeBlockAsync(k,function(f,g){f||null===h||(h[e]=g),d(f,{x:a,y:b,sample:c,data:g})});var l=this.getDecoder().decodeBlock(k);return null!==h&&(h[e]=l),l},_readRasterAsync:function(a,b,c,d,e,f){function g(e,f){if(e)x=e;else for(var g=new DataView(f.data),j=f.y*k,l=f.x*i,m=(f.y+1)*k,n=(f.x+1)*i,o=(f.sample,Math.max(0,a[1]-j));o<Math.min(k,k-(m-a[3]));++o)for(var t=Math.max(0,a[0]-l);t<Math.min(i,i-(n-a[2]));++t){var u,y=(o*i+t)*q,z=s[C].call(g,y+r[C],w);d?(u=(o+j-a[1])*p*b.length+(t+l-a[0])*b.length+C,c[u]=z):(u=(o+j-a[1])*p+t+l-a[0],c[C][u]=z)}v-=1,h()}function h(){u&&0===v&&(x?f(x):e(c))}for(var i=this.getTileWidth(),k=this.getTileHeight(),l=Math.floor(a[0]/i),m=Math.ceil(a[2]/i),n=Math.floor(a[1]/k),o=Math.ceil(a[3]/k),p=(Math.ceil(this.getWidth()/i),a[2]-a[0]),q=(a[3]-a[1],this.getBytesPerPixel()),r=(this.getWidth(),[]),s=[],t=0;t<b.length;++t)1===this.planarConfiguration?r.push(j(this.fileDirectory.BitsPerSample,0,b[t])/8):r.push(0),s.push(this.getReaderForSample(b[t]));for(var u=!1,v=0,w=this.littleEndian,x=null,y=n;o>=y;++y)for(var z=l;m>=z;++z)for(var A=0;A<b.length;++A){var B=b[A];2===this.planarConfiguration&&(q=this.getSampleByteSize(B));var C=A;v+=1,this.getTileOrStrip(z,y,B,g)}u=!0,h()},_readRaster:function(a,b,c,d,e,f){try{for(var g=this.getTileWidth(),h=this.getTileHeight(),i=Math.floor(a[0]/g),k=Math.ceil(a[2]/g),l=Math.floor(a[1]/h),m=Math.ceil(a[3]/h),n=(Math.ceil(this.getWidth()/g),a[2]-a[0]),o=(a[3]-a[1],this.getBytesPerPixel()),p=(this.getWidth(),[]),q=[],r=0;r<b.length;++r)1===this.planarConfiguration?p.push(j(this.fileDirectory.BitsPerSample,0,b[r])/8):p.push(0),q.push(this.getReaderForSample(b[r]));for(var s=l;m>s;++s)for(var t=i;k>t;++t)for(var u=s*h,v=t*g,w=(s+1)*h,x=(t+1)*g,y=0;y<b.length;++y){var z=b[y];2===this.planarConfiguration&&(o=this.getSampleByteSize(z));for(var A=new DataView(this.getTileOrStrip(t,s,z)),B=Math.max(0,a[1]-u);B<Math.min(h,h-(w-a[3]));++B)for(var C=Math.max(0,a[0]-v);C<Math.min(g,g-(x-a[2]));++C){var D,E=(B*g+C)*o,F=q[y].call(A,E+p[y],this.littleEndian);d?(D=(B+u-a[1])*n*b.length+(C+v-a[0])*b.length+y,c[D]=F):(D=(B+u-a[1])*n+C+v-a[0],c[y][D]=F)}}return e(c),c}catch(G){return f(G)}},readRasters:function(){var a,b,c;switch(arguments.length){case 0:break;case 1:"function"==typeof arguments[0]?b=arguments[0]:a=arguments[0];break;case 2:"function"==typeof arguments[0]?(b=arguments[0],c=arguments[1]):(a=arguments[0],b=arguments[1]);break;case 3:a=arguments[0],b=arguments[1],c=arguments[2];break;default:throw new Error("Invalid number of arguments passed.")}a=a||{},c=c||function(a){console.error(a)};var d=a.window||[0,0,this.getWidth(),this.getHeight()],e=a.samples,f=a.interleave;if(d[0]<0||d[1]<0||d[2]>this.getWidth()||d[3]>this.getHeight())throw new Error("Select window is out of image bounds.");if(d[0]>d[2]||d[1]>d[3])throw new Error("Invalid subsets");var g,h=d[2]-d[0],i=d[3]-d[1],j=h*i;if(e){for(g=0;g<e.length;++g)if(e[g]>=this.fileDirectory.SamplesPerPixel)throw new RangeError("Invalid sample index '"+e[g]+"'.")}else for(e=[],g=0;g<this.fileDirectory.SamplesPerPixel;++g)e.push(g);var l;if(f){var m=this.fileDirectory.SampleFormat?Math.max.apply(null,this.fileDirectory.SampleFormat):1,n=Math.max.apply(null,this.fileDirectory.BitsPerSample);l=k(m,n,j*e.length)}else for(l=[],g=0;g<e.length;++g)l.push(this.getArrayForSample(e[g],j));var o=this.getDecoder();if(o.isAsync()){if(!b)throw new Error("No callback specified for asynchronous raster reading.");return this._readRasterAsync(d,e,l,f,b,c)}return b=b||function(){},this._readRaster(d,e,l,f,b,c)},getTiePoints:function(){if(!this.fileDirectory.ModelTiepoint)return[];for(var a=[],b=0;b<this.fileDirectory.ModelTiepoint.length;b+=6)a.push({i:this.fileDirectory.ModelTiepoint[b],j:this.fileDirectory.ModelTiepoint[b+1],k:this.fileDirectory.ModelTiepoint[b+2],x:this.fileDirectory.ModelTiepoint[b+3],y:this.fileDirectory.ModelTiepoint[b+4],z:this.fileDirectory.ModelTiepoint[b+5]});return a},getGDALMetadata:function(){var a={};if(!this.fileDirectory.GDAL_METADATA)return null;for(var b=this.fileDirectory.GDAL_METADATA,c=e.parseXml(b.substring(0,b.length-1)),d=c.evaluate("GDALMetadata/Item",c,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null),f=0;f<d.snapshotLength;++f){var g=d.snapshotItem(f);a[g.getAttribute("name")]=g.textContent}return a}},b.exports=d},{"./compression/deflate.js":2,"./compression/lzw.js":3,"./compression/packbits.js":4,"./compression/raw.js":5,"./globals.js":9}],9:[function(a,b,c){"use strict";var d,e={315:"Artist",258:"BitsPerSample",265:"CellLength",264:"CellWidth",320:"ColorMap",259:"Compression",33432:"Copyright",306:"DateTime",338:"ExtraSamples",266:"FillOrder",289:"FreeByteCounts",288:"FreeOffsets",291:"GrayResponseCurve",290:"GrayResponseUnit",316:"HostComputer",270:"ImageDescription",257:"ImageLength",256:"ImageWidth",271:"Make",281:"MaxSampleValue",280:"MinSampleValue",272:"Model",254:"NewSubfileType",274:"Orientation",262:"PhotometricInterpretation",284:"PlanarConfiguration",296:"ResolutionUnit",278:"RowsPerStrip",277:"SamplesPerPixel",305:"Software",279:"StripByteCounts",273:"StripOffsets",255:"SubfileType",263:"Threshholding",282:"XResolution",283:"YResolution",326:"BadFaxLines",327:"CleanFaxData",343:"ClipPath",328:"ConsecutiveBadFaxLines",433:"Decode",434:"DefaultImageColor",269:"DocumentName",336:"DotRange",321:"HalftoneHints",346:"Indexed",347:"JPEGTables",285:"PageName",297:"PageNumber",317:"Predictor",319:"PrimaryChromaticities",532:"ReferenceBlackWhite",339:"SampleFormat",340:"SMinSampleValue",341:"SMaxSampleValue",559:"StripRowCounts",330:"SubIFDs",292:"T4Options",293:"T6Options",325:"TileByteCounts",323:"TileLength",324:"TileOffsets",322:"TileWidth",301:"TransferFunction",318:"WhitePoint",344:"XClipPathUnits",286:"XPosition",529:"YCbCrCoefficients",531:"YCbCrPositioning",530:"YCbCrSubSampling",345:"YClipPathUnits",287:"YPosition",37378:"ApertureValue",40961:"ColorSpace",36868:"DateTimeDigitized",36867:"DateTimeOriginal",34665:"Exif IFD",36864:"ExifVersion",33434:"ExposureTime",41728:"FileSource",37385:"Flash",40960:"FlashpixVersion",33437:"FNumber",42016:"ImageUniqueID",37384:"LightSource",37500:"MakerNote",37377:"ShutterSpeedValue",37510:"UserComment",33723:"IPTC",34675:"ICC Profile",700:"XMP",42112:"GDAL_METADATA",42113:"GDAL_NODATA",34377:"Photoshop",33550:"ModelPixelScale",33922:"ModelTiepoint",34264:"ModelTransformation",34735:"GeoKeyDirectory",34736:"GeoDoubleParams",34737:"GeoAsciiParams"},f={};for(d in e)f[e[d]]=parseInt(d);var g=[f.BitsPerSample,f.ExtraSamples,f.SampleFormat,f.StripByteCounts,f.StripOffsets,f.StripRowCounts,f.TileByteCounts,f.TileOffsets],h={1:"BYTE",2:"ASCII",3:"SHORT",4:"LONG",5:"RATIONAL",6:"SBYTE",7:"UNDEFINED",8:"SSHORT",9:"SLONG",10:"SRATIONAL",11:"FLOAT",12:"DOUBLE",16:"LONG8",17:"SLONG8",18:"IFD8"},i={};for(d in h)i[h[d]]=parseInt(d);var j={1024:"GTModelTypeGeoKey",1025:"GTRasterTypeGeoKey",1026:"GTCitationGeoKey",2048:"GeographicTypeGeoKey",2049:"GeogCitationGeoKey",2050:"GeogGeodeticDatumGeoKey",2051:"GeogPrimeMeridianGeoKey",2052:"GeogLinearUnitsGeoKey",2053:"GeogLinearUnitSizeGeoKey",2054:"GeogAngularUnitsGeoKey",2055:"GeogAngularUnitSizeGeoKey",2056:"GeogEllipsoidGeoKey",2057:"GeogSemiMajorAxisGeoKey",2058:"GeogSemiMinorAxisGeoKey",2059:"GeogInvFlatteningGeoKey",2060:"GeogAzimuthUnitsGeoKey",2061:"GeogPrimeMeridianLongGeoKey",2062:"GeogTOWGS84GeoKey",3072:"ProjectedCSTypeGeoKey",3073:"PCSCitationGeoKey",3074:"ProjectionGeoKey",3075:"ProjCoordTransGeoKey",3076:"ProjLinearUnitsGeoKey",3077:"ProjLinearUnitSizeGeoKey",3078:"ProjStdParallel1GeoKey",3079:"ProjStdParallel2GeoKey",3080:"ProjNatOriginLongGeoKey",3081:"ProjNatOriginLatGeoKey",3082:"ProjFalseEastingGeoKey",3083:"ProjFalseNorthingGeoKey",3084:"ProjFalseOriginLongGeoKey",3085:"ProjFalseOriginLatGeoKey",3086:"ProjFalseOriginEastingGeoKey",3087:"ProjFalseOriginNorthingGeoKey",3088:"ProjCenterLongGeoKey",3089:"ProjCenterLatGeoKey",3090:"ProjCenterEastingGeoKey",3091:"ProjCenterNorthingGeoKey",3092:"ProjScaleAtNatOriginGeoKey",3093:"ProjScaleAtCenterGeoKey",3094:"ProjAzimuthAngleGeoKey",3095:"ProjStraightVertPoleLongGeoKey",3096:"ProjRectifiedGridAngleGeoKey",4096:"VerticalCSTypeGeoKey",4097:"VerticalCitationGeoKey",4098:"VerticalDatumGeoKey",4099:"VerticalUnitsGeoKey"},k={};for(d in j)k[j[d]]=parseInt(d);var l;"undefined"==typeof window?l=function(b){var c=a("xmldom").DOMParser;return(new c).parseFromString(b,"text/xml")}:"undefined"!=typeof window.DOMParser?l=function(a){return(new window.DOMParser).parseFromString(a,"text/xml")}:"undefined"!=typeof window.ActiveXObject&&new window.ActiveXObject("Microsoft.XMLDOM")&&(l=function(a){var b=new window.ActiveXObject("Microsoft.XMLDOM");return b.async="false",b.loadXML(a),b}),b.exports={fieldTags:f,fieldTagNames:e,arrayFields:g,fieldTypes:i,fieldTypeNames:h,geoKeys:k,geoKeyNames:j,parseXml:l}},{xmldom:"xmldom"}],10:[function(a,b,c){"use strict";var d=a("./geotiff.js"),e=function(a,b){var c,e,f,g;if("string"==typeof a||a instanceof String)for(c=new ArrayBuffer(2*a.length),g=new Uint16Array(c),e=0,f=a.length;f>e;++e)g[e]=a.charCodeAt(e);else{if(!(a instanceof ArrayBuffer))throw new Error("Invalid input data given.");c=a}return new d(c,b)};"undefined"!=typeof b&&"undefined"!=typeof b.exports&&(b.exports.parse=e),"undefined"!=typeof window&&(window.GeoTIFF={parse:e})},{"./geotiff.js":7}]},{},[10]);
<!DOCTYPE html>
<meta charset="utf-8">
<style>
</style>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="geotiff.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="color-scale.js"></script>
<script>
var width = 680,
height = 500;
var projection = d3.geoAzimuthalEqualArea()
.rotate([-8.2, -46.8])
.translate([width/2, height/2])
.scale(12000);
var canvas = d3.select("body").append("canvas")
.attr("width", width)
.attr("height", height);
var context = canvas.node().getContext("2d");
d3.request("swiss.tiff")
.responseType('arraybuffer')
.get(function(error, tiffData){
d3.json("swiss.json", function(error, topojsonData) {
var countries = topojson.feature(topojsonData, topojsonData.objects.country);
var path = d3.geoPath()
.projection(projection).context(context);
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 altData = new Array(image.getHeight());
for (var j = 0; j<image.getHeight(); j++){
altData[j] = new Array(image.getWidth());
for (var i = 0; i<image.getWidth(); i++){
altData[j][i] = rasters[0][i + j*image.getWidth()];
}
}
//Calculate shaded Relief. Outside the first loop, to be able to put it in a function
var azimuth = 315;
var angleAltitude = 45;
var azimuthrad = azimuth*Math.PI / 180;
var altituderad = angleAltitude*Math.PI / 180;
var shadedData = new Array(image.getHeight());
for (var j = 0; j<image.getHeight(); j++){
shadedData[j] = new Array(image.getWidth());
for (var i = 0; i<image.getWidth(); i++){
var gradX, gradY;
if(i==0) gradX = altData[j][i+1] - altData[j][i];
else if(i==image.getWidth()-1) gradX = altData[j][i] - altData[j][i-1];
else gradX = (altData[j][i+1] - altData[j][i])/2 + (altData[j][i] - altData[j][i-1])/2;
if(j==0) gradY = altData[j+1][i] - altData[j][i];
else if(j==image.getHeight()-1) gradY = altData[j][i] - altData[j-1][i];
else gradY = (altData[j+1][i] - altData[j][i])/2 + (altData[j][i] - altData[j-1][i])/2;
var slope = Math.PI/2 - Math.atan(Math.sqrt(gradX*gradX + gradY*gradY));
var aspect = Math.atan2(-gradY, gradX);
shadedData[j][i] = Math.sin(altituderad) * Math.sin(slope)
+ Math.cos(altituderad) * Math.cos(slope)
* Math.cos(azimuthrad - aspect);
}
}
var canvasShaded = d3.select("body").append("canvas")
.attr("width", width)
.attr("height", height)
.style("display","none");
var contextShaded = canvasShaded.node().getContext("2d");
var idShaded = contextShaded.createImageData(width,height);
var dataShaded = idShaded.data;
var posShaded = 0;
for(var j = 0; j<height; j++){
for(var i = 0; i<width; i++){
var pointCoords = projection.invert([i,j]);
var px = invGeoTransform[0] + pointCoords[0]* invGeoTransform[1];
var py = invGeoTransform[3] + pointCoords[1] * invGeoTransform[5];
var shadedValue;
if(Math.floor(px) >= 0 && Math.ceil(px) < image.getWidth() && Math.floor(py) >= 0 && Math.ceil(py) < image.getHeight()){
shadedValue = 255*(1+shadedData[Math.floor(py)][Math.floor(px)])/2;
} else {
shadedValue = 255;
}
dataShaded[posShaded] = shadedValue;
dataShaded[posShaded+1] = shadedValue;
dataShaded[posShaded+2] = shadedValue;
dataShaded[posShaded+3] = 255 - shadedValue;
posShaded=posShaded+4;
}
}
contextShaded.putImageData( idShaded, 0, 0);
var scaleValues = [{value: 200, color: "#c9d5a6"},
{value: 900, color: "#7fa67a"},
{value: 1600, color: "#976a2f"},
{value: 2300, color: "#79750a"},
{value: 3000, color: "#7ab5e3"},
{value: 3700, color: "#fefefe"},
{value: 4400, color: "#f605cf"}];
var scale = d3.ColorScaleChooser()
.squareWidth(50)
.squareHeight(30)
.scaleValues(scaleValues)
.title("Altitude (m)")
.on("change", function(d, min, max){
var scaleWidth = 256;
d3.select("#colorScaleCanvas").remove();
var canvasColorScale = d3.select("body").append("canvas")
.attr("width", scaleWidth)
.attr("height", 1)
.attr("id", "colorScaleCanvas")
.style("display","none");
var contextColorScale = canvasColorScale.node().getContext("2d");
var gradient = contextColorScale.createLinearGradient(0, 0, scaleWidth, 1);
for (var i = 0; i < d.length; ++i) {
var position = (d[i].value-min)/(max-min);
if(position >= 0 && position < scaleWidth){
gradient.addColorStop(position, d[i].color);
}
}
contextColorScale.fillStyle = gradient;
contextColorScale.fillRect(0, 0, scaleWidth, 1);
var csImageData = contextColorScale.getImageData(0, 0, scaleWidth, 1).data;
draw(csImageData, min, max);
});
var svg = d3.select("body").append("svg")
.attr("width", 150)
.attr("height", 500)
.style("position", "absolute")
.style("left", "10px")
.style("top", "10px");
svg.call(scale);
function draw(csImageData, min, max){
context.drawImage(canvasShaded.node(), 0, 0);
context.globalAlpha = 0.7;
context.fillStyle = '#ffffff';
context.fillRect(0,0,width,height);
context.fill();
context.globalAlpha = 1;
var scaleWidth = csImageData.length/4;
var canvasRaster = d3.select("body").append("canvas")
.attr("width", width)
.attr("height", height)
.style("display","none");
var contextRaster = canvasRaster.node().getContext("2d");
var id = contextRaster.createImageData(width,height);
var data = id.data;
var pos = 0;
for(var j = 0; j<height; j++){
for(var i = 0; i<width; i++){
var pointCoords = projection.invert([i,j]);
var px = invGeoTransform[0] + pointCoords[0]* invGeoTransform[1];
var py = invGeoTransform[3] + pointCoords[1] * invGeoTransform[5];
var value;
if(Math.floor(px) >= 0 && Math.ceil(px) < image.getWidth() && Math.floor(py) >= 0 && Math.ceil(py) < image.getHeight()){
var dist1 = (Math.ceil(px)-px)*(Math.ceil(py)-py);
var dist2 = (px-Math.floor(px))*(Math.ceil(py)-py);
var dist3 = (Math.ceil(px)-px)*(py-Math.floor(py));
var dist4 = (px-Math.floor(px))*(py-Math.floor(py));
if (dist1 != 0 || dist2!=0 || dist3!=0 || dist4!=0){
value = altData[Math.floor(py)][Math.floor(px)]*dist1+
altData[Math.floor(py)][Math.ceil(px)]*dist2 +
altData[Math.ceil(py)][Math.floor(px)]*dist3 +
altData[Math.ceil(py)][Math.ceil(px)]*dist4;
} else {
value = altData[Math.floor(py)][Math.floor(px)];
}
} else {
value = -999;
}
var c = Math.round((scaleWidth-1) * ((value - min)/(max-min)));
var alpha = 255;
if(c<0) c=0;
if(c>=scaleWidth) c=scaleWidth-1;
data[pos] = csImageData[c*4];;
data[pos+1] = csImageData[c*4+1];
data[pos+2] = csImageData[c*4+2];
data[pos+3] = alpha;
pos = pos + 4
}
}
contextRaster.putImageData( id, 0, 0);
context.save();
context.beginPath();
path(countries);
context.clip();
context.drawImage(canvasRaster.node(), 0, 0);
context.globalAlpha = 0.5;
context.drawImage(canvasShaded.node(), 0, 0);
context.restore();
context.beginPath();
context.strokeStyle = "#777";
path(countries);
context.stroke();
}
});
});
</script>
</body>
This file has been truncated, but you can view the full file.
View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment