summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuval Adam <yuv.adm@gmail.com>2011-10-27 11:59:22 +0200
committerYuval Adam <yuv.adm@gmail.com>2011-10-27 11:59:22 +0200
commite263daa376ed8b6be58d3c7d311e4b896666d8fc (patch)
tree5b908017b3bbcfaebc7b0a5b373e58972474ef20
parentce999c4277bafa656af28bf62c173837787fe9e9 (diff)
added lsys
-rw-r--r--lsys/README.md3
-rw-r--r--lsys/app.js60
-rw-r--r--lsys/index.html50
-rw-r--r--lsys/lsystem.js172
4 files changed, 285 insertions, 0 deletions
diff --git a/lsys/README.md b/lsys/README.md
new file mode 100644
index 0000000..b8b2535
--- /dev/null
+++ b/lsys/README.md
@@ -0,0 +1,3 @@
+## L-system generator
+
+Plug in values and see what you get. You can click "Save Image" to generate a PNG for downloading (at least in Chrome -- I haven't tested it in other browsers).
diff --git a/lsys/app.js b/lsys/app.js
new file mode 100644
index 0000000..3c5e696
--- /dev/null
+++ b/lsys/app.js
@@ -0,0 +1,60 @@
+/* Based on http://www.robotacid.com/PBeta/LSystem/index.html */
+
+var lsystem = new LSystem();
+
+var width = 1200;
+var height = 600;
+
+var HALF_PI = 3.141592 / 2;
+
+function setup(axiom, ruleset, iterations) {
+ lsystem = new LSystem(axiom, ruleset);
+ lsystem.iterate(iterations);
+}
+
+function saveImage() {
+ console.log("save");
+ window.open(c.toDataURL());
+}
+
+function draw(x, y, axiom, ruleset, iterations, angle, zoom, drawtype) {
+ a.fillStyle = "#fff";
+ a.fillRect(0, 0, width, height);
+
+ var angle_radians = parseFloat(angle) * (Math.PI / 360);
+
+ lsystem.draw(x, y, zoom, angle_radians, drawtype);
+
+ a.fillStyle = "#666";
+ a.fillRect(0, 0, width, 20);
+ a.fillStyle = "#fff";
+ a.font = "bold 10px 'Lucida Grande', Helvetica";
+
+ var str = "axiom: " + axiom + " ";
+ str += "ruleset: " + ruleset + " ";
+ str += "angle: " + angle + "ยบ ";
+ str += "iterations: " + iterations + " ";
+ str += "zoom: " + zoom + " ";
+ str += "x: " + x + " ";
+ str += "y: " + y + " ";
+ str += "drawtype: " + drawtype;
+ a.fillText(str, 5, 13);
+}
+
+function generate() {
+ var axiom = document.getElementById("axiom").value;
+ var ruleset = document.getElementById("ruleset").value;
+ var angle = document.getElementById("angle").value;
+ var iterations = document.getElementById("iterations").value;
+ var zoom = document.getElementById("zoom").value;
+
+ var x = document.getElementById("x").value;
+ var y = document.getElementById("y").value;
+
+ var drawtype = document.getElementById("drawtype").value;
+
+ setup(axiom, ruleset, iterations);
+ draw(x, y, axiom, ruleset, iterations, angle, zoom, drawtype);
+}
+
+generate();
diff --git a/lsys/index.html b/lsys/index.html
new file mode 100644
index 0000000..7197b7f
--- /dev/null
+++ b/lsys/index.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>L-System test</title>
+ <meta charset="utf-8" />
+ <style type="text/css" media="screen">
+ body { margin: 0; padding: 15px; border-top: solid 10px #000; }
+ canvas { border: solid 1px #999; }
+ #controls { font-family: "Lucida Grande", Helvetica, Arial, sans-serif; font-size: 11px; margin-bottom: 10px; }
+ #controls input[type="text"] { border: solid 1px #ccc; font-weight: bold; padding: 2px; font-size: 12px; width: 35px; margin-right: 10px; }
+ #controls input#axiom { width: 75px; }
+ #controls input#ruleset { width: 200px; }
+ </style>
+ </head>
+ <body>
+ <div id="controls">
+ <form action="" onsubmit="generate(); return false;">
+ Axiom: <input type="text" id="axiom" name="axiom" value="F" />
+ Ruleset: <input type="text" id="ruleset" name="ruleset" value="F-F+FF-F-F+F" />
+ Angle: <input type="text" id="angle" name="angle" value="200" />
+ Iterations: <input type="text" id="iterations" name="iterations" value="4" />
+ Zoom: <input type="text" id="zoom" name="zoom" value="10" />
+ X: <input type="text" id="x" name="x" value="600" />
+ Y: <input type="text" id="y" name="y" value="300" />
+
+ <select id="drawtype" name="drawtype" onchange="generate()">
+ <option value="line">Line</option>
+ <option value="hollow_circle">Hollow Circle</option>
+ <option value="filled_circle">Filled Circle</option>
+ <option value="small_circles">Small Circles</option>
+ <option value="more_circles">More Circles</option>
+ <option value="faint">Faint</option>
+ <option value="triangles">Triangles</option>
+ <option value="hatch">Hatch</option>
+ </select>
+
+ <input id="generateButton" type="submit" value="Generate" />
+ <input id="saveButton" type="button" value="Download" onclick="saveImage()" />
+ </form>
+ </div>
+ <canvas width="1200" height="600"></canvas>
+
+ <script>
+ var c = document.getElementsByTagName('canvas')[0];
+ var a = c.getContext('2d');
+ </script>
+ <script type="text/javascript" charset="utf-8" src="lsystem.js"></script>
+ <script type="text/javascript" charset="utf-8" src="app.js"></script>
+ </body>
+</html>
diff --git a/lsys/lsystem.js b/lsys/lsystem.js
new file mode 100644
index 0000000..c3896e5
--- /dev/null
+++ b/lsys/lsystem.js
@@ -0,0 +1,172 @@
+/* LSystem */
+
+function LSystem(axiom, ruleset) {
+ this.alphabet = ['F', '+', '-', '[', ']'];
+ this.axiom = axiom;
+ this.rule = ["", "+", "-", "[", "]"];
+ this.tree = "";
+
+ this.rule[0] = ruleset;
+
+ this.draw = function(x, y, zoom, angle, drawtype) {
+ a.fillStyle = "#000";
+ a.strokeStyle = "#000";
+
+ a.save();
+ a.translate(x, y);
+
+ var i;
+
+ for (i=0; i<this.tree.length; i++) {
+ switch (this.tree.charAt(i)) {
+ case 'F':
+ switch (drawtype) {
+ case 'line':
+ a.beginPath();
+ a.moveTo(0, 0);
+ a.lineTo(zoom, 0);
+ a.closePath();
+ a.stroke();
+ break;
+ case 'hollow_circle':
+ a.beginPath();
+ a.arc(0, 0, zoom / 10, 0, Math.PI*2, true);
+ a.closePath();
+ a.stroke();
+ break;
+ case 'filled_circle':
+ a.beginPath();
+ a.arc(0, 0, zoom / 10, 0, Math.PI*2, true);
+ a.closePath();
+ a.fill();
+ break;
+ case 'faint':
+ a.fillStyle = "rgba(0, 0, 0, " + (i / this.tree.length) + ")";
+ a.beginPath();
+ a.moveTo(Math.random() - .5, Math.random() - .5);
+ a.lineTo(Math.sin(zoom) + (zoom / 2), Math.random() - .5);
+ a.lineTo(zoom, 0);
+ a.closePath();
+ a.fill();
+ break;
+ case 'small_circles':
+ a.fillStyle = "rgba(0, 0, 0, " + (i / this.tree.length) + 0.2 + ")";
+ a.beginPath();
+ a.moveTo(Math.random() - .5, Math.random() - .5);
+ a.lineTo(Math.sin(zoom) + (zoom / 2), Math.random() - .5);
+ a.arc(Math.sin(zoom) + (zoom / 2), Math.random() - .5, zoom / 5, 0, Math.PI*2, true);
+ a.lineTo(zoom, 0);
+ a.closePath();
+ a.fill();
+ break;
+ case 'triangles':
+ a.fillStyle = "rgba(0, 0, 0, " + (i / this.tree.length) + ")";
+ a.beginPath();
+
+ var dist = zoom / 2;
+ var halfdist = dist / 2;
+ a.moveTo(0, dist);
+ a.lineTo(halfdist, halfdist);
+ a.lineTo(dist, 0);
+ a.lineTo(halfdist, -halfdist);
+ a.lineTo(0, -dist);
+ a.closePath();
+ a.fill();
+ break;
+ case 'more_circles':
+ a.fillStyle = "rgba(0, 0, 0, " + Math.random() + ")";
+ a.beginPath();
+ a.arc(Math.random() + .5, Math.random() - .5, (i / this.tree.length) * 5, 0, Math.PI*2, true);
+ a.closePath();
+ a.fill();
+
+ a.fillStyle = "rgba(0, 0, 0, " + Math.random() + ")";
+ a.beginPath();
+ a.arc(Math.random() - .5, Math.random() + .5, (i / this.tree.length) * 3, 0, Math.PI*2, true);
+ a.closePath();
+ a.fill();
+
+ break;
+ case 'hatch':
+ var red = Math.random() * 255;
+ var green = Math.random() * 255;
+ var blue = Math.random() * 255;
+ a.strokeStyle = "rgba(" + red + ", " + green + ", " + blue + ", " + (i / this.tree.length) + ")";
+ a.beginPath();
+
+ var dist = zoom / 2;
+ a.moveTo(-dist, -dist);
+ a.lineTo(dist, -dist);
+ a.moveTo(-dist, 0);
+ a.lineTo(dist, 0);
+ a.moveTo(-dist, dist);
+ a.lineTo(dist, dist);
+ a.closePath();
+ a.stroke();
+ break;
+ }
+ a.translate(zoom, 0);
+ break;
+
+ case '+':
+ a.rotate(angle);
+ break;
+
+ case '-':
+ a.rotate(-angle);
+ break;
+
+ case '[':
+ a.save();
+ break;
+
+ case ']':
+ a.restore();
+ break;
+ }
+ }
+ a.restore();
+ }
+
+ this.iterate = function(max_length) {
+ this.tree = this.axiom;
+ var rule_length = [];
+ var i;
+
+ for (i=0; i<this.alphabet.length; i++) {
+ rule_length[i] = this.rule[i].length;
+ }
+
+ for (i=0; i<max_length; i++) {
+ var new_length = 0;
+ var j;
+
+ for (j=0; j<this.tree.length; j++) {
+ var c = this.tree.charAt(j);
+ var k;
+
+ for (k=0; k<this.alphabet.length; k++) {
+ if (c == this.alphabet[k]) {
+ new_length += rule_length[k];
+ break;
+ }
+ }
+ }
+
+ var new_tree = [];
+
+ for (j=0; j<this.tree.length; j++) {
+ var c = this.tree.charAt(j);
+ var k;
+
+ for (k=0; k<this.alphabet.length; k++) {
+ if (c == this.alphabet[k]) {
+ new_tree.push(this.rule[k]);
+ break;
+ }
+ }
+ }
+ this.tree = new_tree.join("");
+ }
+ }
+}