I'm trying to draw fern pattern using lsystem, I found a formula on a website that says you get this:
http://www.home.aone.net.au/~byzantium/ferns/leaf34.gif
if you use this formula(s):
angle 8 axiom x a=n n=o o=p p=x b=e e=h h=j j=y x=F[+A(4)]Fy y=F[B(4)]Fx F=@1.18F@...1985...
(I separated rules with ; )
But the result I got doesn't match: http://img143.imageshack.us/img143/1948/fernmt4.png
Is this a bug in lsystem, or are these rules wrong, or am I using the effect wrong?
btw the image I got was made with order 34 as the website suggested, but it takes a long while till Inkscape calculates it (nearly 100000 nodes), I'd suggest a much lower order for testing ;)
Mihaela wrote:
if you use this formula(s):
angle 8 axiom x a=n n=o o=p p=x b=e e=h h=j j=y x=F[+A(4)]Fy y=F[B(4)]Fx F=@1.18F@...1985...
There are many slight variations on interpreting the characters in lsystem rules as drawing commands. I believe I've found an explanation of the variation you are using at:
http://spanky.triumf.ca/www/fractint/lsystem_type.html
The problem is that the rule language above and Inkscape's rule language differ. In Inkscapes rule language characters have the following meaning:
AF: draw a line of specified length GL: move forward specified length without drawing +: left turn : right turn : 180 degree turn [: remember current state ]: return to last remembered state All other characters are ignored.
The rule language implemented in Inkscape doesn't currently support the @ or @i commands for multiplying the line length. And in my quick search I didn't run across an explanation for (4).
If you'd like to try your hand at fixing these omission in Inkscape check out the source for this extension in lindenmayer.py:
http://inkscape.svn.sourceforge.net/viewvc/inkscape/inkscape/trunk/share/ext...
Aaron Spike
Aaron Spike wrote:
The rule language implemented in Inkscape doesn't currently support the @ or @i commands for multiplying the line length. And in my quick search I didn't run across an explanation for (4).
If you'd like to try your hand at fixing these omission in Inkscape check out the source for this extension in lindenmayer.py:
http://inkscape.svn.sourceforge.net/viewvc/inkscape/inkscape/trunk/share/ext...
Aaron Spike
I thought the lsystem syntax was unique, but I found different formulation for scaling on another website, does it matter which one is adopted in Inkscape?
Can you explain how you pull the formula through generations (order)? Where do I look; iterate or recurse?
I played with the script a bit and I was able to make every drawn step resize by an amount (every ABC...), but that isn't what I want. I want fractals, they apply the resize only after the whole object had gone through a substitution.
I was also able to make the resize apply after one run through the formula, but this way "resize generations" still alternate too fast, before the order is applied to the whole object.
What should I look into considering python for pulling out the number behind @ from the rules (I'm a total python newbie)?
Mihaela wrote:
I thought the lsystem syntax was unique, but I found different formulation for scaling on another website, does it matter which one is adopted in Inkscape?
It probably doesn't matter. Perhaps we should try to find out which syntax is more popular (and thus which has more examples on the web). Or if possible we could implement both. Can you summarize the different syntaxes you've found?
Can you explain how you pull the formula through generations (order)? Where do I look; iterate or recurse?
iterate() is the entrance point (called from effect()). recurse continues to call itself incrementing the order up from zero until the desired generation has been reached. recurse forms the pattern by replacing the rules in the string over and over. I'm sure this is a source of major inefficiency, so if someone has an idea for making it faster let me know.
I played with the script a bit and I was able to make every drawn step resize by an amount (every ABC...), but that isn't what I want. I want fractals, they apply the resize only after the whole object had gone through a substitution.
I was also able to make the resize apply after one run through the formula, but this way "resize generations" still alternate too fast, before the order is applied to the whole object.
What should I look into considering python for pulling out the number behind @ from the rules (I'm a total python newbie)?
I think we need to switch from iterated loop over the pattern string to a counted loop. Then when we see @ we know to advance until we've used all the possible numeric characters. This could even be done with a regular expression.
Aaron
Aaron Spike wrote:
Mihaela wrote:
I thought the lsystem syntax was unique, but I found different formulation for scaling on another website, does it matter which one is adopted in Inkscape?
It probably doesn't matter. Perhaps we should try to find out which syntax is more popular (and thus which has more examples on the web). Or if possible we could implement both. Can you summarize the different syntaxes you've found?
I haven't had time to go through all of them in detail but I think I found more than 2 different approaches. I plan to dive into python as soon as I get some free time, and then I'll look deeper into this also. Until then I'll stick to what's already there in your script ignoring everything else.
I think we need to switch from iterated loop over the pattern string to a counted loop. Then when we see @ we know to advance until we've used all the possible numeric characters. This could even be done with a regular expression.
Aaron
I don't have enough python knowledge to do it myself (yet), I think I've been able to come up with is an algorithm how the @ resize factor might be implemented, then if it makes any sense to anyone else they might do the python cooking:
*SYNTAX* Because of the way the script goes through the rules it would probably be best to syntax the resize rules like this: @0.8F  first comes the @ that signals you are about to get the resize factor, then resize factor itself (0.8 in this case) and then the element (line) we want to resize (F in this case).
*RECURSE* This is how the recurse part of the script works atm: it spits out the final generation rule to be drawn, level can tell you each element's generation (age), i.e. level counts how many times an element is replaced by the rule.
The recurse part should be modified to detect @ in the last generation rule, and recalculate every resize factor following the @ according to this formula:
resize factor=(resize factor)^level
So the recurse part of the script now spits out the final generation rule where every element we want resized has its resize factor calculated according to its age. Lets say this is our rule (axiom is F, I used spaces just to visually help separate the elements, there are no spaces in real formulas):
F=@0.7A @0.5F @0.3A
Only the middle element (F) is recursed, its level is increased (is older one generation) so its factor is recalculated, the second generation is:
@0.7^1A @0.7^2A @0.5^2F @0.3^2A @0.3^1A that is:
@0.7A @0.49A @0.25F @0.09A @0.3A
*COMPOSE PATH* The second thing to modify is the compose_path part of the script. Another c must be added (for @), make it get the number behind @ and multiply it with the element length (step size). Maybe the randomize feature might also be applied here?
This way the resize factor can be set for every element of the rule separately, so I think it's more flexible than some of the other solutions I've seen.
Aaron Spike wrote:
Mihaela wrote:
I thought the lsystem syntax was unique, but I found different formulation for scaling on another website, does it matter which one is adopted in Inkscape?
It probably doesn't matter. Perhaps we should try to find out which syntax is more popular (and thus which has more examples on the web). Or if possible we could implement both. Can you summarize the different syntaxes you've found?
I haven't had time to go through all of them in detail but I think I found more than 2 different approaches. I plan to dive into python as soon as I get some free time, and then I'll look deeper into this also. Until then I'll stick to what's already there in your script ignoring everything else.
I think we need to switch from iterated loop over the pattern string to a counted loop. Then when we see @ we know to advance until we've used all the possible numeric characters. This could even be done with a regular expression.
Aaron
I don't have enough python knowledge to do it myself (yet), I think I've been able to come up with is an algorithm how the @ resize factor might be implemented, then if it makes any sense to anyone else they might do the python cooking:
*SYNTAX* Because of the way the script goes through the rules it would probably be best to syntax the resize rules like this: @0.8F  first comes the @ that signals you are about to get the resize factor, then resize factor itself (0.8 in this case) and then the element (line) we want to resize (F in this case).
*RECURSE* This is how the recurse part of the script works atm: it spits out the final generation rule to be drawn, level can tell you each element's generation (age), i.e. level counts how many times an element is replaced by the rule.
The recurse part should be modified to detect @ in the last generation rule, and recalculate every resize factor following the @ according to this formula:
resize factor=(resize factor)^level
So the recurse part of the script now spits out the final generation rule where every element we want resized has its resize factor calculated according to its age. Lets say this is our rule (axiom is F, I used spaces just to visually help separate the elements, there are no spaces in real formulas):
F=@0.7A @0.5F @0.3A
Only the middle element (F) is recursed, its level is increased (is older one generation) so its factor is recalculated, the second generation is:
@0.7^1A @0.7^2A @0.5^2F @0.3^2A @0.3^1A that is:
@0.7A @0.49A @0.25F @0.09A @0.3A
*COMPOSE PATH* The second thing to modify is the compose_path part of the script. Another c must be added (for @), make it get the number behind @ and multiply it with the element length (step size). Maybe the randomize feature might also be applied here?
This way the resize factor can be set for every element of the rule separately, so I think it's more flexible than some of the other solutions I've seen.
Aaron Spike wrote:
Mihaela wrote:
I thought the lsystem syntax was unique, but I found different formulation for scaling on another website, does it matter which one is adopted in Inkscape?
It probably doesn't matter. Perhaps we should try to find out which syntax is more popular (and thus which has more examples on the web). Or if possible we could implement both. Can you summarize the different syntaxes you've found?
I haven't had time to go through all of them in detail but I think I found more than 2 different approaches. I plan to dive into python as soon as I get some free time, and then I'll look deeper into this also. Until then I'll stick to what's already there in your script ignoring everything else.
I think we need to switch from iterated loop over the pattern string to a counted loop. Then when we see @ we know to advance until we've used all the possible numeric characters. This could even be done with a regular expression.
Aaron
I don't have enough python knowledge to do it myself (yet), I think I've been able to come up with is an algorithm how the @ resize factor might be implemented, then if it makes any sense to anyone else they might do the python cooking:
*SYNTAX* Because of the way the script goes through the rules it would probably be best to syntax the resize rules like this: @0.8F  first comes the @ that signals you are about to get the resize factor, then resize factor itself (0.8 in this case) and then the element (line) we want to resize (F in this case).
*RECURSE* This is how the recurse part of the script works atm: it spits out the final generation rule to be drawn, level can tell you each element's generation (age), i.e. level counts how many times an element is replaced by the rule.
The recurse part should be modified to detect @ in the last generation rule, and recalculate every resize factor following the @ according to this formula:
resize factor=(resize factor)^level
So the recurse part of the script now spits out the final generation rule where every element we want resized has its resize factor calculated according to its age. Lets say this is our rule (axiom is F, I used spaces just to visually help separate the elements, there are no spaces in real formulas):
F=@0.7A @0.5F @0.3A
Only the middle element (F) is recursed, its level is increased (is older one generation) so its factor is recalculated, the second generation is:
@0.7^1A @0.7^2A @0.5^2F @0.3^2A @0.3^1A that is:
@0.7A @0.49A @0.25F @0.09A @0.3A
*COMPOSE PATH* The second thing to modify is the compose_path part of the script. Another c must be added (for @), make it get the number behind @ and multiply it with the element length (step size). Maybe the randomize feature might also be applied here?
This way the resize factor can be set for every element of the rule separately, so I think it's more flexible than some of the other solutions I've seen.
Aaron Spike wrote:
Mihaela wrote:
I thought the lsystem syntax was unique, but I found different formulation for scaling on another website, does it matter which one is adopted in Inkscape?
It probably doesn't matter. Perhaps we should try to find out which syntax is more popular (and thus which has more examples on the web). Or if possible we could implement both. Can you summarize the different syntaxes you've found?
I haven't had time to go through all of them in detail but I think I found more than 2 different approaches. I plan to dive into python as soon as I get some free time, and then I'll look deeper into this also. Until then I'll stick to what's already there in your script ignoring everything else.
I think we need to switch from iterated loop over the pattern string to a counted loop. Then when we see @ we know to advance until we've used all the possible numeric characters. This could even be done with a regular expression.
Aaron
I don't have enough python knowledge to do it myself (yet), I think I've been able to come up with is an algorithm how the @ resize factor might be implemented, then if it makes any sense to anyone else they might do the python cooking:
*SYNTAX* Because of the way the script goes through the rules it would probably be best to syntax the resize rules like this: @0.8F  first comes the @ that signals you are about to get the resize factor, then resize factor itself (0.8 in this case) and then the element (line) we want to resize (F in this case).
*RECURSE* This is how the recurse part of the script works atm: it spits out the final generation rule to be drawn, level can tell you each element's generation (age), i.e. level counts how many times an element is replaced by the rule.
The recurse part should be modified to detect @ in the last generation rule, and recalculate every resize factor following the @ according to this formula:
resize factor=(resize factor)^level
So the recurse part of the script now spits out the final generation rule where every element we want resized has its resize factor calculated according to its age. Lets say this is our rule (axiom is F, I used spaces just to visually help separate the elements, there are no spaces in real formulas):
F=@0.7A @0.5F @0.3A
Only the middle element (F) is recursed, its level is increased (is older one generation) so its factor is recalculated, the second generation is:
@0.7^1A @0.7^2A @0.5^2F @0.3^2A @0.3^1A that is:
@0.7A @0.49A @0.25F @0.09A @0.3A
*COMPOSE PATH* The second thing to modify is the compose_path part of the script. Another c must be added (for @), make it get the number behind @ and multiply it with the element length (step size). Maybe the randomize feature might also be applied here?
This way the resize factor can be set for every element of the rule separately, so I think it's more flexible than some of the other solutions I've seen.
Mihaela wrote:
Aaron Spike wrote:
Mihaela wrote:
I thought the lsystem syntax was unique, but I found different formulation for scaling on another website, does it matter which one is adopted in Inkscape?
It probably doesn't matter. Perhaps we should try to find out which syntax is more popular (and thus which has more examples on the web). Or if possible we could implement both. Can you summarize the different syntaxes you've found?
I haven't had time to go through all of them in detail but I think I found more than 2 different approaches. I plan to dive into python as soon as I get some free time, and then I'll look deeper into this also.
I don't think it will take much to convince me to do the python for you. I just need to know how it should work. :)
Aaron Spike
Aaron Spike wrote:
I don't think it will take much to convince me to do the python for you. I just need to know how it should work. :)
Aaron Spike
First I'd like to apologize everyone for spamming the list last weekend with the same message, I didn't realize it was sourceforge, I thought it was a problem with my login since I didn't get post acknowledgement.
Aaron thats great! Im sorry I didn't reply sooner, just when I thought I had some free time new projects came up... I hope you can play with what Ive written last time, did it make any sense to you? I'd love to test it :)
In the meantime I think I've found a way to draw fractal objects in the current lsystem version. It uses 2 rules, one is A=AA where A is used for stems of the fern and the other is any of the usual plant F rules, axiom is F of course. This makes the stems larger and larger every generation while the final elements (should I call them pine needles) stay the same length. It is kinda opposite of the usual fractal making where every generation gets smaller and smaller, here the length change affects older generations making them bigger and bigger as they age while the current generation is always the same length. I'll investigate all this as soon as I get some free time, maybe all fractals I've seen can be drawn without the @ resize factor just using clever rules. It doesn't mean of course that using @ is unnecessary, @ would make things easier imo. I don't think I'll get to it before august though.
There were some fern examples that I concluded can't be drawn with only 1 angle specified, they need 2 different angles where each is applied to a different element, for example A rotation uses 10° while F uses 35°. I'd also like to investigate this, maybe this could also be avoided with clever rules? I guess I'll have to dive into maths to get all this sorted...
participants (2)

Aaron Spike

Mihaela