var app = new Vue({ el: '#lSystemsApp', data: { V: "", P: "", E: "+-[]|f", A: "", n: 4, alpha: 45.0, startAngle: 0.0, angleOffset: 90.0, out: "", log: "", xoffsetUI: 0, yoffsetUI: 0, zoomUI: 1, startTime: null, endTime: null, durationOut: "", showCanvasDebug: false, ctx: null, autoGen: true, boxDimensionValue: 0, occupiedBoxes : 0, allBoxes : 0, gridSize: 0.05, gridCheckBox: false, audiopreter: null, boxDimCheckBox: false, showPoints: false, lsystem: null, turtle: null, }, created: function () { //this.setLStarTemplate(); // --> Default // Disable AutoGenerate inside the constructor // to avoid Canvas Context Reference Errors // This is maybe caused by the execution order of the browser var temp = this.autoGen; this.autoGen = false; this.setKochSnowflakeTemplate(); this.autoGen = temp; }, methods: { autoGenerate: function () { if (this.autoGen) this.generate(); }, generate: function () { this.startTime = performance.now(); this.clearCanvas(); this.lsystem = new LSystem(); var output = ""; this.log = ""; try { this.lsystem.V = this.V; this.lsystem.E = this.E; this.lsystem.Axiom = this.A; this.lsystem.P = this.P; this.lsystem.n = this.n; this.lsystem.generate() this.out = this.lsystem.out; } catch (error) { this.log = "
[LSystem]: " + error + "
"; return; } if (this.boxDimCheckBox) this.calcBoxDimension(this.lsystem); else { this.turtle = new Turtle(this.ctx.canvas.width, this.ctx.canvas.height, parseFloat(this.alpha), Number(this.n), 100.0, this.showCanvasDebug, this.showPoints); this.turtle.angleOffset = parseFloat(this.angleOffset) + parseFloat(this.startAngle); this.turtle.computeWord(this.lsystem.out); this.ctx.drawImage(this.turtle.finalCanvas, 0, 0); } if (this.gridCheckBox) this.drawGrid(); this.endTime = performance.now(); var duration = (this.endTime - this.startTime) / 1000.0; this.durationOut = "Rendered within " + duration + "s" }, drawGrid: function () { var localGridSize = Number((this.gridSize * this.ctx.canvas.width)); this.ctx.save(); for (let i = 0; i < this.ctx.canvas.width; i += localGridSize) { this.ctx.beginPath(); // Horizontal Lines if (Number(i % (localGridSize * 4)) == 0) this.ctx.lineWidth = 0.25; else this.ctx.lineWidth = 0.1; this.ctx.moveTo(0, i); this.ctx.lineTo(this.ctx.canvas.width, i); // Vertical Lines if (i % (localGridSize * 2) == 0) this.ctx.lineWidth = 0.25; else this.ctx.lineWidth = 0.1; this.ctx.moveTo(i, 0); this.ctx.lineTo(i, this.ctx.canvas.height); this.ctx.stroke(); this.ctx.closePath(); } this.ctx.restore(); }, calcBoxDimension: function (lsystem = false) { this.clearCanvas(); if (lsystem === false) { lsystem = new LSystem(); lsystem.V = this.V; lsystem.E = this.E; lsystem.Axiom = this.A; lsystem.P = this.P; lsystem.n = this.n; lsystem.generate(); } var width = this.ctx.canvas.width; var height = this.ctx.canvas.height; var resolution = width * height; var t = new Turtle(this.ctx.canvas.width, this.ctx.canvas.height, parseFloat(this.alpha), Number(this.n), 100.0); t.angleOffset = parseFloat(this.angleOffset) + parseFloat(this.startAngle); t.computeWord(lsystem.out); this.out = lsystem.out; var boxDim = new BoxDimension(t.finalContext,Number((this.gridSize * this.ctx.canvas.width)), parseFloat(this.gridSize), this.gridCheckBox); boxDim.calculate(); this.ctx.drawImage(boxDim.boxCanvas, 0, 0); this.ctx.drawImage(t.finalContext.canvas, 0, 0); this.occupiedBoxes = boxDim.occupied; this.allBoxes = boxDim.totalBoxCount; this.boxDimensionValue = boxDim.dimension; }, // Clear-Function for L-System and Turtle clear: function () { this.V = ""; this.P = ""; this.E = "+-[]|f"; this.A = ""; }, clearCanvas: function () { this.ctx.save(); this.ctx.setTransform(1, 0, 0, 1, 0, 0); this.ctx.fillStyle = "#FFF" this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height); this.ctx.restore(); }, // L-System Templates setHoneycombTemplate: function () { this.V = "F"; this.P = "F=F++F+F+F+F"; this.A = "F|F|F"; this.alpha = 60 this.n = 5; this.startAngle = 0; this.out = ""; this.log = ""; this.autoGenerate(); }, setCoastlineTemplate: function () { this.V = "F"; this.P = "F=F+F--[--F]+F"; this.A = "F|F"; this.alpha = 90 this.n = 6; this.startAngle = 0; this.out = ""; this.log = ""; this.autoGenerate(); }, setCloudTemplate: function () { this.V = "F"; this.P = "F=F+FF-"; this.A = "F|F"; this.alpha = 90 this.n = 6; this.startAngle = 0; this.out = ""; this.log = ""; this.autoGenerate(); }, setLichterketteTemplate: function () { this.V = "FG"; this.P = "F=F+F-G-F-\nG=GFG"; this.A = "F|F"; this.alpha = 212 this.n = 6; this.startAngle = 0.0; this.out = ""; this.log = ""; this.autoGenerate(); }, setLStarTemplate: function () { this.V = "AF"; this.P = "A=AAffff--f--fff++ff--f--fff+AA-"; this.A = "FA"; this.alpha = 45.0; this.startAngle = 0.0; this.n = 3; this.out = ""; this.log = ""; this.autoGenerate(); }, setKochTemplate: function () { this.V = "F"; this.P = "F=F+F--F+F"; this.A = "F"; this.alpha = 60.0; this.startAngle = 0.0; this.n = 3; this.out = ""; this.log = ""; this.autoGenerate(); }, setKochSnowflakeTemplate: function () { this.V = "F"; this.P = "F=F+F--F+F"; this.A = "F--F--F"; this.alpha = 60.0; this.startAngle = 0.0; this.n = 3; this.out = ""; this.log = ""; this.autoGenerate(); }, setDragonCurveTemplate: function () { this.V = "FG"; this.P = "F=F+Gf+\nG=-fF-G"; this.A = "fF"; this.alpha = 90.0; this.startAngle = 0.0; this.n = 3; this.out = ""; this.log = ""; this.autoGenerate(); }, setHilbertTemplate: function () { this.V = "AB"; this.P = "A=-Bf+AfA+fB-\nB=+Af-BfB-fA+"; this.A = "B"; this.alpha = 90.0; this.startAngle = 0.0; this.n = 3; this.out = ""; this.log = ""; this.autoGenerate(); }, setSierpinskiTriangleTemplate: function () { this.V = "FG"; this.P = "F=G-F-G\nG=F+G+F"; this.A = "F"; this.alpha = 60.0; this.startAngle = 0.0; this.n = 4; this.out = ""; this.log = ""; this.autoGenerate(); }, setNotSierpinskiTemplate: function () { this.V = "F"; this.P = "F=F[-F][+F]F"; this.A = "F"; this.alpha = 120.0; this.startAngle = 270.0; this.n = 8; this.out = ""; this.log = ""; this.autoGenerate(); }, setPlantTemplate: function () { this.V = "FG"; this.P = "G=F+[[G]-G]-F[-FG]+F\nF=FF"; this.A = "G"; this.alpha = 25.0; this.startAngle = 270.0; this.n = 3; this.out = ""; this.log = ""; this.autoGenerate(); }, setLecyCTemplate: function () { this.V = "F"; this.P = "F=+F--F+"; this.A = "F"; this.alpha = 45.0; this.startAngle = 180.0; this.n = 10; this.out = ""; this.log = ""; this.autoGenerate(); }, setGosperTemplate: function () { this.V = "FG"; this.P = "F = F+G++G-F--FF-G+\nG = -F+GG++G+F--F-G"; this.A = "F"; this.alpha = 60.0; this.startAngle = 0.0; this.n = 5; this.out = ""; this.log = ""; this.autoGenerate(); }, setOccultTemplate: function () { this.V = "ABC"; this.P = "A=fA++B++Af\nB=fB--C--Bf\nC=f+f"; this.A = "A"; this.alpha = 60.0; this.startAngle = 0.0; this.n = 8; this.out = ""; this.log = ""; this.autoGenerate(); }, setRobotTemplate: function () { this.V = "AB"; this.P = "A=fA+B+Af\nB=fB-f-Bf"; this.A = "A"; this.alpha = 87.0; this.startAngle = 18.0; this.n = 6; this.out = ""; this.log = ""; this.autoGenerate(); }, setRandom: function (){ var maxVars = 10; var maxRuleChars = 10; var maxIterations = 4; var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; var alpha = Math.floor((Math.random()*360.0)); var n = Math.floor(Math.random()*(maxIterations-1))+1; var V = ""; var P = ""; var charPool = ""; var A = ""; var valid = false; while(!valid) { var V = ""; var P = ""; var charPool = ""; var A = ""; var varCount = Math.floor(Math.random() * maxVars); while(V.length< varCount) { var candidate = characters.charAt(Math.floor(Math.random()*characters.length)); if(V.indexOf(candidate) != -1) continue; V += candidate; } if(V.length == 0)continue; charPool = V + '+-f'; for(var i=0;i"; return; } this.audiopreter = new Audiopreter(); this.audiopreter.interpretWord(l.out); }, stopFractal: function () { if (this.audiopreter != null) this.audiopreter.stop(); }, exportSVG: function() { /* * Transform points [(-infinity,-infinity),(infinity, infinity)] * to svg space, which is [(0,0),(xmax,ymax)]. This will be accomplished by * translating all points by the minimum x/y or zero if the minimum is positive value. * This ensures that no negative points are left. * * Also transform the line to a svg-line-primitive. A polygone can't be used * while trees (e.g. plant) are not convex hulls and therefore no polygons. */ xMin = this.turtle.bounds.xMin; yMin = this.turtle.bounds.yMin; lines = this.turtle.lines.map(function(line){ startPoint = [ line[0][0] + Math.abs(xMin), line[0][1] + Math.abs(yMin) ]; endPoint = [ line[1][0] + Math.abs(xMin), line[1][1] + Math.abs(yMin) ]; return `` }); svg = ` ${lines.join("\n")} ` svgBlob = new Blob([svg], {type: "image/svg+xml"}); /* Create new link to simulate download */ link = document.createElement('a'); link.download = "out.svg" link.href = window.URL.createObjectURL(svgBlob); link.click(); window.URL.revokeObjectURL(link.href); } }, filters : { round2f : function(value){ if(!value) return 0; return Math.round(Number(value)*100.0)/100.0; } } });