diff --git a/README.md b/README.md index a67aef88..f5fa317c 100644 --- a/README.md +++ b/README.md @@ -213,6 +213,7 @@ See [examples](examples). ### Turtle - [turtle/footprints2](https://openhome.cc/eGossip/OpenSCAD/lib2x-footprints2.html) - [turtle/footprints3](https://openhome.cc/eGossip/OpenSCAD/lib2x-footprints3.html) +- [turtle/lsystem2](https://openhome.cc/eGossip/OpenSCAD/lib2x-lsystem2.html) ---- diff --git a/docs/images/lib2x-lsystem2-1.JPG b/docs/images/lib2x-lsystem2-1.JPG new file mode 100644 index 00000000..88ba072e Binary files /dev/null and b/docs/images/lib2x-lsystem2-1.JPG differ diff --git a/docs/images/lib2x-lsystem2-2.JPG b/docs/images/lib2x-lsystem2-2.JPG new file mode 100644 index 00000000..34183cb7 Binary files /dev/null and b/docs/images/lib2x-lsystem2-2.JPG differ diff --git a/docs/images/lib2x-lsystem2-3.JPG b/docs/images/lib2x-lsystem2-3.JPG new file mode 100644 index 00000000..9b46983f Binary files /dev/null and b/docs/images/lib2x-lsystem2-3.JPG differ diff --git a/docs/lib2x-lsystem2.md b/docs/lib2x-lsystem2.md new file mode 100644 index 00000000..90a8d469 --- /dev/null +++ b/docs/lib2x-lsystem2.md @@ -0,0 +1,85 @@ +# lsystem2 + +`lsystem2` is a 2D implementation of [L-system](https://en.wikipedia.org/wiki/L-system). It's based on the algorithm of turtle grahpics. Instructions for generation of rules are as follows: + + F Move forward and draw line + f Move forward without drawing a line + + Turn left + - Turn right + | Reverse direction (ie: turn by 180 degrees) + [ Push current turtle state onto stack + ] Pop current turtle state from the stack + +**Since:** 2.4 + +## Parameters + +- `axiom` : The initial state of the system. +- `rules` : A list of production rules. The first element of each rule is the predecessor, and the second is the successor. +- `n` : Iteration times. +- `angle` : Used when turing. +- `leng` : Used when forwarding. Default to `1`. +- `heading` : The initial angle of the turtle. Default to `0`. +- `start` : The starting point of the turtle. Default to `[0, 0]`. +- `forward_chars` : Chars used for forwarding after the last iteration. Default to `'F'`. +- `rule_prs` : The probabilities for taking rules. If each rule is chosen with a certain probability, it's a stochastic L-system. Each probability value for a rule ranges from 0 to 1. + +## Examples + +[lsystem-collections.scad](https://github.com/JustinSDK/dotSCAD/blob/master/examples/turtle/lsystem2_collection.scad) collects several L-system grammars. Here's one of them. + + use ; + use ; + + for(line = fern()) { + line2d( + line[0], + line[1], + .2, + p1Style = "CAP_ROUND", + p2Style = "CAP_ROUND" + ); + } + + function fern(n = 8, angle = 4, leng = 1, heading = 0, start = [0, 0]) = + let( + axiom = "EEEA", + rules = [ + ["A", "[++++++++++++++EC]B+B[--------------ED]B+BA"], + ["C", "[---------EE][+++++++++EE]B+C"], + ["D", "[---------EE][+++++++++EE]B-D"] + ] + ) + lsystem2(axiom, rules, n, angle, leng, heading, start, forward_chars = "ABCDE"); + +![lsystem2](images/lib2x-lsystem2-1.JPG) + + // a stochastic L-system + + use ; + use ; + + for(line = weed()) { + line2d( + line[0], + line[1], + .2, + p1Style = "CAP_ROUND", + p2Style = "CAP_ROUND" + ); + } + + function weed(n = 6, angle = 22.5, leng = 1, heading = 0, start = [0, 0]) = + let( + axiom = "F", + rules = [ + ["F", "FF-[XY]+[XY]"], + ["X", "+FY"], + ["Y", "-FX"] + ] + ) + lsystem2(axiom, rules, n, angle, leng, heading, start, rule_prs = [0.8, 0.8, 0.8]); + +![lsystem2](images/lib2x-lsystem2-2.JPG) + +![lsystem2](images/lib2x-lsystem2-3.JPG) \ No newline at end of file diff --git a/src/turtle/_impl/_lsystem2_impl.scad b/src/turtle/_impl/_lsystem2_impl.scad index ef8839f0..92ecb319 100644 --- a/src/turtle/_impl/_lsystem2_impl.scad +++ b/src/turtle/_impl/_lsystem2_impl.scad @@ -3,9 +3,9 @@ use <../turtle2d.scad>; function _lsystem2_join(str_lt) = _join(str_lt); -function _lsystem2_derive(axiom, rules, n, rules_pr) = - is_undef(rules_pr) ? _derive(axiom, rules, n) : - _derive_p(axiom, rules, rules_pr, n); +function _lsystem2_derive(axiom, rules, n, rule_prs) = + is_undef(rule_prs) ? _derive(axiom, rules, n) : + _derive_p(axiom, rules, rule_prs, n); function _next_stack(t, code, stack) = code == "[" ? concat([t], stack) : diff --git a/src/turtle/lsystem2.scad b/src/turtle/lsystem2.scad index e37c104f..928bc980 100644 --- a/src/turtle/lsystem2.scad +++ b/src/turtle/lsystem2.scad @@ -1,21 +1,19 @@ +/** +* lsystem2.scad +* +* @copyright Justin Lin, 2020 +* @license https://opensource.org/licenses/lgpl-3.0.html +* +* @see https://openhome.cc/eGossip/OpenSCAD/lib2x-lsystem2.html +* +**/ + use <_impl/_lsystem2_impl.scad>; use ; -/* - - F Move forward and draw line - f Move forward without drawing a line - + Turn left - - Turn right - | Reverse direction (ie: turn by 180 degrees) - [ Push current turtle state onto stack - ] Pop current turtle state from the stack - -*/ - -function lsystem2(axiom, rules, n, angle, leng = 1, heading = 0, start = [0, 0], forward_chars = "F", rules_pr) = +function lsystem2(axiom, rules, n, angle, leng = 1, heading = 0, start = [0, 0], forward_chars = "F", rule_prs) = let( - derived = _lsystem2_derive(axiom, rules, n, rules_pr), + derived = _lsystem2_derive(axiom, rules, n, rule_prs), codes = forward_chars == "F" ? derived : _lsystem2_join([ for(c = derived) let(idx = search(c, forward_chars))