Skip to content

Instantly share code, notes, and snippets.

@ZJONSSON
Created November 6, 2011 15:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZJONSSON/1343062 to your computer and use it in GitHub Desktop.
Save ZJONSSON/1343062 to your computer and use it in GitHub Desktop.
Basic filled contours in D3
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js"></script>
<script type="text/javascript" src="multiplot.js"></script>
</head>
<body></body>
<script type="text/javascript">
// Simplified version of calculating contours based on triangular mesh between each set of 4 points.
// Contour segments are "unconnected" but collectively fill up the contour map
// Futher development might include connecting points to collapse lines and shapes
// Idea based on CONREC by Paul Bourke http://paulbourke.net/papers/conrec/
function contour(data,levels) {
var contour_lines = [],
contour_areas=[]
function checkTriangle(levels,level_no,edges) {
var contour = [],
area = [],
c=levels[level_no]+0.000000000001
function checkLine(c,p1,p2) {
if ((c>Math.min(p1[2],p2[2])) && (c< Math.max(p1[2],p2[2]))) {
var fraction=(c-p1[2])/(p2[2]-p1[2])
contour.push([p1[0]+fraction*(p2[0]-p1[0]),p1[1]+fraction*(p2[1]-p1[1]),c])
area.push([p1[0]+fraction*(p2[0]-p1[0]),p1[1]+fraction*(p2[1]-p1[1]),c])
}
if (p2[2] > c) {
area.push(p2)
}
}
checkLine(c,edges[0],edges[1])
checkLine(c,edges[1],edges[2])
checkLine(c,edges[2],edges[0])
if(contour.length==2) {
contour_lines[level_no].push(contour)
}
if(area.length>0) {
contour_areas[level_no].push(area)
if (level_no < (levels.length-2) ) {
checkTriangle(levels,level_no+1,edges)
}
}
}
for (var i=0;i<levels.length;i++) {
contour_areas.push([]);
contour_lines.push([]);
}
for(var x=0;x<data.length-1;x++) {
for (var y=0;y<data[0].length-1;y++) {
var middle = (data[x][y]+data[x+1][y]+data[x][y+1]+data[x+1][y+1])/4,
a=[x,y,data[x][y]],
b=[x+1,y,data[x+1][y]],
c=[x+0.5,y+0.5,middle],
d=[x,y+1,data[x][y+1]],
e=[x+1,y+1,data[x+1][y+1]]
checkTriangle(levels,0,[a,b,c])
checkTriangle(levels,0,[a,c,d])
checkTriangle(levels,0,[d,c,e])
checkTriangle(levels,0,[b,c,e])
}
}
return {area:contour_areas,lines:contour_lines}
}
// Lets take it for a spin
w = 500, h = 500;
x=d3.scale.linear().range([0,w]).domain([0,data[0].length]),
y=d3.scale.linear().range([h,0]).domain([0,data.length]),
svg=d3.select("body").append("svg:svg")
.attr("width",w)
.attr("height",h)
zs = d3.range(-5, 3, .5)
data=contour(data,zs)
colors = d3.scale.linear().domain([-5, 3]).range(["#fff", "red"]);
areas=svg.append("svg:g").selectAll("g")
.data(data.area)
.enter()
.append("svg:g")
.style("fill",function(d,i) { return colors(zs[i])})
.style("stroke",function(d,i) { return colors(zs[i])})
.style("opacity",0.5)
.selectAll("polygon")
.data(function(d) { return d;})
.enter()
.append("svg:polygon")
.attr("points",function(d) {
var txt=""
d.forEach(function(e) { ;txt+=x(e[0])+","+y(e[1])+" "})
return txt
})
lines=svg.append("svg:g").selectAll("g")
.data(data.lines)
.enter()
.append("svg:g")
.selectAll("g").data(function(d) { return d;})
.enter()
.append("svg:path")
.style("fill","black")
.style("stroke","black")
.attr("d",d3.svg.line()
.x(function(d) { return x(d[0])})
.y(function(d) { return y(d[1])})
)
</SCRIPT>
</html>
/**
* Originally from http://www2.warwick.ac.uk/fac/sci/moac/currentstudents/peter_cock/r/matrix_contour/
*/
var data = [
[
0.4,
0.4,
0.7,
-1.0,
-0.1,
0.6,
-0.4,
0.6,
-0.4,
1.3,
0.7,
-0.4,
1.1,
1.3,
0.6,
0.1,
-0.0,
-0.8,
-0.8,
-1.0
],
[
0.4,
-0.4,
0.4,
-1.2,
-0.7,
0.4,
-0.9,
0.5,
-0.9,
1.2,
0.5,
-1.0,
1.3,
1.1,
0.5,
-0.0,
-0.1,
-1.2,
-1.0,
-0.9
],
[
0.7,
0.4,
0.1,
-1.2,
-0.2,
0.5,
-0.6,
0.6,
-0.2,
0.9,
0.6,
-0.5,
1.1,
0.8,
0.6,
0.1,
-0.4,
-0.9,
-0.7,
-0.8
],
[
-1.0,
-1.2,
-1.2,
-4.4,
-1.9,
-0.8,
-2.2,
-1.0,
-2.2,
0.0,
-0.3,
-2.0,
-0.2,
0.2,
-0.8,
-1.6,
-1.9,
-2.4,
-2.3,
-2.6
],
[
-0.1,
-0.7,
-0.2,
-1.9,
-2.0,
-0.5,
-1.9,
-0.3,
-1.7,
0.4,
-0.2,
-1.9,
0.3,
0.4,
-0.3,
-0.8,
-0.9,
-2.1,
-1.8,
-2.0
],
[
0.6,
0.4,
0.5,
-0.8,
-0.5,
-0.1,
-0.8,
0.6,
-0.5,
1.0,
0.5,
-0.7,
0.8,
1.0,
0.5,
0.1,
-0.3,
-0.9,
-0.7,
-1.1
],
[
-0.4,
-0.9,
-0.6,
-2.2,
-1.9,
-0.8,
-2.7,
-0.6,
-2.0,
0.3,
-0.3,
-2.3,
-0.0,
-0.0,
-0.6,
-1.1,
-1.3,
-2.4,
-2.0,
-2.2
],
[
0.6,
0.5,
0.6,
-1.0,
-0.3,
0.6,
-0.6,
0.1,
-0.8,
1.3,
0.8,
-0.8,
1.1,
1.3,
0.4,
0.1,
0.1,
-0.8,
-1.0,
-1.0
],
[
-0.4,
-0.9,
-0.2,
-2.2,
-1.7,
-0.5,
-2.0,
-0.8,
-2.9,
0.3,
-0.4,
-2.2,
-0.0,
-0.0,
-0.7,
-0.7,
-1.3,
-2.4,
-2.1,
-2.6
],
[
1.3,
1.2,
0.9,
0.0,
0.4,
1.0,
0.3,
1.3,
0.3,
1.1,
1.0,
0.2,
0.7,
1.9,
0.9,
-0.2,
0.3,
0.1,
-0.4,
-0.2
],
[
0.7,
0.5,
0.6,
-0.3,
-0.2,
0.5,
-0.3,
0.8,
-0.4,
1.0,
0.3,
-0.3,
1.0,
1.1,
0.6,
0.1,
0.3,
-0.7,
-0.5,
-0.6
],
[
-0.4,
-1.0,
-0.5,
-2.0,
-1.9,
-0.7,
-2.3,
-0.8,
-2.2,
0.2,
-0.3,
-2.7,
0.0,
-0.0,
-0.6,
-1.0,
-1.1,
-2.3,
-2.1,
-2.4
],
[
1.1,
1.3,
1.1,
-0.2,
0.3,
0.8,
-0.0,
1.1,
-0.0,
0.7,
1.0,
0.0,
1.6,
0.8,
1.0,
0.8,
0.7,
-0.2,
-0.2,
-0.2
],
[
1.3,
1.1,
0.8,
0.2,
0.4,
1.0,
-0.0,
1.3,
-0.0,
1.9,
1.1,
-0.0,
0.8,
1.2,
1.1,
0.0,
0.2,
-0.1,
-0.4,
0.0
],
[
0.6,
0.5,
0.6,
-0.8,
-0.3,
0.5,
-0.6,
0.4,
-0.7,
0.9,
0.6,
-0.6,
1.0,
1.1,
-0.2,
0.1,
-0.0,
-0.9,
-0.6,
-1.2
],
[
0.1,
-0.0,
0.1,
-1.6,
-0.8,
0.1,
-1.1,
0.1,
-0.7,
-0.2,
0.1,
-1.0,
0.8,
0.0,
0.1,
-0.6,
-0.4,
-1.2,
-1.3,
-1.4
],
[
-0.0,
-0.1,
-0.4,
-1.9,
-0.9,
-0.3,
-1.3,
0.1,
-1.3,
0.3,
0.3,
-1.1,
0.7,
0.2,
-0.0,
-0.4,
-1.3,
-1.4,
-1.6,
-1.9
],
[
-0.8,
-1.2,
-0.9,
-2.4,
-2.1,
-0.9,
-2.4,
-0.8,
-2.4,
0.1,
-0.7,
-2.3,
-0.2,
-0.1,
-0.9,
-1.2,
-1.4,
-3.0,
-2.3,
-2.5
],
[
-0.8,
-1.0,
-0.7,
-2.3,
-1.8,
-0.7,
-2.0,
-1.0,
-2.1,
-0.4,
-0.5,
-2.1,
-0.2,
-0.4,
-0.6,
-1.3,
-1.6,
-2.3,
-2.3,
-2.4
],
[
-1.0,
-0.9,
-0.8,
-2.6,
-2.0,
-1.1,
-2.2,
-1.0,
-2.6,
-0.2,
-0.6,
-2.4,
-0.2,
0.0,
-1.2,
-1.4,
-1.9,
-2.5,
-2.4,
-3.3
]
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment