Skip to content

Commit

Permalink
Merge branch 'lindsvg-1.2.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
Amphiluke committed Mar 1, 2020
2 parents 161d3ca + 84a5d14 commit 79e61a1
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 78 deletions.
50 changes: 28 additions & 22 deletions dist/lindsvg.esm.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*!
lindsvg v1.2.0
lindsvg v1.2.1
https://amphiluke.github.io/l-systems/
(c) 2020 Amphiluke
*/
Expand Down Expand Up @@ -146,9 +146,9 @@ function generate(lsParams) {
}

let proto = {
translate() {
this.x += this.step * Math.cos(this.alpha);
this.y += this.step * Math.sin(this.alpha);
translate(stepCount = 1) {
this.x += stepCount * this.step * Math.cos(this.alpha);
this.y += stepCount * this.step * Math.sin(this.alpha);
this.minX = Math.min(this.minX, this.x);
this.maxX = Math.max(this.maxX, this.x);
this.minY = Math.min(this.minY, this.y);
Expand All @@ -157,11 +157,15 @@ let proto = {
rotate(factor) {
this.alpha += factor * this.theta;
},
pushStack() {
this.stack.push({x: this.x, y: this.y, alpha: this.alpha});
pushStack(repeatCount = 1) {
for (; repeatCount > 0; repeatCount--) {
this.stack.push({x: this.x, y: this.y, alpha: this.alpha});
}
},
popStack() {
({x: this.x, y: this.y, alpha: this.alpha} = this.stack.pop());
popStack(repeatCount) {
for (; repeatCount > 0; repeatCount--) {
({x: this.x, y: this.y, alpha: this.alpha} = this.stack.pop());
}
},
getDrawingRect() {
let minX = Math.floor(this.minX);
Expand All @@ -185,11 +189,12 @@ function createTurtle({x, y, step, alpha, theta}) {

/**
* Remove all letters which don’t affect the drawing process from the codeword
* and split it into “tokens” for the further processing
* @param {String} codeword - L-system code
* @return {String}
* @return {Array<String>}
*/
function cleanCodeword(codeword) {
return codeword.replace(/[^FB[\]+-]/g, "");
function tokenizeCodeword(codeword) {
return codeword.match(/([FB[\]+-])\1*/g);
}

function formatCoordinates(x, y) {
Expand All @@ -199,21 +204,22 @@ function formatCoordinates(x, y) {

/**
* Get the value of the d attribute
* @param {String} codeword - Clean code
* @param {Array<String>} tokens - Tokenized codeword
* @param {Object} turtle - Turtle object to work with
* @return {String}
*/
function getPathData(codeword, turtle) {
function getPathData(tokens, turtle) {
let prevCommand; // used to avoid unnecessary repeating of the commands L and M
return [...codeword].reduce((accumulator, symbol) => {
switch (symbol) {
return tokens.reduce((accumulator, token) => {
let tokenLength = token.length;
switch (token[0]) {
case "F":
turtle.translate();
turtle.translate(tokenLength);
accumulator += (prevCommand === "L" ? " " : "L") + formatCoordinates(turtle.x, turtle.y);
prevCommand = "L";
break;
case "B":
turtle.translate();
turtle.translate(tokenLength);
if (prevCommand === "M") {
// As the spec states, “If a moveto is followed by multiple pairs of coordinates,
// the subsequent pairs are treated as implicit lineto commands”.
Expand All @@ -224,16 +230,16 @@ function getPathData(codeword, turtle) {
prevCommand = "M";
break;
case "+":
turtle.rotate(1);
turtle.rotate(tokenLength);
break;
case "-":
turtle.rotate(-1);
turtle.rotate(-tokenLength);
break;
case "[":
turtle.pushStack();
turtle.pushStack(tokenLength);
break;
case "]":
turtle.popStack();
turtle.popStack(tokenLength);
accumulator += `M${formatCoordinates(turtle.x, turtle.y)}`;
prevCommand = "M";
break;
Expand All @@ -250,7 +256,7 @@ function getPathData(codeword, turtle) {
function getSVGData(lsParams) {
let codeword = generate(lsParams);
let turtle = createTurtle({x: 0, y: 0, ...lsParams});
let pathData = getPathData(cleanCodeword(codeword), turtle);
let pathData = getPathData(tokenizeCodeword(codeword), turtle);
return {
pathData,
...turtle.getDrawingRect()
Expand Down
4 changes: 2 additions & 2 deletions dist/lindsvg.esm.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 28 additions & 22 deletions dist/lindsvg.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*!
lindsvg v1.2.0
lindsvg v1.2.1
https://amphiluke.github.io/l-systems/
(c) 2020 Amphiluke
*/
Expand Down Expand Up @@ -152,9 +152,9 @@ https://amphiluke.github.io/l-systems/
}

let proto = {
translate() {
this.x += this.step * Math.cos(this.alpha);
this.y += this.step * Math.sin(this.alpha);
translate(stepCount = 1) {
this.x += stepCount * this.step * Math.cos(this.alpha);
this.y += stepCount * this.step * Math.sin(this.alpha);
this.minX = Math.min(this.minX, this.x);
this.maxX = Math.max(this.maxX, this.x);
this.minY = Math.min(this.minY, this.y);
Expand All @@ -163,11 +163,15 @@ https://amphiluke.github.io/l-systems/
rotate(factor) {
this.alpha += factor * this.theta;
},
pushStack() {
this.stack.push({x: this.x, y: this.y, alpha: this.alpha});
pushStack(repeatCount = 1) {
for (; repeatCount > 0; repeatCount--) {
this.stack.push({x: this.x, y: this.y, alpha: this.alpha});
}
},
popStack() {
({x: this.x, y: this.y, alpha: this.alpha} = this.stack.pop());
popStack(repeatCount) {
for (; repeatCount > 0; repeatCount--) {
({x: this.x, y: this.y, alpha: this.alpha} = this.stack.pop());
}
},
getDrawingRect() {
let minX = Math.floor(this.minX);
Expand All @@ -191,11 +195,12 @@ https://amphiluke.github.io/l-systems/

/**
* Remove all letters which don’t affect the drawing process from the codeword
* and split it into “tokens” for the further processing
* @param {String} codeword - L-system code
* @return {String}
* @return {Array<String>}
*/
function cleanCodeword(codeword) {
return codeword.replace(/[^FB[\]+-]/g, "");
function tokenizeCodeword(codeword) {
return codeword.match(/([FB[\]+-])\1*/g);
}

function formatCoordinates(x, y) {
Expand All @@ -205,21 +210,22 @@ https://amphiluke.github.io/l-systems/

/**
* Get the value of the d attribute
* @param {String} codeword - Clean code
* @param {Array<String>} tokens - Tokenized codeword
* @param {Object} turtle - Turtle object to work with
* @return {String}
*/
function getPathData(codeword, turtle) {
function getPathData(tokens, turtle) {
let prevCommand; // used to avoid unnecessary repeating of the commands L and M
return [...codeword].reduce((accumulator, symbol) => {
switch (symbol) {
return tokens.reduce((accumulator, token) => {
let tokenLength = token.length;
switch (token[0]) {
case "F":
turtle.translate();
turtle.translate(tokenLength);
accumulator += (prevCommand === "L" ? " " : "L") + formatCoordinates(turtle.x, turtle.y);
prevCommand = "L";
break;
case "B":
turtle.translate();
turtle.translate(tokenLength);
if (prevCommand === "M") {
// As the spec states, “If a moveto is followed by multiple pairs of coordinates,
// the subsequent pairs are treated as implicit lineto commands”.
Expand All @@ -230,16 +236,16 @@ https://amphiluke.github.io/l-systems/
prevCommand = "M";
break;
case "+":
turtle.rotate(1);
turtle.rotate(tokenLength);
break;
case "-":
turtle.rotate(-1);
turtle.rotate(-tokenLength);
break;
case "[":
turtle.pushStack();
turtle.pushStack(tokenLength);
break;
case "]":
turtle.popStack();
turtle.popStack(tokenLength);
accumulator += `M${formatCoordinates(turtle.x, turtle.y)}`;
prevCommand = "M";
break;
Expand All @@ -256,7 +262,7 @@ https://amphiluke.github.io/l-systems/
function getSVGData(lsParams) {
let codeword = generate(lsParams);
let turtle = createTurtle({x: 0, y: 0, ...lsParams});
let pathData = getPathData(cleanCodeword(codeword), turtle);
let pathData = getPathData(tokenizeCodeword(codeword), turtle);
return {
pathData,
...turtle.getDrawingRect()
Expand Down
Loading

0 comments on commit 79e61a1

Please sign in to comment.