Skip to content

Instantly share code, notes, and snippets.

@zeffii
Created January 3, 2013 16:08
Show Gist options
  • Save zeffii/4444542 to your computer and use it in GitHub Desktop.
Save zeffii/4444542 to your computer and use it in GitHub Desktop.
almost_dendelion
{"description":"almost_dendelion","endpoint":"","display":"canvas","public":true,"require":[],"fileconfigs":{"inlet.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"_.md":{"default":true,"vim":false,"emacs":false,"fontSize":12},"config.json":{"default":true,"vim":false,"emacs":false,"fontSize":12}},"tab":"edit","display_percent":0.5179645222468813,"play":false,"loop":false,"restart":false,"autoinit":true,"pause":true,"loop_type":"period","bv":false,"nclones":15,"clone_opacity":0.4,"duration":3000,"ease":"linear","dt":0.01,"hidepanel":false}
d3.select("body").style("background", "#242222")
// variables
var bend = 2*(15.07525), // angle to twist (degrees)
i_max = 8, // limit, warning 10 is probably an upperlimit
i_user = Math.abs(Math.floor(8)), // scrub between 1 and upperlimit for recursion levels
iterations = Math.min(i_max, i_user), // number of rewrites (recursion levels in grammar)
F = 116243/(Math.pow(2.4,iterations)), // arm distance
angle_offset = to_rad(bend), // angle as radian
angle_rad = 0, // the current angle for drawing
x_start = 409, // drawing start x
y_start = 455, // drawing start y
x_current = x_start, // current cursor position x
y_current = y_start, // current cursor position y
rules = {}, // a map of the rules
commands = {}; // a map of the commands
/* Helper Functions */
function to_rad(degrees){
return degrees * (2*Math.PI) / 360
}
function get_xy(angle_rad, Lv){
return {x: Math.cos(angle_rad) * Lv,
y: Math.sin(angle_rad) * Lv}
}
function command_from_rad(command, angle_rad){
var command_parts = command.split(" ");
Lv = parseFloat(command_parts[1]);
if (command_parts.length > 2) {
if (command_parts[2] == "R") Lv = Lv*(1 + (command_parts[3] * (Math.random() - 0.5))/100);
}
var c = get_xy(angle_rad,Lv);
x_current = x_current + c.x;
y_current = y_current + c.y;
if (command_parts[0] == "L") tributary.ctx.lineTo(x_current, y_current);
if (command_parts[0] == "M") {
tributary.ctx.stroke();
tributary.ctx.moveTo(x_current, y_current);
}
}
function make_path(rules, commands, start_string){
tributary.ctx.moveTo(x_start,y_start);
tributary.ctx.strokeStyle = '#BEBEBE';
tributary.ctx.lineWidth = 0.6;
recursive_path(rules,commands,start_string, 0);
tributary.ctx.stroke();
}
/* L-systems grammar rewriting */
function recursive_path(rules, commands, input_string, iteration) {
var token = "";
for (i in d3.range(input_string.length)) {
token = input_string[i];
if (token === '-') angle_rad += angle_offset;
else if (token === '+') angle_rad -= angle_offset;
else if (token in rules) {
// if we're at the bottom level, move forward
if (iteration >= iterations && token in commands) command_from_rad(commands[token], angle_rad);
// else go deeper down the rabbit hole...
else recursive_path(rules, commands, rules[token], iteration+1);
}
else if (token in commands) {
command_from_rad(commands[token], angle_rad);
}
}
}
delete rules;
delete commands;
// The rules:
// + means turn left by bend degrees
// - means turn right by bend degrees
// Variables (like A or B) get replaced by the rule when encountered
// This keeps repeating until the maximum number of iterations is reached
// You need one rule entry per variable used
rules["A"] = "BBB-";
rules["B"] = "+A-----------------------A++++++++++++++++";
// The commands:
// "L nn" means draw a line of length nn, e.g. L90 means draw a line 90 pixels long
// "M nn" means move nn pixels forward, e.g. M90 means move the current cursor 90 pixels forward
// "R nn" at the end of the command means add +/- nn% random noise to the length
commands["A"] = "L " + F;
start = "A";
make_path(rules, commands, start);
/* EOF */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment