nylki / lindenmayer

Feature complete classic L-System library (branching, context sensitive, parametric) & multi-purpose modern L-System/LSystem implementation that can take javascript functions as productions. It is not opinionated about how you do visualisations.
MIT License
183 stars 14 forks source link

FR: Support (or error out) with string axioms if you have parametric productions #33

Open alfongj opened 3 years ago

nylki commented 3 years ago

Hi @alfongj! Could you add some more detail why you opened this issue, are you missing some features or documentation?

Assuming the latter, parametric L-Systems are in fact supported. As a starting point you may refer to the docs which have some details and examples regarding parametric L-System usage.

alfongj commented 3 years ago

Really? That's exciting. I couldn't make it work and saw:

So I thought it wasnt :)

I'm going to give it another try and resort back; maybe there's a bug on my code or I found a bug in the library

nylki commented 3 years ago

Good find! Both the broken link and that statement are outdated. Changed them. ;)

Parametric L-Systems as described in the docs and readme should work. You can also take a look at the unit tests to see some more working examples. Since the tests are run before a version is released, you can be sure that the test examles will work.

However note, that the classic syntax for parametric L-Systems as defined by Prusinkiewicz and Lindenmayer in 1990 will not work. This library does not try to replicate the exact functionality as described in the book, but offers a different, more JS-idiomatic approach to parametric L-Systems. So if you were looking to 1:1 reproduce the examples from the book, this won't be possible I am afraid. Symbols in L-Systems axioms and productions in this library are defined exclusively via JS objects (see docs + readme). However, I wouldn't see it as a disadvantages, since it gives you a lot flexibility and interoparabilty with your own code.

alfongj commented 3 years ago

I found the issue.

If you define a parametric's system axiom as a simple string (e.g. "X") and then have parametric productions, then it doesn't work -- "axiom" moving forward will always be a string and never store objects for parts produced on parametric productions.

I think the bug is on the function applyProductions()

The way to fix this is to pass an axiom with objects from the get go

alfongj commented 3 years ago
if (typeof newAxiom === 'string') {
          newAxiom += result;
        } else if (result instanceof Array) {
          // If result is an array, merge result into new axiom instead of pushing.
          newAxiom.push(...result);
        } else {
          newAxiom.push(result);
        }

Here you may want to either throw an error if typeof newAxiom === 'string' but results are objects, or add a branch that transforms the existing axiom into an object based representation and merge with the new results