diff --git a/README.md b/README.md index d7b4739e..a7677387 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,8 @@ Some modules may depend on other modules. For example, the `polyline2d` module d - Other - [box_extrude](https://openhome.cc/eGossip/OpenSCAD/lib-box_extrude.html) - [stereographic_extrude](https://openhome.cc/eGossip/OpenSCAD/lib-stereographic_extrude.html) + - [turtle2d](https://openhome.cc/eGossip/OpenSCAD/lib-turtle2d.html) + ## Bugs and Feedback diff --git a/docs/images/lib-turtle2d-1.JPG b/docs/images/lib-turtle2d-1.JPG new file mode 100644 index 00000000..25219bbb Binary files /dev/null and b/docs/images/lib-turtle2d-1.JPG differ diff --git a/docs/images/lib-turtle2d-2.JPG b/docs/images/lib-turtle2d-2.JPG new file mode 100644 index 00000000..35f384f1 Binary files /dev/null and b/docs/images/lib-turtle2d-2.JPG differ diff --git a/docs/lib-turtle2d.md b/docs/lib-turtle2d.md new file mode 100644 index 00000000..688eb453 --- /dev/null +++ b/docs/lib-turtle2d.md @@ -0,0 +1,86 @@ +# turtle2d + +An OpenSCAD implementation of Turtle Graphics. It moves on the xy plane. You can get the cooridinate `[x, y]` or `angle` of its current position. + +## Parameters + +- `cmd` : A string command. Different commands use different numbers of arguments. + - `"create"` : Creates a turtle data. The command needs three arguments `x`, `y` and `angle`. For example, use `turtle2d("create", 5, 10, 30)` to create a turtle located at `[0, 0]` with an angle `30` degrees. + - `"set_x"` : Sets the `x` coordinate of a turtle. The command needs two arguments. The first one is a turtle data, and the second one is the `x` coordinate. For example, `turtle2d("set_x", turtle, 20)`. + - `"set_y"` : Sets the `y` coordinate of a turtle. The command needs two arguments. The first one is a turtle data, and the second one is the `y` coordinate. For example, `turtle2d("set_y", turtle, 20)`. + - `"set_a"` : Sets the angle of a turtle. The command needs two arguments. The first one is a turtle data, and the second one is the angle. For example, `turtle2d("set_a", turtle, 45)`. + - `"set_pt"` : Sets `[x, y]` of a turtle. The command needs two arguments. The first one is a turtle data, and the second one is `[x, y]`. For example, `turtle2d("set_pt", turtle, [x, y])`. + - `"forward"` : Forwards a turtle. The command needs two arguments. The first one is a turtle data, and the second one is the length. For example, `turtle2d("forward", turtle, 100)`. + - `"forward"` : Turns a turtle. The command needs two arguments. The first one is a turtle data, and the second one is the angle. For example, `turtle2d("turn", turtle, 180)`. + - `"get_x"`, `"get_y"`, `"get_a"`, `"get_pt"` : All these commands needs only one argument, the turtle data. + +## Examples + + include ; + include ; + + module turtle_spiral(t_before, times, side_leng, angle, width) { + $fn = 24; + if(times != 0) { + t_after_tr = turtle2d("turn", t_before, angle); + t_after_fd = turtle2d("forward", t_after_tr, side_leng); + + line2d( + turtle2d("get_pt", t_before), + turtle2d("get_pt", t_after_fd), + width, + p1Style = "CAP_ROUND", + p2Style = "CAP_ROUND" + ); + + turtle_spiral(t_after_fd, times - 1, side_leng, angle, width); + } + + } + + side_leng = 10; + angle = 144; + width = 1; + times = 5; + + turtle_spiral(turtle2d("create", 0, 0, 0), times, side_leng, angle, width); + +![turtle2d](images/lib-turtle2d-1.JPG) + + include ; + + module turtle_spiral(t_before, side_leng, d_step, min_leng, angle, width) { + $fn = 24; + if(side_leng > min_leng) { + t_after = turtle2d("forward", turtle2d("turn", t_before, angle), side_leng); + + line2d( + turtle2d("get_pt", t_before), + turtle2d("get_pt", t_after), + width, + p1Style = "CAP_ROUND", + p2Style = "CAP_ROUND" + ); + + + turtle_spiral(t_after, side_leng - d_step, d_step, min_leng, angle, width); + } + + } + + side_leng = 50; + d_step = 1; + min_leng = 1; + angle = 90; + width = 1; + + turtle_spiral( + turtle2d("create", 0, 0, 0), + side_leng, + d_step, + min_leng, + angle, + width + ); + +![turtle2d](images/lib-turtle2d-2.JPG) diff --git a/src/turtle2d.scad b/src/turtle2d.scad new file mode 100644 index 00000000..b9c5f867 --- /dev/null +++ b/src/turtle2d.scad @@ -0,0 +1,64 @@ +/** +* turtle2d.scad +* +* An OpenSCAD implementation of Turtle Graphics. +* It moves on the xy plane. +* +* @copyright Justin Lin, 2017 +* @license https://opensource.org/licenses/lgpl-3.0.html +* +* @see https://openhome.cc/eGossip/OpenSCAD/lib-turtle2d.html +* +**/ + +include ; + +function _turtle2d_turtle(x, y, angle) = [[x, y], angle]; + +function _turtle2d_set_point(turtle, point) = [point, _turtle2d_get_angle(turtle)]; + +function _turtle2d_set_x(turtle, x) = [[x, _turtle2d_get_y(turtle)], _turtle2d_get_angle(turtle)]; +function _turtle2d_set_y(turtle, y) = [[_turtle2d_get_x(turtle), y], _turtle2d_get_angle(turtle)]; +function _turtle2d_set_angle(turtle, angle) = [_turtle2d_get_pt(turtle), angle]; + +function _turtle2d_forward(turtle, leng) = + _turtle2d_turtle( + _turtle2d_get_x(turtle) + leng * cos(_turtle2d_get_angle(turtle)), + _turtle2d_get_y(turtle) + leng * sin(_turtle2d_get_angle(turtle)), + _turtle2d_get_angle(turtle) + ); + +function _turtle2d_turn(turtle, angle) = [_turtle2d_get_pt(turtle), _turtle2d_get_angle(turtle) + angle]; + +function _turtle2d_get_x(turtle) = turtle[0][0]; +function _turtle2d_get_y(turtle) = turtle[0][1]; +function _turtle2d_get_pt(turtle) = turtle[0]; +function _turtle2d_get_angle(turtle) = turtle[1]; + +function _turtle2d_three_args_command(cmd, arg1, arg2, arg3) = + cmd == "create" ? _turtle2d_turtle(arg1, arg2, arg3) : _turtle2d_two_args_command(cmd, arg1, arg2); + +function _turtle2d_two_args_command(cmd, arg1, arg2) = + cmd == "set_pt" ? _turtle2d_set_point(arg1, arg2) : ( + cmd == "set_x" ? _turtle2d_set_x(arg1, arg2) : ( + cmd == "set_y" ? _turtle2d_set_y(arg1, arg2) : ( + cmd == "set_a" ? _turtle2d_set_angle(arg1, arg2) : ( + cmd == "forward" ? _turtle2d_forward(arg1, arg2) : ( + cmd == "turn" ? _turtle2d_turn(arg1, arg2) : _turtle2d_one_arg_command(cmd, arg1) + ) + ) + ) + ) + ); + +function _turtle2d_one_arg_command(cmd, arg) = + cmd == "get_x" ? _turtle2d_get_x(arg) : ( + cmd == "get_y" ? _turtle2d_get_y(arg) : ( + cmd == "get_a" ? _turtle2d_get_angle(arg) : ( + cmd == "get_pt" ? _turtle2d_get_pt(arg) : undef + ) + ) + ); + +function turtle2d(cmd, arg1, arg2, arg3) = + _turtle2d_three_args_command(cmd, arg1, arg2, arg3);