562 lines
13 KiB
Bash
Executable File
562 lines
13 KiB
Bash
Executable File
#!/bin/sh
|
|
:; exec /usr/local/bin/stk -f "$0" "$@"
|
|
;;;
|
|
;;; STkTurtle v1.0
|
|
;;;
|
|
;;; A (direct) rewritting of the TkTurtle demo found on the net in STk.
|
|
;;; Original copyright:
|
|
;;; Copyright 1993 James Noble, kjx@comp.vuw.ac.nz
|
|
;;;
|
|
|
|
;;; This file comports two distinct parts.
|
|
;;; First part is the turtle package
|
|
;;; Second parts contains a set of examples using the turtle package
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;;
|
|
;;;; T u r t l e p a c k a g e
|
|
;;;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(define turtle-canvas-name ".c")
|
|
(define turtle-canvas '())
|
|
|
|
(define turtle-colours #("" "root_weave" "stipple" "gray1" "boxes"
|
|
"hlines2" "vlines2" "cross_weave"
|
|
"light_gray" "dimple1" "vlines3" "hlines3"
|
|
"grid4" "gray3" "dimple3" "grid8"))
|
|
|
|
(define turtle-num_colours 16)
|
|
|
|
(define turtle-d2r (/ 180 3.14159))
|
|
|
|
(define turtle-x 0)
|
|
(define turtle-y 0)
|
|
(define turtle-direction 270)
|
|
(define turtle-width 0)
|
|
(define turtle-colour 0)
|
|
(define turtle-pen #t)
|
|
|
|
(define turtle-speed #t)
|
|
(define turtle-show #t)
|
|
|
|
|
|
;;;
|
|
;;; initialise turtle
|
|
;;;
|
|
(define (turtle)
|
|
;; clear actually does this, plus draw-turtle
|
|
(set! turtle-x 0)
|
|
(set! turtle-y 0)
|
|
(set! turtle-direction 270)
|
|
(set! turtle-width 0)
|
|
(set! turtle-colour 0)
|
|
(set! turtle-pen #t)
|
|
|
|
;; debugging
|
|
(set! turtle-speed #t)
|
|
(set! turtle-show #t)
|
|
|
|
(if (winfo 'exists turtle-canvas-name)
|
|
(new)
|
|
(begin
|
|
(scrollbar ".v" :relief "sunken" :borderwidth 3
|
|
:command (lambda l (apply turtle-canvas 'yview l)))
|
|
(scrollbar ".h" :relief "sunken" :borderwidth 3
|
|
:orient 'horiz :command (lambda l
|
|
(apply turtle-canvas 'xview l)))
|
|
|
|
(canvas turtle-canvas-name :borderwidth 3
|
|
:scrollregion '(-1000 -1000 1000 1000)
|
|
:xscrollcommand (lambda l (apply .h 'set l))
|
|
:yscrollcommand (lambda l (apply .v 'set l))
|
|
:height 500
|
|
:width 500)
|
|
|
|
(set! turtle-canvas (string->widget turtle-canvas-name))
|
|
|
|
(centre)
|
|
|
|
(pack .h :side "bottom" :fill "x")
|
|
(pack .v :side "right" :fill "y")
|
|
(pack turtle-canvas :expand #t :fill "both")
|
|
|
|
|
|
(bind turtle-canvas "<2>" (lambda (x y)
|
|
(turtle-canvas 'scan 'mark x y)))
|
|
(bind turtle-canvas "<B2-Motion>" (lambda (x y)
|
|
(turtle-canvas 'scan 'dragto x y)))
|
|
(bind turtle-canvas "<c>" centre)
|
|
(bind turtle-canvas "<Control-c>" (lambda () (destroy ".")))
|
|
(bind turtle-canvas "<Control-q>" (lambda () (destroy ".")))
|
|
(bind turtle-canvas "<f>" toggle-speed)
|
|
(bind turtle-canvas "<s>" toggle-show)
|
|
|
|
(focus turtle-canvas)
|
|
|
|
(wm 'minsize "." 10 10)
|
|
(wm 'title "." "Turtle")
|
|
(wm 'iconname "." "Turtle")
|
|
|
|
(draw-turtle))))
|
|
|
|
;;;
|
|
;;; drawing
|
|
;;;
|
|
|
|
(define (make-stipple n)
|
|
(let ((name (vector-ref turtle-colours n)))
|
|
(if (string=? name "")
|
|
""
|
|
(string-append "@" *STk-library* "/images/" name))))
|
|
|
|
(define (go length)
|
|
(let ((newx (+ turtle-x (* (cos (/ turtle-direction turtle-d2r)) length)))
|
|
(newy (+ turtle-y (* (sin (/ turtle-direction turtle-d2r)) length))))
|
|
|
|
(goto newx newy)
|
|
length))
|
|
|
|
(define (goto x y)
|
|
(when turtle-pen
|
|
(turtle-canvas 'create 'line turtle-x turtle-y x y
|
|
:width turtle-width
|
|
:stipple (make-stipple turtle-colour)
|
|
:tags 'line))
|
|
|
|
(set! turtle-x x)
|
|
(set! turtle-y y)
|
|
(when turtle-show (draw-turtle))
|
|
(when turtle-speed (update))
|
|
(list x y))
|
|
|
|
|
|
;;; writing text
|
|
(define (Write text)
|
|
(turtle-canvas 'create 'text turtle-x turtle-y
|
|
:text text
|
|
:stipple (make-stipple turtle-colour)
|
|
:tags 'text)
|
|
(when turtle-speed (update)))
|
|
|
|
|
|
;;; writing windows
|
|
(define (window name)
|
|
(turtle-canvas 'create 'window turtle-x turtle-y
|
|
:window name
|
|
:tags 'window)
|
|
(update))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;; drawing parameters
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; change pen state
|
|
(define (pen . p)
|
|
(if (null? p)
|
|
turtle-pen
|
|
(set! turtle-pen (car p))))
|
|
|
|
(define (down) (pen #t))
|
|
(define (up) (pen #f))
|
|
|
|
|
|
;;; change direction
|
|
(define (turn n)
|
|
(turnto (+ turtle-direction n)))
|
|
|
|
(define (turnto n)
|
|
(set! turtle-direction (modulo (floor n) 360))
|
|
(draw-turtle)
|
|
turtle-direction)
|
|
|
|
(define (east) (turnto 0))
|
|
(define (south) (turnto 90))
|
|
(define (west) (turnto 180))
|
|
(define (north) (turnto 270))
|
|
|
|
(define (direction)
|
|
turtle-direction)
|
|
|
|
(define (location)
|
|
(list turtle-x turtle-y))
|
|
|
|
(define (width . w)
|
|
(unless (null? w)
|
|
(set! turtle-width (car w))
|
|
(draw-turtle))
|
|
turtle-width)
|
|
|
|
(define (colour . c)
|
|
(if (null? c)
|
|
turtle-colour
|
|
(set! turtle-colour (modulo (floor (car c)) turtle-num_colours))))
|
|
|
|
(define (status . c)
|
|
(if (null? c)
|
|
(list turtle-x turtle-y turtle-direction turtle-width turtle-colour
|
|
turtle-pen)
|
|
(if (not (= (length (car c)) 6))
|
|
(error "Can't restore saved state")
|
|
(let ((c (car c)))
|
|
(set! turtle-x (list-ref c 0))
|
|
(set! turtle-y (list-ref c 1))
|
|
(set! turtle-direction (list-ref c 2))
|
|
(set! turtle-width (list-ref c 3))
|
|
(set! turtle-colour (list-ref c 4))
|
|
(set! turtle-pen (list-ref c 5))
|
|
(draw-turtle)
|
|
c))))
|
|
|
|
(define (draw-turtle)
|
|
(when turtle-show
|
|
(turtle-canvas 'delete 'turtle)
|
|
(turtle-canvas 'create 'line
|
|
turtle-x
|
|
turtle-y
|
|
(+ turtle-x (* (cos (/ turtle-direction turtle-d2r)) 10))
|
|
(+ turtle-y (* (sin (/ turtle-direction turtle-d2r)) 10))
|
|
:arrow 'last
|
|
:fill "red"
|
|
:tags 'turtle
|
|
:width turtle-width))
|
|
0)
|
|
|
|
(define (show)
|
|
(set! turtle-show #t)
|
|
(draw-turtle)
|
|
#t)
|
|
|
|
(define (hide)
|
|
(set! turtle-show #f)
|
|
(turtle-canvas 'delete 'turtle)
|
|
#f)
|
|
|
|
(define (toggle-show)
|
|
(if turtle-show (hide) (show)))
|
|
|
|
|
|
;;; misc
|
|
(define (home)
|
|
(set! turtle-x 0)
|
|
(set! turtle-y 0)
|
|
(set! turtle-direction 270)
|
|
(draw-turtle))
|
|
|
|
(define (clear)
|
|
(home)
|
|
(down)
|
|
(width 0)
|
|
(colour 0)
|
|
(turtle-canvas 'delete 'line 'text)
|
|
(draw-turtle))
|
|
|
|
(define (new)
|
|
(clear)
|
|
(turtle-canvas 'delete 'window))
|
|
|
|
(define (screen-dump . file)
|
|
(turtle-canvas 'postscript
|
|
:file (if (null? file) "Screen-dump.ps" (car file))))
|
|
|
|
(define (centre)
|
|
(turtle-canvas 'xview 'moveto 0.37)
|
|
(turtle-canvas 'yview 'moveto 0.37))
|
|
|
|
|
|
;;;conversion
|
|
(define (d2r degrees)
|
|
(/ degrees turtle-d2r))
|
|
|
|
;;; speed
|
|
(define (speed . s)
|
|
(if (null? s)
|
|
turtle-speed
|
|
(set! turtle-speed (car s))))
|
|
|
|
(define (slow) (speed #t))
|
|
(define (fast) (speed #f))
|
|
(define (toggle-speed) (if turtle-speed (fast) (slow)))
|
|
|
|
;;; MACROS - move, moveto
|
|
(define (move distance)
|
|
(let ((oldpen (pen)))
|
|
(go distance)
|
|
(pen oldpen)))
|
|
|
|
(define (moveto x y)
|
|
(let ((oldpen (pen)))
|
|
(goto x y)
|
|
(pen oldpen)))
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;;
|
|
;;;; E x a m p l e s
|
|
;;;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
;; polygon
|
|
(define (polygon n length)
|
|
(do ((k 0 (+ k 1)))
|
|
((= k n))
|
|
(turn (/ 360 n))
|
|
(go length)))
|
|
|
|
;; polygon, with a functional parameter
|
|
(define (fungon n length F)
|
|
(do ((k 0 (+ k 1)))
|
|
((= k n))
|
|
(turn (/ 360 n))
|
|
(F length)))
|
|
|
|
;; Iterative Spiral
|
|
(define (spiral angle length)
|
|
(while (>= length 1)
|
|
(go length)
|
|
(turn angle)
|
|
(set! length (- length 5))))
|
|
|
|
;; Recursive spiral
|
|
(define (rspiral angle length)
|
|
(when (>= length 1)
|
|
(go length)
|
|
(turn angle)
|
|
(rspiral angle (- length 5))))
|
|
|
|
;; "Koch's" a single line - used in snowflake
|
|
(define (koch order length)
|
|
(if (or (<= order 1) (<= length 1))
|
|
(go length)
|
|
(begin
|
|
(koch (- order 1) (/ length 3))
|
|
(turn -60)
|
|
(koch (- order 1) (/ length 3))
|
|
(turn 120)
|
|
(koch (- order 1) (/ length 3))
|
|
(turn -60)
|
|
(koch (- order 1) (/ length 3)))))
|
|
|
|
;; Koch's snowflake fractal
|
|
(define (kochflake order length)
|
|
(do ((k 0 (+ k 1)))
|
|
((= k 3))
|
|
(turn 120)
|
|
(koch order length)))
|
|
|
|
;; tricky version of kochflake
|
|
(define (tricky-kochflake order length)
|
|
(fungon 3 (lambda () (koch order length))))
|
|
|
|
;; Four sided koch
|
|
(define (squarekoch order length)
|
|
(if (or (<= order 1) (<= length 1))
|
|
(go length)
|
|
(begin
|
|
(squarekoch (- order 1) (/ length 3))
|
|
(turn -90)
|
|
(squarekoch (- order 1) (/ length 3))
|
|
(turn 90)
|
|
(squarekoch (- order 1) (/ length 3))
|
|
(turn 90)
|
|
(squarekoch (- order 1) (/ length 3))
|
|
(turn -90)
|
|
(squarekoch (- order 1) (/ length 3)))))
|
|
|
|
(define (squareflake order length)
|
|
(do ((k 0 (+ k 1)))
|
|
((= k 4))
|
|
(turn 90)
|
|
(squarekoch order length)))
|
|
|
|
;; Fractal line
|
|
(define (fracline order angle length)
|
|
(if (< order 1)
|
|
(go length)
|
|
(let* ((ang (- [random (* 2 angle)] angle))
|
|
(len (/ length (* 2 [cos (d2r ang)]))))
|
|
(turn ang)
|
|
(fracline (- order 1) angle len)
|
|
(turn (- (* ang 2)))
|
|
(fracline (- order 1) angle len)
|
|
(turn ang))))
|
|
|
|
;; binary tree
|
|
(define (bintree depth length angle)
|
|
(when (> depth 0)
|
|
(let ((saved (status)))
|
|
(set! depth (- depth 1))
|
|
(go length)
|
|
(turn (- angle))
|
|
(bintree depth length angle)
|
|
(turn (+ angle 2))
|
|
(bintree depth length angle)
|
|
(status saved))))
|
|
|
|
;; C curve fractal
|
|
(define (ccurv order length)
|
|
(if (<= order 1)
|
|
(go length)
|
|
(begin
|
|
(ccurv (- order 1) length)
|
|
(turn 90)
|
|
(ccurv (- order 1) length)
|
|
(turn -90))))
|
|
|
|
;; Dragon curve fractal
|
|
(define (dragon order length)
|
|
(letrec ((dragon-aux (lambda (order length dirn)
|
|
(if (<= order 1)
|
|
(go length)
|
|
(begin
|
|
(dragon-aux (- order 1) length 90)
|
|
(turn dirn)
|
|
(dragon-aux (- order 1) length -90))))))
|
|
(dragon-aux order length 90)))
|
|
|
|
;; Sierpinski's gasket
|
|
(define (gasket order length)
|
|
(when (> order 0)
|
|
(do ((k 0 (+ k 1)))
|
|
((= k 3))
|
|
(gasket (- order 1) (/ length 2))
|
|
(go length)
|
|
(turn 120))))
|
|
|
|
;; Sierpinski's carpet
|
|
(define (carpet order length)
|
|
(if (< order 1)
|
|
(go length)
|
|
(begin
|
|
(carpet (- order 1) (/ length 3))
|
|
(turn -90)
|
|
(carpet (- order 1) (/ length 3))
|
|
(turn 90)
|
|
(carpet (- order 1) (/ length 3))
|
|
(turn 90)
|
|
(carpet (- order 1) (/ length 3))
|
|
(let ((saved (status)))
|
|
(carpet (- order 1) (/ length 3))
|
|
(turn 90)
|
|
(carpet (- order 1) (/ length 3))
|
|
(turn 90)
|
|
(carpet (- order 1) (/ length 3))
|
|
(status saved)
|
|
(turn -90)
|
|
(carpet (- order 1) (/ length 3))))))
|
|
|
|
;; "Bendy" - simple fractal (C curve variation)
|
|
(define (bendy order length)
|
|
(if (< order 1)
|
|
(go length)
|
|
(begin
|
|
(turn 30)
|
|
(bendy (- order 1) (/ length 2))
|
|
(turn -60)
|
|
(bendy (- order 1) (/ length 2))
|
|
(turn 30))))
|
|
|
|
;; "Squigly" - simple fractal (C curve variation)
|
|
(define (squigly order length)
|
|
(if (< order 1)
|
|
(go length)
|
|
(begin
|
|
(turn 30)
|
|
(squigly (- order 1) (/ length 4))
|
|
(turn -60)
|
|
(squigly (- order 1) (/ length 2))
|
|
(turn 60)
|
|
(squigly (- order 1) (/ length 4))
|
|
(turn -30))))
|
|
|
|
(define (randtree depth length angle branch)
|
|
(when (>= depth 1)
|
|
(let ((saved (status))
|
|
(thisbranch (random branch)))
|
|
(set! depth (- depth 1))
|
|
(go (+ (random length) length))
|
|
(turn (- (/ (* angle thisbranch) 4)))
|
|
(do ((k 0 (+ k 1)))
|
|
((= k thisbranch))
|
|
(turn (random angle))
|
|
(randtree depth length angle branch))
|
|
(status saved))))
|
|
|
|
;;windows-demo
|
|
(define (windows-demo)
|
|
(let ((S (scale (& turtle-canvas "scale"))))
|
|
(show)
|
|
(up)
|
|
(goto -200 -200)
|
|
(window S)
|
|
(goto -150 -200)
|
|
(window (button (& turtle-canvas ".spiral-button") :text "Spiral"
|
|
:command (lambda () (spiral [S 'get] 100))))
|
|
(goto -100 -200)
|
|
(window [button (& turtle-canvas ".clear-button") :text "Clear" :command clear])
|
|
(goto -50 -200)
|
|
(window [button (& turtle-canvas ".home-button") :text "Home" :command home])
|
|
(goto 180 -200)
|
|
(window [button (& turtle-canvas ".quit-button") :text "Quit Demo"
|
|
:fg "CadetBlue" :command (lambda () (exit))])
|
|
(S 'set 45)
|
|
(down)
|
|
(home)))
|
|
|
|
(define (item message demo)
|
|
(clear)
|
|
(up)
|
|
(goto 0 220)
|
|
(down)
|
|
(Write message)
|
|
(home)
|
|
(demo))
|
|
|
|
(define (run-demo)
|
|
(item "Polygon"
|
|
(lambda ()
|
|
(do ((k 3 (+ k 1))) ((= k 12))
|
|
(home) (polygon k 50))))
|
|
(item "Lines"
|
|
(lambda ()
|
|
(do ((k 0 (+ k 1))) ((= k 16))
|
|
(moveto 0 0) (turn 22.5) (width k) (go 200))))
|
|
|
|
(item "Stipple"
|
|
(lambda ()
|
|
(width 15)
|
|
(do ((k 0 (+ k 1))) ((= k 16))
|
|
(moveto 0 0) (turn 22.5) (colour k) (go 200))))
|
|
|
|
(item "Fractal lines"
|
|
(lambda ()
|
|
(do ((k 0 (+ k 1))) ((= k 7))
|
|
(home) (fracline 6 40 200))))
|
|
|
|
(item "Spiral" (lambda () (spiral 50 100)))
|
|
(item "Recursive spiral" (lambda () (rspiral 89 100)))
|
|
(item "Recursive spiral" (lambda () (rspiral -90 100)))
|
|
(item "Koch flake" (lambda () (kochflake 3 150)))
|
|
(item "Square flake" (lambda () (squareflake 3 150)))
|
|
(item "Squigly" (lambda () (squigly 4 200)))
|
|
(item "C curve" (lambda () (ccurv 6 20)))
|
|
(item "Dragon" (lambda () (dragon 6 20)))
|
|
(item "Gasket" (lambda () (gasket 6 200)))
|
|
(item "Carpet" (lambda () (carpet 3 250)))
|
|
(item "Binary tree" (lambda () (bintree 6 30 20)))
|
|
(item "Random tree" (lambda () (randtree 4 20 30 6)))
|
|
(item "Windows Demo" windows-demo))
|
|
|
|
|
|
|
|
;; Init part - Run the demo
|
|
(expand-heap 50000)
|
|
(set! *gc-verbose* #f)
|
|
|
|
(turtle)
|
|
(hide)
|
|
|
|
(run-demo)
|