Last active
January 6, 2017 03:27
-
-
Save topologicallytony/dcad982821f737ce81df963a50692177 to your computer and use it in GitHub Desktop.
Sierpinski Triangle
This file contains hidden or 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>Sierpinski Triangle</title> | |
<!-- D3.js --> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<!-- Latest compiled and minified CSS --> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> | |
<style type="text/css"> | |
.line { | |
fill: none; | |
stroke: steelblue; | |
stroke-width: 1px; | |
} | |
.base_line { | |
fill: none; | |
stroke: steelblue; | |
stroke-width: 1px; | |
} | |
</style> | |
</head> | |
<body> | |
<div> | |
Click to Iterate | |
</div> | |
<script type="text/javascript"> | |
//Basic idea is you have 2 datasets | |
//The first holds line segments that are drawn | |
//The second holds all the triangles that are iterated on | |
//Width and height of the visualization | |
var w = 500; | |
var h = 500; | |
//How much skew? 0.5 means sierpinski | |
var skew = 0.5; | |
//padding creates a buffer of white space around the chart to make it a little easier to look at | |
var padding = 15; | |
//Create the scales used to map the set | |
var xScale = d3.scaleLinear() | |
.domain([-.5, 1.5]) | |
.range([padding, w - padding]); | |
var yScale = d3.scaleLinear() | |
.domain([-1, 1]) | |
.range([h - padding, padding]); | |
//Create a canvas to display the chart on | |
var svg = d3.select("body").append("svg") | |
.attr("width", w) | |
.attr("height", h); | |
//Create group elements to layer the svg | |
//This is an easy way to make sure things you want on top are on top, and things you want behind stay behind | |
var layer1 = svg.append('g'); | |
var layer2 = svg.append('g'); | |
var layer3 = svg.append('g'); | |
//This function will iterate the koch snowflake and is called on mouse click | |
function step() { | |
//temp_dataset holds the most recently displayed iteration | |
temp_dataset = triangles; | |
//dataset will get loaded with the next iteration | |
triangles = []; | |
//How many triangles we need to iterate on | |
var len = temp_dataset.length; | |
//For each triangle, add an inscribed triangle | |
for (var i = 0; i < len; i++) { | |
//get the endpoints of the current triangle | |
var x1 = temp_dataset[i][0]; | |
var y1 = temp_dataset[i][1]; | |
var x2 = temp_dataset[i][2]; | |
var y2 = temp_dataset[i][3]; | |
var x3 = temp_dataset[i][4]; | |
var y3 = temp_dataset[i][5]; | |
//find points at skew | |
var x13_new = x1 + ((x3 - x1) * skew); | |
var y13_new = y1 + ((y3 - y1) * skew); | |
var x12_new = x2 + ((x1 - x2) * skew); | |
var y12_new = y2 + ((y1 - y2) * skew); | |
var x23_new = x3 + ((x2 - x3) * skew); | |
var y23_new = y3 + ((y2 - y3) * skew); | |
//Store the 3 new triangles, and 3 new line segments | |
triangles.push([x1, y1, x12_new, y12_new, x13_new, y13_new]); | |
triangles.push([x2, y2, x23_new, y23_new, x12_new, y12_new]); | |
triangles.push([x3, y3, x13_new, y13_new, x23_new, y23_new]); | |
lines.push([x1, y1, x2, y2, x3, y3]); | |
lines.push([x2, y2, x3, y3, x1, y1]); | |
lines.push([x3, y3, x1, y1, x2, y2]); | |
} | |
} | |
function display() { | |
//Draw all the lines | |
var line = layer2.selectAll(".line").data(lines); | |
line | |
.attr("x1", function(d){return xScale(d[0] + ((d[4] - d[0]) * skew));}) | |
.attr("y1", function(d){return yScale(d[1] + ((d[5] - d[1]) * skew));}) | |
.attr("x2", function(d){return xScale(d[2] + ((d[0] - d[2]) * skew));}) | |
.attr("y2", function(d){return yScale(d[3] + ((d[1] - d[3]) * skew));}); | |
line.enter().append("line") | |
.attr("x1", function(d){return xScale(d[0]);}) | |
.attr("y1", function(d){return yScale(d[1]);}) | |
.attr("x2", function(d){return xScale(d[2]);}) | |
.attr("y2", function(d){return yScale(d[3]);}) | |
.transition() | |
.duration(1250) | |
.attr("x1", function(d){return xScale(d[0] + ((d[4] - d[0]) * skew));}) | |
.attr("y1", function(d){return yScale(d[1] + ((d[5] - d[1]) * skew));}) | |
.attr("x2", function(d){return xScale(d[2] + ((d[0] - d[2]) * skew));}) | |
.attr("y2", function(d){return yScale(d[3] + ((d[1] - d[3]) * skew));}) | |
.attr("class", "line"); | |
} | |
//initialize the datasets | |
var temp_dataset = []; | |
//lines will hold all the line segments | |
//initialize with an equilateral triangle. | |
var lines = [ | |
[0, 0, Math.cos(Math.PI / 3), Math.sin(Math.PI / 3)], | |
[Math.cos(Math.PI / 3), Math.sin(Math.PI / 3), 1, 0], | |
[1, 0, 0, 0] | |
]; | |
var triangles = [ | |
[0, 0, 1, 0, Math.cos(Math.PI / 3), Math.sin(Math.PI / 3)] | |
]; | |
layer2.selectAll(".base_line").data(lines).enter().append("line") | |
.attr("x1", function(d){return xScale(d[0]);}) | |
.attr("y1", function(d){return yScale(d[1]);}) | |
.attr("x2", function(d){return xScale(d[2]);}) | |
.attr("y2", function(d){return yScale(d[3]);}) | |
.attr("class", "base_line"); | |
lines = []; | |
d3.select("body") | |
.on("click", function() { | |
step(); | |
display(); | |
}); | |
d3.select("body") | |
.on("touchstart", function() { | |
step(); | |
display(); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment