|
/* compute a Lindenmayer system given an axiom, a number of steps and rules |
|
*/ |
|
|
|
(function() { |
|
var collapse, curves, fractal, fractalize, height, side, steps, svg, svg_path, width; |
|
|
|
fractalize = function(config) { |
|
var char, i, input, output, _i, _len, _ref; |
|
input = config.axiom; |
|
for (i = 0, _ref = config.steps; 0 <= _ref ? i < _ref : i > _ref; 0 <= _ref ? i++ : i--) { |
|
output = ''; |
|
for (_i = 0, _len = input.length; _i < _len; _i++) { |
|
char = input[_i]; |
|
if (char in config.rules) { |
|
output += config.rules[char]; |
|
} else { |
|
output += char; |
|
} |
|
} |
|
input = output; |
|
} |
|
return output; |
|
}; |
|
|
|
/* convert a Lindenmayer string into an SVG path string |
|
*/ |
|
|
|
svg_path = function(config) { |
|
var angle, char, path, _i, _len, _ref; |
|
angle = 0.0; |
|
path = 'M0 0'; |
|
_ref = config.fractal; |
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) { |
|
char = _ref[_i]; |
|
if (char === '+') { |
|
angle += config.angle; |
|
} else if (char === '-') { |
|
angle -= config.angle; |
|
} else if (char === 'F') { |
|
path += "l" + (config.side * Math.cos(angle)) + " " + (config.side * Math.sin(angle)); |
|
} |
|
} |
|
return path; |
|
}; |
|
|
|
side = 6; |
|
|
|
curves = []; |
|
|
|
for (steps = 1; steps <= 4; steps++) { |
|
fractal = fractalize({ |
|
axiom: 'L', |
|
steps: steps, |
|
rules: { |
|
L: 'LFRFL-F-RFLFR+F+LFRFL', |
|
R: 'RFLFR+F+LFRFL-F-RFLFR' |
|
} |
|
}); |
|
curves.push(svg_path({ |
|
fractal: fractal, |
|
side: side, |
|
angle: Math.PI / 2 |
|
})); |
|
} |
|
|
|
width = 960; |
|
|
|
height = 500; |
|
|
|
svg = d3.select('body').append('svg').attr('width', width).attr('height', height); |
|
|
|
svg.selectAll('.curve').data(curves).enter().append('path').attr('class', 'curve').attr('d', function(d) { |
|
return d; |
|
}).attr('transform', function(d, i) { |
|
return "translate(" + (100 + (Math.pow(3, i + 1) / 2 + i) * side) + ",490)"; |
|
}).attr('opacity', 1); |
|
|
|
collapse = false; |
|
|
|
svg.on('click', function() { |
|
collapse = !collapse; |
|
if (collapse) { |
|
return svg.selectAll('.curve').transition().duration(1000).attr('transform', function(d, i) { |
|
return 'translate(240,490)'; |
|
}).attr('opacity', 0.4); |
|
} else { |
|
return svg.selectAll('.curve').transition().duration(1000).attr('transform', function(d, i) { |
|
return "translate(" + (100 + (Math.pow(3, i + 1) / 2 + i) * side) + ",490)"; |
|
}).attr('opacity', 1); |
|
} |
|
}); |
|
|
|
}).call(this); |