The idea of this toy package arose during a conversation between Rafa RodrÃguez and me in Vigo (Galicia - Spain). It was in july of 2008 when we met there during a course on free maths software at the School of Telecommunications Engineering. His talk was about Octave and mine on Maxima.

While drinking some beers he told me that he was an enthusiast of the Logo programming language and asked me if it could be possible to perform turtle graphics with Maxima. I considered this question as a nice challenge and here is a (very) simple implementation of the idea, in part due to Rafa's idea, in part due to the beers.

The idea is to define a new object called **turtle**, such that we can pass to it as arguments sentences in logo-like style. This is the list of available sentences:

**forward(n)****arc(angle,radius)****left(n)****right(n)****back(n)****setxy(n,n)****setx(n)****sety(n)****home()****towards(number,number)****penup()****pendown()****repeat(n, ....)****to(name, ....)****setpencolor(number)****setpensize(number)****setheading(angle)****make(variable, number)****when(condition, ..., ...)****ifelse(condition,[...],[...])**

Objects of type **turtle** can live together with other **draw2d** objects, such as **explicit**, **parametric** and so on. Also, turtle graphics should be compatible with draw's graphics options.

After loading package turtle.mac we are ready to do some simple things.

load("path/turtle.mac")$

These examples look better on a proportional canvas. Here we set once and for the rest of the session this option as default.

set_draw_defaults( terminal = svg, dimensions = [350,350], proportional_axes = xy) $

A square in blue. See how we can control the x and y ranges and the color with standard draw options:

draw2d( xrange = [-25, 75], yrange = [-25, 75], color = blue, turtle( forward(50), right(90), forward(50), right(90), forward(50), right(90), forward(50)) ) $

Sort of flower made with squares. With **to** we define a procedure named **square** and with **repeat** we draw the squares and make rotations. Angles are always measured in degrees:

draw2d( turtle( to(square,[side], repeat(4, forward(side), right(90))), repeat(10, square(100), left(36))) ) $

A colored flower. Here we make use of the turtle commands to control the colors. Also, command **make** is used to assign values to variables; Maxima's colon (**:**) operator shouldn't be used here. Colors are defined by integers from 1 to 16: black, blue, green, cyan, red, magenta, yellow, white, brown, #d2b48c, forest-green, aquamarine, salmon, purple, orange, grey :

draw2d( turtle( setpensize(2), to(square,[], repeat(4, forward(100), right(90))), make(col,1), repeat(20, setpencolor(col), make(col,col+1), square(), left(18))) ) $

An ellipse of varying width. Command **setheading** sets the orientation of the turtle's head in degrees. **arc(a,r)** draws an arc, where *a* is the angle and *r* the radius, the center being the position of the turtle. Note that the turtle is always at (0, 0):

draw2d( turtle( make(ancho, 1), make(orienta, 90), repeat(71, setpensize(ancho), setheading(orienta), arc(10,5), make(ancho,ancho+0.1), make(orienta,orienta+5)))) $

Two turtle graphics. Note how we play with commands **penup**, **pendown** and **sety** to move the turtle to a new position. **penup** and **pendown** are called as functions without arguments:

draw2d( turtle( make(ancho, 1), make(orienta, 90), repeat(71, setpensize(ancho), setheading(orienta), arc(10,5), make(ancho,ancho+0.1), make(orienta,orienta+5)), to(cuadrado,[], forward(sqrt(2)*9), right(90)), setpensize(2), setpencolor(10), penup(), sety(9), pendown(), setheading(-45), repeat(4, cuadrado()) ) ) $

A circumference. In this case, the turtle walks along the curve:

draw2d( turtle( to(circunferencia,[], repeat(360, forward(1), right(1))), circunferencia()) ) $

A circumference formed by a polygonal line:

draw2d( turtle( to(poly,[side,angle,times], repeat(times, forward(side), right(angle))), poly(10,92,100)) ) $

Spiral:

draw2d( turtle( to(espi,[side,angle,inc,times], /* arguments to procedures can't be changed; we can create a new variable */ make(lado,side), repeat(times, forward(lado), right(angle), make(lado, lado+inc))), espi(1,10,5,200)) ) $

Rotated square:

draw2d( turtle( to(square,[side], repeat(4, forward(side), right(90))), right(70), square(20)) ) $

Playing with **arc**:

draw2d( turtle( penup(), make(radius, 10), repeat(10, arc(360, radius), forward(5), make(radius, radius-1))))$

Nested loops:

draw2d( turtle( setpencolor(5), repeat(24, repeat(3, forward(35), right(120)), right(15) ) )) $

Colored random walk. To force multiple evaluations of Maxima's **random** function inside the loop, don't forget to write the simple quote operator:

draw2d( turtle( repeat(50, setpencolor('random(16)), forward('random(50)), right('random(180))) ) ) $

Variable **repcount** stores the number of the iteration being executed in the most internal loop; in this case, from 1 to 200:

draw2d( turtle( setpencolor(3), make(counter, 1), repeat(200, forward(counter), make(counter, counter+1), right(89)))) $

Multiple polygons:

draw2d( turtle( to(poly,[n], repeat(n, forward(1), right(360 / n))), make(counter, 3), repeat(16, setpencolor(counter), poly(counter), make(counter, counter + 1)) )) $

Random curve. Example with the **ifelse** command:

draw2d( turtle( repeat(100, make(direction, 'random(5)), make(rotation, 'random(30)), forward(direction), ifelse(direction=0, [left(rotation)], [right(rotation)])) ) ) $

© 2011-2016, TecnoStats.