main.rkt 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #lang typed/racket
  2. (require pict3d)
  3. ;; TODO:
  4. ;; - Calculate positions for lights
  5. ;; - Simple animations with a light attached to the camera
  6. ;; Convert character `C' to a number.
  7. ;; E.g. `(char->number #\5) => 5'.
  8. (: char->number (-> Char Integer))
  9. (define (char->number c)
  10. (- (char->integer c) 48))
  11. ;; Convert a string `STR' containng only digits to a list of numbers.
  12. ;; E.g. `(string->numbers "0123") => '(0 1 2 3)'.
  13. (: string->numbers (-> String (Listof Integer)))
  14. (define (string->numbers str) (map char->number (string->list str)))
  15. (: calculate-base (-> (Listof Integer) Integer))
  16. (define (calculate-base lst)
  17. (+ 1 (apply max lst)))
  18. ;; interpret a list of integers `NUM' as an integer in base `BASE'
  19. ;; E.g. `(interp->num '(1 1) 2) => 3'
  20. (: interp-num (-> (Listof Integer) Integer Integer))
  21. (define (interp-num num base)
  22. (let-values
  23. ;; TODO: typed/racket does not support the `#:result' argument in `FOR/FOLD`?
  24. ([(sum pow)
  25. (for/fold ([sum : Integer 0]
  26. [pow : Integer 1])
  27. ([i (reverse num)])
  28. (values (+ sum (* i pow)) (* pow base)))])
  29. sum))
  30. ;; divide up the list into the sublists of size n.
  31. ;; E.g. `(div-list '(1 2 3 4 5) 3) => '((1 2 3) (4 5))' or
  32. ;; `(div-list '(1 2 3 4 5 6) 2) => '((1 2) (3 4) (5 6))'.
  33. (: div-list (All (A) (-> (Listof A) Integer (Listof (Listof A)))))
  34. (define (div-list lst n)
  35. (if (<= (length lst) n)
  36. (list lst)
  37. (let-values
  38. ([(a b) (split-at lst n)])
  39. (cons a (div-list b n)))))
  40. ;; calculate the permutations of the string as a list of coordinates
  41. (: permute-string (-> (Listof Integer) Integer (Listof (Listof Integer))))
  42. (define (permute-string str base)
  43. (for/list
  44. ([perm : (Listof Integer) (permutations str)])
  45. (map
  46. (lambda ([x : (Listof Integer)])
  47. (interp-num x base))
  48. (div-list perm (ceiling (/ (length str) 3))))))
  49. ;; Interpret a list of coordinate lists as a list of positions
  50. (: get-positions (-> (Listof (Listof Integer)) (Listof Pos)))
  51. (define (get-positions lst)
  52. (map
  53. (lambda ([p : (Listof Integer)])
  54. (match p
  55. [(list x y z) (pos x y z)]
  56. [(list x y) (pos x y x)]
  57. [(list x) (pos x x x)]))
  58. lst))
  59. ;; pick one element from a list, at random
  60. (: pick-one (All (A) (-> (Listof A) A)))
  61. (define (pick-one l)
  62. (list-ref l (random (length l))))
  63. (define (random-emitted)
  64. (pick-one
  65. (list default-emitted default-emitted
  66. (emitted "lightgreen" (/ 1 (+ 2 (random 5))))
  67. (emitted "blue" (/ 1 (+ 1 (random 5)))))))
  68. ;; Plot a collection of cubes at the given positions
  69. (: cubes (-> (Listof Pos) Pict3D))
  70. (define (cubes lst)
  71. (combine
  72. (map (lambda ([p : Pos])
  73. (set-emitted (cube p (pick-one '(1/3 1/2 1/3 2/5))) (random-emitted)))
  74. lst)))
  75. (define str "223345")
  76. (printf "Processing string ~s..~n" str)
  77. (define num (string->numbers str))
  78. (define base (calculate-base num))
  79. (define t
  80. (freeze (cubes (get-positions (permute-string num base)))))
  81. (define outer-pos 2102)
  82. ;; Place some lights at various places
  83. (define lights
  84. (combine (light (pos 0 0 0) (emitted "chocolate" 100))
  85. (light (pos (/ outer-pos 2) (/ outer-pos 2) (/ outer-pos 2)) (emitted "pink" 300))
  86. (light (pos (+ outer-pos 2) (+ outer-pos 2) (+ outer-pos 2)) (emitted "cyan" 200))
  87. (light (pos (+ outer-pos 2) -1 (+ outer-pos 2)) (emitted "blue" 170))
  88. (light (pos -1 (+ outer-pos 2) (+ outer-pos 2)) (emitted "red" 170))
  89. (light (pos (+ outer-pos 2) (+ outer-pos 2) 4) (emitted "green" 170))))
  90. (define t+lights (combine t lights))
  91. (current-pict3d-width 600)
  92. (current-pict3d-height 600)
  93. (current-pict3d-add-sunlight? #f)
  94. (current-pict3d-add-indicators? #f)
  95. (define t+sunlight
  96. (combine t
  97. (sunlight
  98. (dir (- (/ outer-pos 2)) (- outer-pos) (- (/ outer-pos 2)))
  99. (emitted "orange" 1/2))))
  100. (time (send (pict3d->bitmap t+sunlight 2000 2000)
  101. save-file
  102. "out.png" 'png))
  103. (displayln "Done, see out.png")