Skip to content

Instantly share code, notes, and snippets.

@nguyenthang98
Last active September 4, 2019 10:11
Show Gist options
  • Select an option

  • Save nguyenthang98/ebf4bbc1b4807df08b05d9e0bb193304 to your computer and use it in GitHub Desktop.

Select an option

Save nguyenthang98/ebf4bbc1b4807df08b05d9e0bb193304 to your computer and use it in GitHub Desktop.
contour test
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-contour.v1.min.js"></script>
<script src="https://d3js.org/d3-hsv.v0.1.min.js"></script>
</head>
<body>
<canvas id="mycanvas" width="900" height="500" style="background-color: lightgrey"></canvas>
<script>
const width = 900;
const height = 500;
const canvas = d3.select('#mycanvas');
const ctx = canvas.node().getContext('2d');
async function loadDataJSON(file) {
return new Promise(resolve => {
d3.json(file || 'data.json', resolve);
})
}
let i0 = d3.interpolateHsvLong(d3.hsv(120, 1, 0.65), d3.hsv(60, 1, 0.90)),
i1 = d3.interpolateHsvLong(d3.hsv(60, 1, 0.90), d3.hsv(0, 0, 0.95)),
interpolateTerrain = function(t) { return t < 0.5 ? i0(t * 2) : i1((t - 0.5) * 2); },
color = d3.scaleSequential(interpolateTerrain).domain([90, 190]);
async function drawContour(_data) {
const data = _data || await loadDataJSON();
const contours = d3.contours()
.size([data.width, data.height])
.thresholds([-10, -5, -2, 1,5,7,10,15,20,21,22])
(data.values);
contours.forEach(c => {
const path = d3.geoPath(d3.geoIdentity().scale(width / data.width))(c);
const p = new Path2D(path);
ctx.stroke(p);
// ctx.fillStyle = color(c.value);
// ctx.fill(p);
})
}
async function loadDataDensity() {
return new Promise(resolve => {
d3.csv("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_for_density2d.csv", resolve);
});
}
async function drawContourDensity() {
const data = await loadDataDensity();
const x = d3.scaleLinear()
.domain([5, 20])
.range([ 0, width ]);
const y = d3.scaleLinear()
.domain([5, 22])
.range([ height, 0 ]);
data.forEach(d => {
ctx.fillRect(x(d.x), y(d.y), 1,1);
})
const densityData = d3.contourDensity()
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); })
.size([width, height])
.bandwidth(20)
(data);
densityData.forEach(d => {
const path = d3.geoPath()(d);
const p = new Path2D(path);
ctx.stroke(p);
})
}
function distance(p1, p2) {
return Math.sqrt((p2.x - p1.x)**2 + (p2.y - p1.y)**2);
}
function getWeightFromDistance(distance) {
return 10/distance;
}
function calValue(index, data) {
const y = Math.floor(index/width);
const x = index - y * width;
const toReturn = data.reduce((acc, curr)=>{
return acc + curr.value * getWeightFromDistance(distance(curr, {x,y}));
}, 0);
return toReturn;
}
async function drawContourInterpolation() {
const data = await loadDataJSON('sampleData.json');
const sampleArr = new Array(width*height);
data.forEach(d => {
sampleArr[width* d.y + d.x] = d.value;
});
for (let i=0; i < sampleArr.length; ++i) {
if (!sampleArr[i]) {
sampleArr[i] = calValue(i, data);
}
}
drawContour({width, height, values: sampleArr});
}
drawContourInterpolation();
//drawContourDensity();
//drawContour();
</script>
</body>
[
{"x": 100, "y": 50, "value": 110},
{"x": 750, "y": 200, "value": 80},
{"x": 450, "y": 450, "value": -10}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment