123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- #lang typed/racket
- (require pict3d)
- ;; TODO:
- ;; - Calculate positions for lights
- ;; - Simple animations with a light attached to the camera
- ;; Convert character `C' to a number.
- ;; E.g. `(char->number #\5) => 5'.
- (: char->number (-> Char Integer))
- (define (char->number c)
- (- (char->integer c) 48))
- ;; Convert a string `STR' containng only digits to a list of numbers.
- ;; E.g. `(string->numbers "0123") => '(0 1 2 3)'.
- (: string->numbers (-> String (Listof Integer)))
- (define (string->numbers str) (map char->number (string->list str)))
- (: calculate-base (-> (Listof Integer) Integer))
- (define (calculate-base lst)
- (+ 1 (apply max lst)))
- ;; interpret a list of integers `NUM' as an integer in base `BASE'
- ;; E.g. `(interp->num '(1 1) 2) => 3'
- (: interp-num (-> (Listof Integer) Integer Integer))
- (define (interp-num num base)
- (let-values
- ;; TODO: typed/racket does not support the `#:result' argument in `FOR/FOLD`?
- ([(sum pow)
- (for/fold ([sum : Integer 0]
- [pow : Integer 1])
- ([i (reverse num)])
- (values (+ sum (* i pow)) (* pow base)))])
- sum))
- ;; divide up the list into the sublists of size n.
- ;; E.g. `(div-list '(1 2 3 4 5) 3) => '((1 2 3) (4 5))' or
- ;; `(div-list '(1 2 3 4 5 6) 2) => '((1 2) (3 4) (5 6))'.
- (: div-list (All (A) (-> (Listof A) Integer (Listof (Listof A)))))
- (define (div-list lst n)
- (if (<= (length lst) n)
- (list lst)
- (let-values
- ([(a b) (split-at lst n)])
- (cons a (div-list b n)))))
- ;; calculate the permutations of the string as a list of coordinates
- (: permute-string (-> (Listof Integer) Integer (Listof (Listof Integer))))
- (define (permute-string str base)
- (for/list
- ([perm : (Listof Integer) (permutations str)])
- (map
- (lambda ([x : (Listof Integer)])
- (interp-num x base))
- (div-list perm (ceiling (/ (length str) 3))))))
- ;; Interpret a list of coordinate lists as a list of positions
- (: get-positions (-> (Listof (Listof Integer)) (Listof Pos)))
- (define (get-positions lst)
- (map
- (lambda ([p : (Listof Integer)])
- (match p
- [(list x y z) (pos x y z)]
- [(list x y) (pos x y x)]
- [(list x) (pos x x x)]))
- lst))
- ;; pick one element from a list, at random
- (: pick-one (All (A) (-> (Listof A) A)))
- (define (pick-one l)
- (list-ref l (random (length l))))
- (define (random-emitted)
- (pick-one
- (list default-emitted default-emitted
- (emitted "lightgreen" (/ 1 (+ 2 (random 5))))
- (emitted "blue" (/ 1 (+ 1 (random 5)))))))
- ;; Plot a collection of cubes at the given positions
- (: cubes (-> (Listof Pos) Pict3D))
- (define (cubes lst)
- (combine
- (map (lambda ([p : Pos])
- (set-emitted (cube p (pick-one '(1/3 1/2 1/3 2/5))) (random-emitted)))
- lst)))
- (define str "223345")
- (printf "Processing string ~s..~n" str)
- (define num (string->numbers str))
- (define base (calculate-base num))
- (define t
- (freeze (cubes (get-positions (permute-string num base)))))
- (define outer-pos 2102)
- ;; Place some lights at various places
- (define lights
- (combine (light (pos 0 0 0) (emitted "chocolate" 100))
- (light (pos (/ outer-pos 2) (/ outer-pos 2) (/ outer-pos 2)) (emitted "pink" 300))
- (light (pos (+ outer-pos 2) (+ outer-pos 2) (+ outer-pos 2)) (emitted "cyan" 200))
- (light (pos (+ outer-pos 2) -1 (+ outer-pos 2)) (emitted "blue" 170))
- (light (pos -1 (+ outer-pos 2) (+ outer-pos 2)) (emitted "red" 170))
- (light (pos (+ outer-pos 2) (+ outer-pos 2) 4) (emitted "green" 170))))
- (define t+lights (combine t lights))
- (current-pict3d-width 600)
- (current-pict3d-height 600)
- (current-pict3d-add-sunlight? #f)
- (current-pict3d-add-indicators? #f)
- (define t+sunlight
- (combine t
- (sunlight
- (dir (- (/ outer-pos 2)) (- outer-pos) (- (/ outer-pos 2)))
- (emitted "orange" 1/2))))
- (time (send (pict3d->bitmap t+sunlight 2000 2000)
- save-file
- "out.png" 'png))
- (displayln "Done, see out.png")
|