Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save jacott/4676db15789a80db25de81ffe0f8b7b6 to your computer and use it in GitHub Desktop.
Save jacott/4676db15789a80db25de81ffe0f8b7b6 to your computer and use it in GitHub Desktop.
Heatmap using Inverse distance weighting - Shepard's method
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Heatmap using Inverse distance weighting - Shepard's method</title>
</head>
<body>
<canvas
id="canvas1"
style="width:600px;height:400px" width="600" height="400"></canvas>
</body>
</html>
{
const hue2rgb = (t)=>{
if (t < 0) t += 6;
if (t > 6) t -= 6;
if (t < 1) return Math.round(t * 255);
if (t < 3) return 255;
if (t < 4) return Math.round((4 - t) * 255);
return 0;
};
const putHue = (h, data, i)=>{
data[i] = hue2rgb(h + 2);
data[i+1] = hue2rgb(h);
data[i+2] = hue2rgb(h - 2);
};
const canvas = document.getElementById("canvas1");
const ctx = canvas.getContext('2d', { alpha: false });
const markers = [
{x: 10, y: 20, value: 100},
{x: 200, y: 350, value: 12},
{x: 50, y: 200, value: 0},
{x: 300, y: 200, value: 25},
{x: 500, y: 50, value: 75},
{x: 400, y: 30, value: 50},
{x: 550, y: 350, value: 87},
];
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const {data} = imageData;
const {width, height} = canvas;
const ml = markers.length;
const draw = (canvas, markers, yFrom=0, yTo=height)=>{
for (let y = yFrom; y < yTo; ++y) {
for (let x = 0; x < width; ++x) {
let t = 0, b = 0;
for(let i = 0; i < ml; ++i) {
const m = markers[i];
const cx = m.x, cy = m.y;
const dx = x - cx, dy = y - cy;
const d2 = dx*dx + dy*dy;
// Inverse distance weighting - Shepard's method
// https://en.wikipedia.org/wiki/Inverse_distance_weighting
if (d2 == 0) {
b = 1; t = m.value;
break;
}
const inv = 1 / (d2*d2);
t += inv * m.value;
b += inv;
}
putHue(4-(0.04*t/b), data, (y*width + x)*4);
}
}
};
draw(canvas, markers);
ctx.putImageData(imageData, 0, 0);
// benchmark
// draw(canvas, markers);
// const d = Date.now();
// for(let i = 0; i < 100; ++i) {
// draw(canvas, markers, i, i+40);
// }
// const d2 = Date.now();
// console.log(`time in ms `+((d2 - d)/100));
for(let i = 0; i < markers.length; ++i) {
const m = markers[i];
ctx.fillRect(m.x, m.y, 5, 5);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment