{lines} ← {defs←default} ##.turtle cmds ⍝ Flying-turtle graphics.
[turtle] displays fractal curves in a temporary window. Hit Escape to close.
Right argument [cmds] is a vector of single-character macro calls as produced by
→lsys←. Left argument [defs] are macro definitions, which expand to primitive
turtle commands:
↑⍵ move forward ⍵ units (⍵<0: move backward)
⌽⍵ turn left ⍵ degrees (⍵<0: turn right)
⊖⍵ roll anti-clockwise ⍵ degress (⍵<0: roll clockwise)
⍋⍵ pitch upwards ⍵ degrees (⍵<0: pitch downwards)
[ stack turtle's current position and attitude, and continue
] pop turtle's position and attitude to start a new path
Default [defs] vector: 'F=↑1 +=⌽¯90 -=⌽90 ×=⊖¯90 ÷=⊖90 ∧=⍋90 ∨=⍋¯90' defines:
F=↑1 F → forward move of 1 unit
+=⌽¯90 + → right turn of 90°
-=⌽90 - → left turn of 90°
×=⊖¯90 × → clockwise roll of 90°
÷=⊖90 ÷ → anti-clockwise roll of 90°
∧=⍋¯90 ∧ → upwards pitch of 90°
∨=⍋90 ∨ → downwards pitch of 90°
Commands without a corresponding macro definition are ignored except that:
'⎕' signals line segments to be drawn one at a time to trace progress.
'⌹' causes 3D images to be rendered in red/cyan Anaglyph mode (see below).
'⌸' returns the [lines] result (without displaying its image) for further
processing, such as hidden line removal or polygon colouring.
2D example
----------
turtle'⎕ FF+F-F' ⍝ [trace progress] fwd fwd right fwd left fwd
produces a window containing an image like this:
┌─────────┐ forward 1; forward 1; right turn
│ │ │ forward 1; left turn
│ ┌──┘ │ forward 1
│ │ │
│ │ ← turtle starts here heading north; Esc to quit.
└─────────┘
3D example
----------
turtle'F+F-F∧F∨F' ⍝ fwd right fwd left fwd up fwd down fwd
produces a 3D zigzag. 3D images can be rotated and zoomed for better viewing:
↑ ↓ cursor-keys rotate the image around the x-axis.
← → .. .. .. .. .. y-azis.
z x keys .. .. .. z-axis.
b f keys zoom the image backwards and forwards
¯ ¯
3D images are given a hint of perspective by scaling the points' x and y values,
and by greying lines with respect to their z positions.
Anaglyph 3D Images
------------------
If the [cmds] vector for a 3D image contains a '⌹' character, slightly offset
cyan and red images are presented, suitable for viewing through red and cyan 3D-
spectacles. These can be constructed using cardboard and coloured toffee-wrapp-
ing paper, thus:
┌─────────────────────────────────┐
┌─────────────────────┘ ┌──────────┐ ┌─┐ ┌──────────┐ └─────────────────────┐
│ ┌───────────────────┐ │//////////│ ┌┘ └┐ │\\\\\\\\\\│ ┌───────────────────┐ │
│ │ │ │///red////│ │ │ │\\\cyan\\\│ │ │ │
│ │ │ │////L/////│ │ │ │\\\\R\\\\\│ │ │ │
│ │ │ │//////////│ │ │ │\\\\\\\\\\│ │ │ │
└─┘ │ └──────────┘ │ │ └──────────┘ │ └─┘
└──────────────┘ └──────────────┘
Your toffee paper may vary. Having chosen filters, adjust the image colours by
changing the RGB values in inner function [colours], so that the left and right
images disappear when viewed through each of the right and left filters in turn.
clrs←(0 255 255)(255 0 0) ⍝ left and right colours
Ref: https://en.wikipedia.org/wiki/3D_film#Anaglyph
NB: to avoid eyestrain, please don't stare through these filters for too long.
See below for an example.
Branching Fractals
------------------
Stacking-commands [ and ] allow the production of branching fractals; see the
"fractal plant" examples below. On encountering a [ command, the turtle's curr-
ent position and attitude are stacked, and processing continued. When the corr-
esponding ] is reached, the stacked state of the turtle is restored and a new
branch started from that point.
Ref: https://en.wikipedia.org/wiki/Turtle_graphics
Ref: https://en.wikipedia.org/wiki/L-system
Technical notes:
The turtle's state is defined by the triple: (position heading banking):
position: (i j k) coordinates in 3-space
heading: (i j k) unit vector: direction of movement
banking: (i j k) unit vector normal to heading
The turtle's position is changed by inner function [move] and its attitude by
functions [turn] [roll] and [pitch].
Inner function [cmds] takes the right argument vector of single-character macro
calls and expands each into a primitive turtle command and numeric argument,
using the left argument vector of macro definitions [defs].
[draw] processes the vector of turtle commands, left to right, and accumulates a
list of paths, where each path is a list of (x y) coordinate pairs. Each ']' in
the command stream starts a new path, which means that non-branching fractals
produce only a single-item paths list.
[rotn] returns an ⍺-rotation of points array ⍵. ⍺ is a 4-vector: the join of the
rotation angle in radians with the unit 3-vector of the axis of rotation. If the
rotation is around one of the i, j or k axes, the calculation is achieved with
the slightly quicker complex arithmetic function [rot2]. Otherwise, if the
rotation is around an axis other than i, j or k, the more general [rot3], which
uses quaternion arithmetic, is used. See →H←.
[points] returns a vector of polygon Points matrices from a list of path lists.
For 2D images, the Points are adjusted to fill 95% of the display window, leav-
ing a 2.5% border. 3D images are reduced so that they may be rotated without
their edges straying outside the window. Inner function [centred] centres the
Points values within the window. For 3D images, the centre of rotation is chosen
as the position with a minimum least-squares distance from all points, using
over-specified matrix division (⌹):
⍵-⍤1¨⊂pts⌹(≢pts)⍴1 ⍝ 3D: mid point centred
[image] takes a vector of polygon Points matrices and displays them in a square
window in the upper right corner of the screen.
[trace] renders images one line at a time if right argument [cmds] contains '⎕'.
[put] places coloured lines in the Poly object. With tracing, the Points and
FCol property vectors are extended incrementally. This presents a problem in
that the vectors must always be of the same length, which means that neither can
be extended before the other without incurring a LENGTH ERROR. To avoid this:
the FCol property is first set to an empty scalar value; then the Points vector
extended; and finally, FCol set to the new vector. This sequence may be achieved
with a single left-to-right vector assignment:
put←{pp.(FCol Points FCol)←(⊂⊂⍬),⍵} ⍝ rendering of polygon points
Examples:
⍝ NB: After each example, hit Escape to close the graphics window.
⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝ 2D turtle examples:
turtle'⎕',('X' 'XFY+')('Y' 'FY')lsys⍣21⊢'X' ⍝ square spiral ("squiral"?)
hilbert ←, ⊂'A' '-BF+AFA+FB-' ⍝ Hilbert curve productions →lsys←
hilbert ,← ⊂'B' '+AF-BFB-FA+' ⍝ (turtle ignores A and B)
turtle hilbert lsys⍣4 ⊢'A' ⍝ order-4 Hilbert curve
turtle '⎕',hilbert lsys⍣4 ⊢'A' ⍝ traced Hilbert curve
peano ←, ⊂'A' 'AFBFA-F-BFAFB+F+AFBFA' ⍝ Peano curve productions
peano ,← ⊂'B' 'BFAFB+F+AFBFA-F-BFAFB' ⍝ (turtle ignores A and B)
turtle peano lsys⍣3 ⊢'A' ⍝ order-3 Peano curve
dragon ←, ⊂'A' 'A+BF+' ⍝ Dragon curve productions
dragon ,← ⊂'B' '-FA-B' ⍝ (turtle ignores A and B)
turtle dragon lsys⍣10 ⊢'FA' ⍝ order-10 Dragon curve
A60 ← 'A=↑1 B=↑1 +=⌽¯60 -=⌽60' ⍝ A and B are fwd 1; 60° turns
koch ← 'A' 'A-A++A-A' ⍝ Koch curve production
A60 turtle koch lsys⍣3 ⊢'A++A++A' ⍝ order-3 Koch curve (snowflake)
gosper ←, ⊂'A' 'A-B--B+A++AA+B-' ⍝ Gosper curve productions
gosper ,← ⊂'B' '+A-BB--B-A++A+B' ⍝ (A and B are fwd 1)
A60 turtle gosper lsys⍣3 ⊢'A' ⍝ order-3 Gosper curve
sierpinski ←, ⊂'A' '+B-A-B+' ⍝ Sierpinski triangle productions
sierpinski ,← ⊂'B' '-A+B+A-' ⍝ (A and B are fwd 1)
A60 turtle sierpinski lsys⍣6 ⊢'A' ⍝ order-6 Sierpinski curve
A30 ← 'A=↑1 B=↑1 +=⌽¯30 -=⌽30' ⍝ A and B are fwd 1; 30° turns
sprig ←, ⊂'A' 'B[+A][-A]BA' ⍝ Symmetrical fractal plant
sprig ,← ⊂'B' 'BB' ⍝ (A and B are fwd 1)
A30 turtle sprig lsys⍣4 ⊢'A' ⍝ order-4 sprig
fern ←, ⊂'X' 'B-[[X]+X]+B[+BX]-X' ⍝ Asymmetrical fractal plant
fern ,← ⊂'B' 'BB' ⍝ (X is ignored)
A30 turtle fern lsys⍣4 ⊢'X' ⍝ order-4 fern
A30 turtle '⎕',fern lsys⍣4 ⊢'X' ⍝ tracing growth
bush ← 'A' 'AA-[-A+A+A]+[+A-A-A]' ⍝ Asymmetrical windswept bush
A30 turtle bush lsys⍣3 ⊢'A' ⍝ order-3 bush
star←{ ⍝ ⍵-pointed star
⍺←⌊(⍵-1)÷2 ⍝ winding number
M←'F=↑1 T=⌽360÷',⍕⍵÷⍺ ⍝ macros
P←'X' 'FTX' ⍝ production
M turtle P lsys⍣⍵⊢'X' ⍝ star drawing
}
star 5 ⍝ 5-pointed star
2 3 star¨ 7 ⍝ two 7-pointed stars
stars←{(⍳⌊⍵÷2)star¨⍵} ⍝ all ⍵-stars
stars 17 ⍝ all 17-pointed stars
⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝ 3D turtle examples:
⍝ Cursor keys ↑ ↓ ← → and keys z x rotate the image.
⍝ Escape (Esc) closes the graphics window.
hilb3 ← 'A' '∨×AF∨×AFA-F∨÷÷AFA∧F+÷÷AFA-F÷A-÷' ⍝ order-2 3D Hilbert curve
turtle hilb3 lsys⍣2 ⊢'A'
⍝ The following function generates one of the 5 platonic solids:
platonic←{⍺←'' ⍝ Platonic solids
tetrahedron←{ ⍝ Tetrahedron
T←turn○÷6 ⍝ 30° turn
P←pitch ¯2○÷3*0.5 ⍝ pitch
S←'X' 'F++++[+∨F]X' ⍝ production
(F,T,P)turtle ⍺,S lsys⍣3⊢'X' ⍝ 3 turtle paths
}
cube←{ ⍝ Cube
T←turn○÷2 ⍝ 90° turn
R←roll○÷2 ⍝ roll
S←'X' '[+FX×+F+F]' ⍝ production
(F,T,R)turtle ⍺,S lsys⍣4⊢'X' ⍝ 4 turtle paths
}
octahedron←{ ⍝ Octahedron
T←turn○÷4 ⍝ 45° turn
P←pitch○÷4 ⍝ pitch
S←'X' 'F++[+∧F][+∨F]X' ⍝ production
(F,T,P)turtle ⍺,S lsys⍣4⊢'X' ⍝ 4 turtle paths
}
dodecahedron←{ ⍝ Dodecahedron
T←turn○2÷5 ⍝ 72° turn
R←roll(○1)-¯3○2 ⍝ roll
S←'X' 'F[×+F+F[÷+F+F]+F]+X' ⍝ production
(F,T,R)turtle ⍺,S lsys⍣5⊢'X' ⍝ 5 turtle paths
}
icosahedron←{ ⍝ Icosahedron
T←turn○÷3 ⍝ 60° turn
R←roll ¯2○(5*0.5)÷3 ⍝ roll
S←'X' '[F++F[---×+F-[-×+F×++F]-F]]+×X' ⍝ production
(F,T,R)turtle ⍺,S lsys⍣5⊢'X' ⍝ 5 turtle paths
}
F←'F=↑1 ' ⍝ forward 1 unit
attd←{⍕(⍺⍺,¨⊂'=',⍵⍵),∘⍕¨⍵÷○÷180 ¯180} ⍝ attitude change
turn←'+-'attd'⌽' ⍝ left/right turn (radians)
roll←'×÷'attd'⊖' ⍝ anti/clock roll
pitch←'∧∨'attd'⍋' ⍝ up/down pitch
⍵∊'Tt',33:⍺ tetrahedron ⍵ ⍝ Schläfli: {3,3}
⍵∊'Cc',43:⍺ cube ⍵ ⍝ .. {4,3}
⍵∊'Oo',34:⍺ octahedron ⍵ ⍝ .. {3,4}
⍵∊'Dd',53:⍺ dodecahedron ⍵ ⍝ .. {5,3}
⍵∊'Ii',35:⍺ icosahedron ⍵ ⍝ .. {3,5}
}
platonic¨ 'TCODI' ⍝ wire frame views
'⌹'platonic¨ 'TCODI' ⍝ anaglyph 3D
⍝ Testing [turtle] with an upper case 'V' left argument displays the images.
⍝ The tests include a modification of the [turtle] function, which produces
⍝ solid-looking images, with hidden edges removed:
'V'test'turtle' ⍝ verbose test shows images.
See also: lsys H
Back to: contents
Back to: Workspaces