http://lzugis.d152.ptzygj.com/
GDAL库学习笔记(1):无缝拼接Google卫星图
http://www.cnblogs.com/i-gps/archive/2012/07/27/2611434.html
/*
* heatmap.js 1.0 - JavaScript Heatmap Library
*
* Copyright (c) 2011, Patrick Wied (http://www.patrick-wied.at)
* Dual-licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and the Beerware (http://en.wikipedia.org/wiki/Beerware) license.
*/
(function(w){
// the heatmapFactory creates heatmap instances
var heatmapFactory = (function(){
// store object constructor
// a heatmap contains a store
// the store has to know about the heatmap in order to trigger heatmap updates when datapoints get added
var store = function store(hmap){
var _ = {
// data is a two dimensional array
// a datapoint gets saved as data[point-x-value][point-y-value]
// the value at [point-x-value][point-y-value] is the occurrence of the datapoint
data: [],
// tight coupling of the heatmap object
heatmap: hmap
};
// the max occurrence - the heatmaps radial gradient alpha transition is based on it
this.max = 1;
this.get = function(key){
return _[key];
};
this.set = function(key, value){
_[key] = value;
};
}
store.prototype = {
// function for adding datapoints to the store
// datapoints are usually defined by x and y but could also contain a third parameter which represents the occurrence
addDataPoint: function(x, y){
if(x < 0 || y < 0)
return;
var me = this,
heatmap = me.get("heatmap"),
data = me.get("data");
if(!data[x])
data[x] = [];
if(!data[x][y])
data[x][y] = 0;
// if count parameter is set increment by count otherwise by 1
data[x][y]+=(arguments.length<3)?1:arguments[2];
me.set("data", data);
// do we have a new maximum?
if(me.max < data[x][y]){
// max changed, we need to redraw all existing(lower) datapoints
heatmap.get("actx").clearRect(0,0,heatmap.get("width"),heatmap.get("height"));
me.setDataSet({ max: data[x][y], data: data }, true);
return;
}
heatmap.drawAlpha(x, y, data[x][y], true);
},
setDataSet: function(obj, internal){
var me = this,
heatmap = me.get("heatmap"),
data = [],
d = obj.data,
dlen = d.length;
// clear the heatmap before the data set gets drawn
heatmap.clear();
this.max = obj.max;
// if a legend is set, update it
heatmap.get("legend") && heatmap.get("legend").update(obj.max);
if(internal != null && internal){
for(var one in d){
// jump over undefined indexes
if(one === undefined)
continue;
for(var two in d[one]){
if(two === undefined)
continue;
// if both indexes are defined, push the values into the array
heatmap.drawAlpha(one, two, d[one][two], false);
}
}
}else{
while(dlen--){
var point = d[dlen];
heatmap.drawAlpha(point.x, point.y, point.count, false);
if(!data[point.x])
data[point.x] = [];
if(!data[point.x][point.y])
data[point.x][point.y] = 0;
data[point.x][point.y] = point.count;
}
}
heatmap.colorize();
this.set("data", d);
},
exportDataSet: function(){
var me = this,
data = me.get("data"),
exportData = [];
for(var one in data){
// jump over undefined indexes
if(one === undefined)
continue;
for(var two in data[one]){
if(two === undefined)
continue;
// if both indexes are defined, push the values into the array
exportData.push({x: parseInt(one, 10), y: parseInt(two, 10), count: data[one][two]});
}
}
return { max: me.max, data: exportData };
},
generateRandomDataSet: function(points){
var heatmap = this.get("heatmap"),
w = heatmap.get("width"),
h = heatmap.get("height");
var randomset = {},
max = Math.floor(Math.random()*1000+1);
randomset.max = max;
var data = [];
while(points--){
data.push({x: Math.floor(Math.random()*w+1), y: Math.floor(Math.random()*h+1), count: Math.floor(Math.random()*max+1)});
}
randomset.data = data;
this.setDataSet(randomset);
}
};
var legend = function legend(config){
this.config = config;
var _ = {
element: null,
labelsEl: null,
gradientCfg: null,
ctx: null
};
this.get = function(key){
return _[key];
};
this.set = function(key, value){
_[key] = value;
};
this.init();
};
legend.prototype = {
init: function(){
var me = this,
config = me.config,
title = config.title || "Legend",
position = config.position,
offset = config.offset || 10,
gconfig = config.gradient,
labelsEl = document.createElement("ul"),
labelsHtml = "",
grad, element, gradient, positionCss = "";
me.processGradientObject();
// Positioning
// top or bottom
if(position.indexOf('t') > -1){
positionCss += 'top:'+offset+'px;';
}else{
positionCss += 'bottom:'+offset+'px;';
}
// left or right
if(position.indexOf('l') > -1){
positionCss += 'left:'+offset+'px;';
}else{
positionCss += 'right:'+offset+'px;';
}
element = document.createElement("div");
element.style.cssText = "border-radius:5px;position:absolute;"+positionCss+"font-family:Helvetica; width:256px;z-index:10000000000; background:rgba(255,255,255,1);padding:10px;border:1px solid black;margin:0;";
element.innerHTML = "<h3 style='padding:0;margin:0;text-align:center;font-size:16px;'>"+title+"</h3>";
// create gradient in canvas
labelsEl.style.cssText = "position:relative;font-size:12px;display:block;list-style:none;list-style-type:none;margin:0;height:15px;";
// create gradient element
gradient = document.createElement("div");
gradient.style.cssText = ["position:relative;display:block;width:256px;height:15px;border-bottom:1px solid black; background-image:url(",me.createGradientImage(),");"].join("");
element.appendChild(labelsEl);
element.appendChild(gradient);
me.set("element", element);
me.set("labelsEl", labelsEl);
me.update(1);
},
processGradientObject: function(){
// create array and sort it
var me = this,
gradientConfig = this.config.gradient,
gradientArr = [];
for(var key in gradientConfig){
if(gradientConfig.hasOwnProperty(key)){
gradientArr.push({ stop: key, value: gradientConfig[key] });
}
}
gradientArr.sort(function(a, b){
return (a.stop - b.stop);
});
gradientArr.unshift({ stop: 0, value: 'rgba(0,0,0,0)' });
me.set("gradientArr", gradientArr);
},
createGradientImage: function(){
var me = this,
gradArr = me.get("gradientArr"),
length = gradArr.length,
canvas = document.createElement("canvas"),
ctx = canvas.getContext("2d"),
grad;
// the gradient in the legend including the ticks will be 256x15px
canvas.width = "256";
canvas.height = "15";
grad = ctx.createLinearGradient(0,5,256,10);
for(var i = 0; i < length; i++){
grad.addColorStop(1/(length-1) * i, gradArr[i].value);
}
ctx.fillStyle = grad;
ctx.fillRect(0,5,256,10);
ctx.strokeStyle = "black";
ctx.beginPath();
for(var i = 0; i < length; i++){
ctx.moveTo(((1/(length-1)*i*256) >> 0)+.5, 0);
ctx.lineTo(((1/(length-1)*i*256) >> 0)+.5, (i==0)?15:5);
}
ctx.moveTo(255.5, 0);
ctx.lineTo(255.5, 15);
ctx.moveTo(255.5, 4.5);
ctx.lineTo(0, 4.5);
ctx.stroke();
// we re-use the context for measuring the legends label widths
me.set("ctx", ctx);
return canvas.toDataURL();
},
getElement: function(){
return this.get("element");
},
update: function(max){
var me = this,
gradient = me.get("gradientArr"),
ctx = me.get("ctx"),
labels = me.get("labelsEl"),
labelText, labelsHtml = "", offset;
for(var i = 0; i < gradient.length; i++){
labelText = max*gradient[i].stop >> 0;
offset = (ctx.measureText(labelText).width/2) >> 0;
if(i == 0){
offset = 0;
}
if(i == gradient.length-1){
offset *= 2;
}
labelsHtml += '<li style="position:absolute;left:'+(((((1/(gradient.length-1)*i*256) || 0)) >> 0)-offset+.5)+'px">'+labelText+'</li>';
}
labels.innerHTML = labelsHtml;
}
};
// heatmap object constructor
var heatmap = function heatmap(config){
// private variables
var _ = {
radius : 40,
element : {},
canvas : {},
acanvas: {},
ctx : {},
actx : {},
legend: null,
visible : true,
width : 0,
height : 0,
max : false,
gradient : false,
opacity: 180,
premultiplyAlpha: false,
bounds: {
l: 1000,
r: 0,
t: 1000,
b: 0
},
debug: false
};
// heatmap store containing the datapoints and information about the maximum
// accessible via instance.store
this.store = new store(this);
this.get = function(key){
return _[key];
};
this.set = function(key, value){
_[key] = value;
};
// configure the heatmap when an instance gets created
this.configure(config);
// and initialize it
this.init();
};
// public functions
heatmap.prototype = {
configure: function(config){
var me = this,
rout, rin;
me.set("radius", config["radius"] || 40);
me.set("element", (config.element instanceof Object)?config.element:document.getElementById(config.element));
me.set("visible", (config.visible != null)?config.visible:true);
me.set("max", config.max || false);
me.set("gradient", config.gradient || { 0.45: "rgb(0,0,255)", 0.55: "rgb(0,255,255)", 0.65: "rgb(0,255,0)", 0.95: "yellow", 1.0: "rgb(255,0,0)"}); // default is the common blue to red gradient
me.set("opacity", parseInt(255/(100/config.opacity), 10) || 180);
me.set("width", config.width || 0);
me.set("height", config.height || 0);
me.set("debug", config.debug);
if(config.legend){
var legendCfg = config.legend;
legendCfg.gradient = me.get("gradient");
me.set("legend", new legend(legendCfg));
}
},
resize: function () {
var me = this,
element = me.get("element"),
canvas = me.get("canvas"),
acanvas = me.get("acanvas");
canvas.width = acanvas.width = me.get("width") || element.style.width.replace(/px/, "") || me.getWidth(element);
this.set("width", canvas.width);
canvas.height = acanvas.height = me.get("height") || element.style.height.replace(/px/, "") || me.getHeight(element);
this.set("height", canvas.height);
},
init: function(){
var me = this,
canvas = document.createElement("canvas"),
acanvas = document.createElement("canvas"),
ctx = canvas.getContext("2d"),
actx = acanvas.getContext("2d"),
element = me.get("element");
me.initColorPalette();
me.set("canvas", canvas);
me.set("ctx", ctx);
me.set("acanvas", acanvas);
me.set("actx", actx);
me.resize();
canvas.style.cssText = acanvas.style.cssText = "position:absolute;top:0;left:0;z-index:10000000;";
if(!me.get("visible"))
canvas.style.display = "none";
element.appendChild(canvas);
if(me.get("legend")){
element.appendChild(me.get("legend").getElement());
}
// debugging purposes only
if(me.get("debug"))
document.body.appendChild(acanvas);
actx.shadowOffsetX = 15000;
actx.shadowOffsetY = 15000;
actx.shadowBlur = 15;
},
initColorPalette: function(){
var me = this,
canvas = document.createElement("canvas"),
gradient = me.get("gradient"),
ctx, grad, testData;
canvas.width = "1";
canvas.height = "256";
ctx = canvas.getContext("2d");
grad = ctx.createLinearGradient(0,0,1,256);
// Test how the browser renders alpha by setting a partially transparent pixel
// and reading the result. A good browser will return a value reasonably close
// to what was set. Some browsers (e.g. on Android) will return a ridiculously wrong value.
testData = ctx.getImageData(0,0,1,1);
testData.data[0] = testData.data[3] = 64; // 25% red & alpha
testData.data[1] = testData.data[2] = 0; // 0% blue & green
ctx.putImageData(testData, 0, 0);
testData = ctx.getImageData(0,0,1,1);
me.set("premultiplyAlpha", (testData.data[0] < 60 || testData.data[0] > 70));
for(var x in gradient){
grad.addColorStop(x, gradient[x]);
}
ctx.fillStyle = grad;
ctx.fillRect(0,0,1,256);
me.set("gradient", ctx.getImageData(0,0,1,256).data);
},
getWidth: function(element){
var width = element.offsetWidth;
if(element.style.paddingLeft){
width+=element.style.paddingLeft;
}
if(element.style.paddingRight){
width+=element.style.paddingRight;
}
return width;
},
getHeight: function(element){
var height = element.offsetHeight;
if(element.style.paddingTop){
height+=element.style.paddingTop;
}
if(element.style.paddingBottom){
height+=element.style.paddingBottom;
}
return height;
},
colorize: function(x, y){
// get the private variables
var me = this,
width = me.get("width"),
radius = me.get("radius"),
height = me.get("height"),
actx = me.get("actx"),
ctx = me.get("ctx"),
x2 = radius * 3,
premultiplyAlpha = me.get("premultiplyAlpha"),
palette = me.get("gradient"),
opacity = me.get("opacity"),
bounds = me.get("bounds"),
left, top, bottom, right,
image, imageData, length, alpha, offset, finalAlpha;
if(x != null && y != null){
if(x+x2>width){
x=width-x2;
}
if(x<0){
x=0;
}
if(y<0){
y=0;
}
if(y+x2>height){
y=height-x2;
}
left = x;
top = y;
right = x + x2;
bottom = y + x2;
}else{
if(bounds['l'] < 0){
left = 0;
}else{
left = bounds['l'];
}
if(bounds['r'] > width){
right = width;
}else{
right = bounds['r'];
}
if(bounds['t'] < 0){
top = 0;
}else{
top = bounds['t'];
}
if(bounds['b'] > height){
bottom = height;
}else{
bottom = bounds['b'];
}
}
image = actx.getImageData(left, top, right-left, bottom-top);
imageData = image.data;
length = imageData.length;
// loop thru the area
for(var i=3; i < length; i+=4){
// [0] -> r, [1] -> g, [2] -> b, [3] -> alpha
alpha = imageData[i],
offset = alpha*4;
if(!offset)
continue;
// we ve started with i=3
// set the new r, g and b values
finalAlpha = (alpha < opacity)?alpha:opacity;
imageData[i-3]=palette[offset];
imageData[i-2]=palette[offset+1];
imageData[i-1]=palette[offset+2];
if (premultiplyAlpha) {
// To fix browsers that premultiply incorrectly, we'll pass in a value scaled
// appropriately so when the multiplication happens the correct value will result.
imageData[i-3] /= 255/finalAlpha;
imageData[i-2] /= 255/finalAlpha;
imageData[i-1] /= 255/finalAlpha;
}
// we want the heatmap to have a gradient from transparent to the colors
// as long as alpha is lower than the defined opacity (maximum), we'll use the alpha value
imageData[i] = finalAlpha;
}
// the rgb data manipulation didn't affect the ImageData object(defined on the top)
// after the manipulation process we have to set the manipulated data to the ImageData object
image.data = imageData;
ctx.putImageData(image, left, top);
},
drawAlpha: function(x, y, count, colorize){
// storing the variables because they will be often used
var me = this,
radius = me.get("radius"),
ctx = me.get("actx"),
max = me.get("max"),
bounds = me.get("bounds"),
xb = x - (1.5 * radius) >> 0, yb = y - (1.5 * radius) >> 0,
xc = x + (1.5 * radius) >> 0, yc = y + (1.5 * radius) >> 0;
ctx.shadowColor = ('rgba(0,0,0,'+((count)?(count/me.store.max):'0.1')+')');
ctx.shadowOffsetX = 15000;
ctx.shadowOffsetY = 15000;
ctx.shadowBlur = 15;
ctx.beginPath();
ctx.arc(x - 15000, y - 15000, radius, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
if(colorize){
// finally colorize the area
me.colorize(xb,yb);
}else{
// or update the boundaries for the area that then should be colorized
if(xb < bounds["l"]){
bounds["l"] = xb;
}
if(yb < bounds["t"]){
bounds["t"] = yb;
}
if(xc > bounds['r']){
bounds['r'] = xc;
}
if(yc > bounds['b']){
bounds['b'] = yc;
}
}
},
toggleDisplay: function(){
var me = this,
visible = me.get("visible"),
canvas = me.get("canvas");
if(!visible)
canvas.style.display = "block";
else
canvas.style.display = "none";
me.set("visible", !visible);
},
// dataURL export
getImageData: function(){
return this.get("canvas").toDataURL();
},
clear: function(){
var me = this,
w = me.get("width"),
h = me.get("height");
me.store.set("data",[]);
// @TODO: reset stores max to 1
//me.store.max = 1;
me.get("ctx").clearRect(0,0,w,h);
me.get("actx").clearRect(0,0,w,h);
},
cleanup: function(){
var me = this;
me.get("element").removeChild(me.get("canvas"));
}
};
return {
create: function(config){
return new heatmap(config);
},
util: {
mousePosition: function(ev){
// this doesn't work right
// rather use
/*
// this = element to observe
var x = ev.pageX - this.offsetLeft;
var y = ev.pageY - this.offsetTop;
*/
var x, y;
if (ev.layerX) { // Firefox
x = ev.layerX;
y = ev.layerY;
} else if (ev.offsetX) { // Opera
x = ev.offsetX;
y = ev.offsetY;
}
if(typeof(x)=='undefined')
return;
return [x,y];
}
}
};
})();
w.h337 = w.heatmapFactory = heatmapFactory;
})(window);
define("echarts/chart/heatmap",["require","./base","../layer/heatmap","../config","../util/ecData","zrender/tool/util","zrender/tool/color","zrender/shape/Image","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("../layer/heatmap"),a=e("../config"),o=(e("../util/ecData"),e("zrender/tool/util")),r=(e("zrender/tool/color"),e("zrender/shape/Image"));return a.heatmap={zlevel:0,z:2,clickable:!0},t.prototype={type:a.CHART_TYPE_HEATMAP,refresh:function(e){this.clear(),e&&(this.option=e,this.series=e.series),this._init()},_init:function(){var e=this.series;this.backupShapeList();for(var t=e.length,i=0;t>i;++i)if(e[i].type===a.CHART_TYPE_HEATMAP){e[i]=this.reformOption(e[i]);var o=new n(e[i]),s=o.getCanvas(e[i].data,this.zr.getWidth(),this.zr.getHeight()),l=new r({position:[0,0],scale:[1,1],hoverable:this.option.hoverable,style:{x:0,y:0,image:s,width:s.width,height:s.height}});this.shapeList.push(l)}this.addShapeList()}},o.inherits(t,i),e("../chart").define("heatmap",t),t}),define("echarts/layer/heatmap",["require"],function(){function e(e){if(this.option=e,e)for(var i in t)this.option[i]=void 0!==e[i]?e[i]:t[i];else this.option=t}var t={blurSize:30,gradientColors:["blue","cyan","lime","yellow","red"],minAlpha:.05,valueScale:1,opacity:1},i=20,n=256;return e.prototype={getCanvas:function(e,t,a){var o=this._getBrush(),r=this._getGradient(),s=i+this.option.blurSize,l=document.createElement("canvas");l.width=t,l.height=a;for(var h=l.getContext("2d"),m=e.length,V=0;m>V;++V){var d=e[V],U=d[0],p=d[1],c=d[2],u=Math.min(1,Math.max(c*this.option.valueScale||this.option.minAlpha,this.option.minAlpha));h.globalAlpha=u,h.drawImage(o,U-s,p-s)}for(var g=h.getImageData(0,0,l.width,l.height),y=g.data,m=y.length/4;m--;){var b=4*m+3,u=y[b]/256,f=Math.floor(u*(n-1));y[b-3]=r[4*f],y[b-2]=r[4*f+1],y[b-1]=r[4*f+2],y[b]*=this.option.opacity}return h.putImageData(g,0,0),l},_getBrush:function(){if(!this._brushCanvas){this._brushCanvas=document.createElement("canvas");var e=i+this.option.blurSize,t=2*e;this._brushCanvas.width=t,this._brushCanvas.height=t;var n=this._brushCanvas.getContext("2d");n.shadowOffsetX=t,n.shadowBlur=this.option.blurSize,n.shadowColor="black",n.beginPath(),n.arc(-e,e,i,0,2*Math.PI,!0),n.closePath(),n.fill()}return this._brushCanvas},_getGradient:function(){if(!this._gradientPixels){var e=n,t=document.createElement("canvas");t.width=1,t.height=e;for(var i=t.getContext("2d"),a=i.createLinearGradient(0,0,0,e),o=this.option.gradientColors.length,r=0;o>r;++r)"string"==typeof this.option.gradientColors[r]?a.addColorStop((r+1)/o,this.option.gradientColors[r]):a.addColorStop(this.option.gradientColors[r].offset,this.option.gradientColors[r].color);i.fillStyle=a,i.fillRect(0,0,1,e),this._gradientPixels=i.getImageData(0,0,1,e).data}return this._gradientPixels}},e}),define("echarts/layer/heatmap",["require"],function(){function e(e){if(this.option=e,e)for(var i in t)this.option[i]=void 0!==e[i]?e[i]:t[i];else this.option=t}var t={blurSize:30,gradientColors:["blue","cyan","lime","yellow","red"],minAlpha:.05,valueScale:1,opacity:1},i=20,n=256;return e.prototype={getCanvas:function(e,t,a){var o=this._getBrush(),r=this._getGradient(),s=i+this.option.blurSize,l=document.createElement("canvas");l.width=t,l.height=a;for(var h=l.getContext("2d"),m=e.length,V=0;m>V;++V){var d=e[V],U=d[0],p=d[1],c=d[2],u=Math.min(1,Math.max(c*this.option.valueScale||this.option.minAlpha,this.option.minAlpha));h.globalAlpha=u,h.drawImage(o,U-s,p-s)}for(var g=h.getImageData(0,0,l.width,l.height),y=g.data,m=y.length/4;m--;){var b=4*m+3,u=y[b]/256,f=Math.floor(u*(n-1));y[b-3]=r[4*f],y[b-2]=r[4*f+1],y[b-1]=r[4*f+2],y[b]*=this.option.opacity}return h.putImageData(g,0,0),l},_getBrush:function(){if(!this._brushCanvas){this._brushCanvas=document.createElement("canvas");var e=i+this.option.blurSize,t=2*e;this._brushCanvas.width=t,this._brushCanvas.height=t;var n=this._brushCanvas.getContext("2d");n.shadowOffsetX=t,n.shadowBlur=this.option.blurSize,n.shadowColor="black",n.beginPath(),n.arc(-e,e,i,0,2*Math.PI,!0),n.closePath(),n.fill()}return this._brushCanvas},_getGradient:function(){if(!this._gradientPixels){var e=n,t=document.createElement("canvas");t.width=1,t.height=e;for(var i=t.getContext("2d"),a=i.createLinearGradient(0,0,0,e),o=this.option.gradientColors.length,r=0;o>r;++r)"string"==typeof this.option.gradientColors[r]?a.addColorStop((r+1)/o,this.option.gradientColors[r]):a.addColorStop(this.option.gradientColors[r].offset,this.option.gradientColors[r].color);i.fillStyle=a,i.fillRect(0,0,1,e),this._gradientPixels=i.getImageData(0,0,1,e).data}return this._gradientPixels}},e});