{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


    ⍝ 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