summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuval Adam <yuv.adm@gmail.com>2012-05-18 11:04:06 +0300
committerYuval Adam <yuv.adm@gmail.com>2012-05-18 11:04:06 +0300
commitc900d290a3d86a4486ac2a8790de0b89b914c47d (patch)
treecb6d7542e07741fd0ad9eb491a2eeed05ecc2ae9
parent3c3aabf0522eed2cf1fdbb4a934606deca091040 (diff)
initial lsys.js import
-rw-r--r--lsys.js143
1 files changed, 143 insertions, 0 deletions
diff --git a/lsys.js b/lsys.js
new file mode 100644
index 0000000..de94df3
--- /dev/null
+++ b/lsys.js
@@ -0,0 +1,143 @@
+// L-System as defined in
+// http://en.wikipedia.org/wiki/L-system
+
+// Example usage:
+// lsys = LSystem('F', { 'F' : 'F-F+FF' });
+// tree = lsys.iterate(2)
+
+function LSystem(axiom, rules) {
+ this.axiom = axiom;
+ this.rules = rules;
+ this.tree = axiom;
+
+ this.iterate = function(n) {
+ for (var i=0; i<n; i++) {
+ this.tree = this.tree.replace(/\w/g, function(c) {
+ return rules[c] || c;
+ });
+ }
+ return this.tree;
+ };
+
+ this.draw = function(alpha) {
+ if (alpha === undefined)
+ alpha = 90 * (Math.PI / 180);
+
+ var coords = [];
+ var stack = [];
+ var geometry = [[0,0,0]];
+
+ var x = 0, y = 0, z = 0; // cartesian coordinates
+ var nx = 0, ny = 1, nz = 0; // next step delta
+ var H = 0, L = 0, U = 0; // headings on 3 axes
+ var RUu = false, RLu = false, RHu = false;
+
+ for (var i=0; i<this.tree.length; i++) {
+ var c = this.tree.charAt(i);
+ switch(c) {
+ case '+':
+ U += alpha;
+ RUu = true;
+ break;
+ case '-':
+ U -= alpha;
+ RUu = true;
+ break;
+
+ case '&':
+ L += alpha;
+ RLu = true;
+ break;
+ case '^':
+ L -= alpha;
+ RLu = true;
+ break;
+
+ case '<':
+ H += alpha;
+ RHu = true;
+ break;
+ case '>':
+ H -= alpha;
+ RHu = true;
+ break;
+
+ case '|':
+ U += Math.PI / 2;
+ RUu = true;
+ break;
+ // push and pop branch
+ case '[':
+ stack.push(x, y, z, H, L, U, geometry);
+ geometry = [[x,y,z]];
+ break;
+ case ']':
+ coords.push(geometry);
+ geometry = stack.pop();
+ U = stack.pop();
+ L = stack.pop();
+ H = stack.pop();
+ z = stack.pop();
+ y = stack.pop();
+ x = stack.pop();
+ break;
+ // forward draw
+ case 'F':
+ nx = 0, ny = 1, nz = 0;
+ nc = this.tree.charAt(i+1);
+
+ if (RUu) {
+ var tx = (nx * Math.cos(U)) - (ny * Math.sin(U));
+ var ty = (nx * Math.sin(U)) + (ny * Math.cos(U));
+ nx = tx;
+ ny = ty;
+
+ if (nc != 'F')
+ RUu = false;
+ }
+
+ if (RLu) {
+ var tx = (nx * Math.cos(L)) + (nz * Math.sin(L));
+ var tz = -(nx * Math.sin(L)) + (nz * Math.cos(L));
+ nx = tx;
+ nz = tz;
+
+ if (nc != 'F')
+ RLu = false;
+ }
+
+ if (RHu) {
+ var ty = (ny * Math.cos(H)) + (nz * Math.sin(H));
+ var tz = -(ny * Math.sin(H)) + (nz * Math.cos(H));
+ ny = ty;
+ nz = tz;
+
+ if (nc != 'F')
+ RHu = false;
+ }
+
+ x += nx;
+ y += ny;
+ z += nz;
+
+ geometry.push([x,y,z]);
+ break;
+ }
+ }
+
+ coords.push(geometry);
+ return coords;
+ };
+
+ this.reset = function() {
+ this.tree = axiom;
+ return this.tree;
+ };
+
+ this.debug = function() {
+ console.log('Axiom: ' + this.axiom);
+ console.log('Rules: ' + this.rules);
+ console.log('Tree: ' + this.tree);
+ };
+
+}