Last active
December 30, 2015 20:48
-
-
Save gchan/7882865 to your computer and use it in GitHub Desktop.
Sierpinski Triangle
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> | |
<meta charset="utf-8"> | |
<style> | |
polygon { | |
fill: orange; | |
} | |
body { | |
font: 12px sans-serif; | |
} | |
</style> | |
<body> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.3.11/d3.min.js"></script> | |
<div id='controls'> | |
<button id='subtract'>-</button> | |
<button id='add'>+</button> | |
Level <strong id='level'>5</strong> | |
</div> | |
<script> | |
var margin = { top: 20, right: 20, bottom: 20, left: 20 }, | |
width = 480 - margin.left - margin.right, | |
height = 430 - margin.top - margin.bottom; | |
var svg = d3.select("body").append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
var triangle_height = width / 2 * Math.tan(Math.PI * 1 / 3); | |
var root_triangle = { | |
top: { x: width / 2, y: 0 }, | |
left: { x: 0, y: triangle_height }, | |
right: { x: width, y: triangle_height } | |
}; | |
var data_cache = { | |
0: [ root_triangle ] | |
}; | |
var level = 5; | |
function clone_obj(obj) { | |
return JSON.parse(JSON.stringify(obj)); | |
} | |
function compute_triangle_points(levels) { | |
var data; | |
if (data_cache[levels]) { | |
return data_cache[levels]; | |
} | |
data = clone_obj(compute_triangle_points(levels - 1)); | |
data.forEach(function(tri) { | |
var height_adj = (tri.left.y - tri.top.y) / 2; | |
var width_adj = (tri.top.x - tri.left.x) / 2; | |
var left_vertex = { | |
x: tri.left.x + width_adj, | |
y: tri.left.y - height_adj | |
}; | |
var right_vertex = { | |
x: tri.right.x - width_adj, | |
y: tri.right.y - height_adj | |
}; | |
var bottom_vertex = { | |
x: tri.top.x, | |
y: tri.right.y | |
}; | |
var left_tri = clone_obj(tri); | |
var right_tri = clone_obj(tri); | |
tri.left = clone_obj(left_vertex); | |
tri.right = clone_obj(right_vertex); | |
left_tri.top = clone_obj(left_vertex); | |
left_tri.right = clone_obj(bottom_vertex); | |
right_tri.top = clone_obj(right_vertex); | |
right_tri.left = clone_obj(bottom_vertex); | |
data.push(left_tri); | |
data.push(right_tri); | |
}); | |
data_cache[levels] = data; | |
return data; | |
} | |
function vertex_to_string(vertex) { | |
return vertex.x + ", " + vertex.y; | |
} | |
function triangle_points(tri) { | |
return vertex_to_string(tri.left) + " " + vertex_to_string(tri.right) + " " + vertex_to_string(tri.top); | |
} | |
function render_sierpinski_triangle(levels) { | |
d3.select('#level').text(level); | |
svg.selectAll("*").remove(); | |
svg.selectAll("polygon") | |
.data(compute_triangle_points(levels)) | |
.enter().append("polygon") | |
.attr('points', triangle_points); | |
} | |
function increase_level() { | |
level = Math.min(level + 1, 8); | |
render_sierpinski_triangle(level); | |
} | |
function decrease_level() { | |
level = Math.max(level - 1, 0); | |
render_sierpinski_triangle(level); | |
} | |
d3.select('#subtract').on('click', decrease_level); | |
d3.select('#add').on('click', increase_level); | |
render_sierpinski_triangle(level); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment