Skip to content

Instantly share code, notes, and snippets.

@nitaku
Last active August 29, 2015 13:56
Show Gist options
  • Save nitaku/9306999 to your computer and use it in GitHub Desktop.
Save nitaku/9306999 to your computer and use it in GitHub Desktop.
Peano Hex curve (L-system)
### compute a Lindenmayer system given an axiom, a number of steps and rules ###
fractalize = (config) ->
input = config.axiom
for i in [0...config.steps]
output = ''
for char in input
if char of config.rules
output += config.rules[char]
else
output += char
input = output
return output
### convert a Lindenmayer string into an SVG path string ###
svg_path = (config) ->
angle = 0.0
path = 'M0 0'
for char in config.fractal
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
### animate the path ###
### from Mike Bostock's stroke dash interpolation example http://bl.ocks.org/mbostock/5649592 ###
tweenDash = () ->
l = this.getTotalLength()
i = d3.interpolateString('0,' + l, l + ',' + l)
return (t) -> i(t)
transition = (path) ->
path.transition()
.duration(20000)
.attrTween('stroke-dasharray', tweenDash)
curve = fractalize
axiom: 'L'
steps: 4
rules:
L: 'LFRFL-F--RFLFR+F++LFRFL'
R: 'RFLFR+F++LFRFL-F--RFLFR'
d = svg_path
fractal: curve
side: 6
angle: Math.PI/3
width = 960
height = 500
svg = d3.select('body').append('svg')
.attr('width', width)
.attr('height', height)
svg.append('path')
.attr('class', 'curve shadow')
.attr('d', d)
.attr('transform', 'translate(240,460)')
svg.append('path')
.attr('class', 'curve')
.attr('d', d)
.attr('transform', 'translate(240,460)')
.call(transition)
.curve {
fill: none;
stroke: black;
stroke-width: 1.5px;
}
.shadow {
opacity: 0.1;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Peano Hex curve</title>
<link type="text/css" href="index.css" rel="stylesheet"/>
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body></body>
<script src="index.js"></script>
</html>
/* compute a Lindenmayer system given an axiom, a number of steps and rules
*/
(function() {
var curve, d, fractalize, height, svg, svg_path, transition, tweenDash, 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;
};
/* animate the path
*/
/* from Mike Bostock's stroke dash interpolation example http://bl.ocks.org/mbostock/5649592
*/
tweenDash = function() {
var i, l;
l = this.getTotalLength();
i = d3.interpolateString('0,' + l, l + ',' + l);
return function(t) {
return i(t);
};
};
transition = function(path) {
return path.transition().duration(20000).attrTween('stroke-dasharray', tweenDash);
};
curve = fractalize({
axiom: 'L',
steps: 4,
rules: {
L: 'LFRFL-F--RFLFR+F++LFRFL',
R: 'RFLFR+F++LFRFL-F--RFLFR'
}
});
d = svg_path({
fractal: curve,
side: 6,
angle: Math.PI / 3
});
width = 960;
height = 500;
svg = d3.select('body').append('svg').attr('width', width).attr('height', height);
svg.append('path').attr('class', 'curve shadow').attr('d', d).attr('transform', 'translate(240,460)');
svg.append('path').attr('class', 'curve').attr('d', d).attr('transform', 'translate(240,460)').call(transition);
}).call(this);
.curve
fill: none
stroke: black
stroke-width: 1.5px
.shadow
opacity: 0.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment