A Pen by Geoff Jacobsen on CodePen.
Created
January 12, 2019 21:41
-
-
Save jacott/4676db15789a80db25de81ffe0f8b7b6 to your computer and use it in GitHub Desktop.
Heatmap using Inverse distance weighting - Shepard's method
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
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