Skip to content

Instantly share code, notes, and snippets.

@roundrobin
Created January 4, 2013 21:00
Show Gist options
  • Save roundrobin/4455971 to your computer and use it in GitHub Desktop.
Save roundrobin/4455971 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},"params.json":{"default":true,"vim":false,"emacs":false,"fontSize":12}},"tab":"edit","display_percent":0.4970692410574826,"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")
var x_start = tributary.params.x_start;
var y_start = tributary.params.y_start;
// variables
var bend = 151.24, // angle to twist (degrees)
i_max = 8, // limit, warning 10 is probably an upperlimit
i_user = Math.abs(Math.floor(5)), // scrub between 1 and upperlimit for recursion levels
iterations = Math.min(i_max, i_user), // number of rewrites (recursion levels in grammar)
F = tributary.params.arm_length/(Math.pow(1.62, 4)*iterations), // arm distance
angle_offset = to_rad(bend), // angle as radian
angle_rad = 0, // the current angle for drawing
// x_start = 301, // drawing start x
// y_start = 238, // 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"] = "CBDCBDBB"
rules["B"] = "AAAACAAAAACAAAAD"
rules["C"] = "----------"
rules["D"] = "++++++++++"
// 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);
var drag = d3.behavior.drag()
.on("drag", function(d) {
var dx = d3.event.dx;
var dy = d3.event.dy;
tributary.params.x_start += dx;
tributary.params.y_start += dy;
updateParams();
})
var zoom = d3.behavior.zoom()
.on("zoom", function(d) {
tributary.params.arm_length *= d3.event.scale;
updateParams();
})
var display = d3.select("#display")
.call(drag)
.call(zoom);
//enable interaction to save state
function updateParams() {
var context = _.find(tributary.__config__.contexts, function(d) {
return d.model.get("filename") === "params.json";
});
context.editor.cm.setValue(JSON.stringify(tributary.params));
}
/* EOF */
{"x_start":512,"y_start":458,"arm_length":434.54344728137727}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment