Skip to content

Instantly share code, notes, and snippets.

/_.md

Created January 2, 2013 02:37
Show Gist options
  • Save anonymous/4431707 to your computer and use it in GitHub Desktop.
Save anonymous/4431707 to your computer and use it in GitHub Desktop.
path_from_function_2
{"description":"path_from_function_2","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.5636916586786652,"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}
// variables
var bend = 120, // angle to twist (degrees)
i_max = 10, // limit, warning 10 is probably an upperlimit
i_user = Math.abs(Math.floor(10)), // scrub between 1 and upperlimit for recursion levels
iterations = Math.min(i_max, i_user), // number of rewrites (recursion levels in grammar)
F = 1040/(Math.pow(1.5,iterations)), // arm distance
angle_offset = to_rad(bend), // angle as radian
angle_rad = 0, // the current angle for drawing
x_start = 154, // drawing start x
y_start = 372, // 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 = '#000AFF';
tributary.ctx.lineWidth = 2;
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) command_from_rad("L " + F, 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["X"] = "X+YF";
rules["Y"] = "FX-Y";
// The commands:
// "Lnn" means draw a line of length nn, e.g. L90 means draw a line 90 pixels long
// "Mnn" means move nn pixels forward, e.g. M90 means move the current cursor 90 pixels forward
// "RAnn" at the end of the command means add
commands["F"] = "L " + F + " R " + 20;
start = "FY";
make_path(rules, commands, start);
/* EOF */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment