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 = `
`
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;
}
}
});