Advertisement
timothy235

sicp-2-2-4-the-drawing-program

Feb 23rd, 2016
232
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 9.23 KB | None | 0 0
  1. #lang racket
  2.  
  3. (require racket/draw)
  4.  
  5. ;; I can't get racket/draw to draw an image for me on windows.  However, you can
  6. ;; use this program to create an image and save it to file as outlined below.
  7. ;; Unfortunately you have to reload the file every time you want to make a new
  8. ;; image.
  9.  
  10. ;; To create a picture using racket/draw and save it to file:
  11.  
  12. ;; 1.  Create a bitmap:
  13. (define target (make-bitmap 640 640))
  14.  
  15. ;; 2.  Create a drawing context that draws to the bitmap:
  16. (define dc (new bitmap-dc% [bitmap target]))
  17.  
  18. ;; 3.  Create a special frame called canvas that fits the drawing context:
  19. (define canvas (make-frame (make-vect 0 0)
  20.                            (make-vect 640 0)
  21.                            (make-vect 0 640)))
  22.  
  23. ;; 4.  Call the painter on the canvas.  For example,
  24. ;; ((square-limit wave 4) canvas)
  25.  
  26. ;; 5.  Save the image to file:
  27. ;; (send target save-file "filename.png" 'png)
  28.  
  29. ;; NOTES:
  30.  
  31. ;; 1.  This only works with painters created by calling segments->painter.  In
  32. ;; fact the only place the drawing program calls racket/draw is in the
  33. ;; segments->painter function.
  34.  
  35. ;; 2.  racket/draw has the origin in the upper-left corner, x-coordinates get
  36. ;; bigger to the right, and y-coordinates get bigger as you go down the image.
  37.  
  38. ;; 3.  racket/draw requires the use of exact integers as coordinates.  This is why
  39. ;; we use a 640 x 640 frame and use fractions to describe unit-square vectors.
  40.  
  41. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  42.  
  43. ;; vectors, frames, and segments
  44.  
  45. ;; A vector is a list of x- and y-coordinates.
  46. (define (make-vect x y) (list x y))
  47. (define (xcor-vect v) (first v))
  48. (define (ycor-vect v) (second v))
  49. (define (add-vect v1 v2)
  50.   (make-vect
  51.     (+ (xcor-vect v1) (xcor-vect v2))
  52.     (+ (ycor-vect v1) (ycor-vect v2))))
  53. (define (sub-vect v1 v2)
  54.   (make-vect
  55.     (- (xcor-vect v1) (xcor-vect v2))
  56.     (- (ycor-vect v1) (ycor-vect v2))))
  57. (define (scale-vect s v)
  58.   (make-vect
  59.     (* s (xcor-vect v))
  60.     (* s (ycor-vect v))))
  61.  
  62. ;; A frame is a list of three vectors, an origin, an edge1, and an edge2.
  63. (define (make-frame origin edge1 edge2)
  64.   (list origin edge1 edge2))
  65. (define (origin-frame frame)
  66.   (first frame))
  67. (define (edge1-frame frame)
  68.   (second frame))
  69. (define (edge2-frame frame)
  70.   (third frame))
  71.  
  72. ;; A segment is a pair of vectors, a start segment and an end segment.
  73. (define (make-segment v1 v2)
  74.   (list v1 v2))
  75. (define (start-segment segment)
  76.   (first segment))
  77. (define (end-segment segment)
  78.   (second segment))
  79.  
  80. ;; create a painter
  81.  
  82. (define (segments->painter segment-list)
  83.   (lambda (frame)
  84.     (define m (frame-coord-map frame))
  85.     (map
  86.       (lambda (segment)
  87.         (define v1 (m (start-segment segment)))
  88.         (define v2 (m (end-segment segment)))
  89.         (send dc draw-line
  90.               (xcor-vect v1)
  91.               (ycor-vect v1)
  92.               (xcor-vect v2)
  93.               (ycor-vect v2)))
  94.       segment-list)))
  95.  
  96. ;; transform a painter to fit a frame
  97.  
  98. (define (my-identity painter)
  99.   painter)
  100.  
  101. (define (frame-coord-map frame)
  102.   (lambda (v) ; vectors in unit square -> vectors in frame
  103.     (add-vect
  104.       (origin-frame frame)
  105.       (add-vect (scale-vect (xcor-vect v)
  106.                             (edge1-frame frame))
  107.                 (scale-vect (ycor-vect v)
  108.                             (edge2-frame frame))))))
  109.  
  110. (define (transform-painter painter origin corner1 corner2)
  111.   (lambda (frame)
  112.     (define m (frame-coord-map frame))
  113.     (define new-origin (m origin))
  114.     (painter (make-frame new-origin
  115.                          (sub-vect (m corner1) new-origin)
  116.                          (sub-vect (m corner2) new-origin)))))
  117.  
  118. (define (flip-vert painter)
  119.   (transform-painter painter
  120.                      (make-vect 0 1)
  121.                      (make-vect 1 1)
  122.                      (make-vect 0 0)))
  123.  
  124. (define (flip-horiz painter)
  125.   (transform-painter painter
  126.                      (make-vect 1 0)
  127.                      (make-vect 0 0)
  128.                      (make-vect 1 1)))
  129.  
  130. (define (rotate90 painter)
  131.   (transform-painter painter
  132.                      (make-vect 0 1)
  133.                      (make-vect 0 0)
  134.                      (make-vect 1 1)))
  135.  
  136. (define (rotate180 painter)
  137.   (transform-painter painter
  138.                      (make-vect 1 1)
  139.                      (make-vect 0 1)
  140.                      (make-vect 1 0)))
  141.  
  142. (define (rotate270 painter)
  143.   (transform-painter painter
  144.                      (make-vect 1 0)
  145.                      (make-vect 1 1)
  146.                      (make-vect 0 0)))
  147.  
  148. ;; combining painters
  149.  
  150. (define (below painter1 painter2)
  151.   (define split-point (make-vect 0 1/2))
  152.   (define paint-below (transform-painter painter1
  153.                                          split-point
  154.                                          (make-vect 1 1/2)
  155.                                          (make-vect 0 1)))
  156.   (define paint-above (transform-painter painter2
  157.                                          (make-vect 0 0)
  158.                                          (make-vect 1 0)
  159.                                          split-point))
  160.   (lambda (frame)
  161.     (begin
  162.       (paint-below frame)
  163.       (paint-above frame))))
  164.  
  165. (define (beside painter1 painter2)
  166.   (define split-point (make-vect 1/2 0))
  167.   (define paint-left (transform-painter painter1
  168.                                         (make-vect 0 0)
  169.                                         split-point
  170.                                         (make-vect 0 1)))
  171.   (define paint-right (transform-painter painter2
  172.                                          split-point
  173.                                          (make-vect 1 0)
  174.                                          (make-vect 1/2 1)))
  175.   (lambda (frame)
  176.     (begin (paint-left frame)
  177.            (paint-right frame))))
  178.  
  179. (define (split comb1 comb2)
  180.   (lambda (painter n)
  181.     (cond [(zero? n) painter]
  182.           [else
  183.             (define smaller ((split comb1 comb2) painter (sub1 n)))
  184.             (comb1 painter (comb2 smaller smaller))])))
  185.  
  186. (define right-split (split beside below))
  187. (define up-split (split below beside))
  188.  
  189. (define (corner-split painter n)
  190.   (cond [(zero? n) painter]
  191.         [else
  192.           (define up (up-split painter (sub1 n)))
  193.           (define right (right-split painter (sub1 n)))
  194.           (define top-left (beside up up))
  195.           (define bottom-right (below right right))
  196.           (define corner (corner-split painter (sub1 n)))
  197.           (beside (below painter top-left)
  198.                   (below bottom-right corner))]))
  199.  
  200. (define (square-of-four tl tr bl br)
  201.   (lambda (painter)
  202.     (define top (beside (tl painter) (tr painter)))
  203.     (define bottom (beside (bl painter) (br painter)))
  204.     (below bottom top)))
  205.  
  206. (define (square-limit painter n)
  207.   (define combine4 (square-of-four flip-horiz
  208.                                    my-identity
  209.                                    rotate180
  210.                                    flip-vert))
  211.   (combine4 (corner-split painter n)))
  212.  
  213. ;; specific painters
  214.  
  215. (define outline-segments
  216.   (list (make-segment (make-vect 0 0)
  217.                       (make-vect 0 1))
  218.         (make-segment (make-vect 0 0)
  219.                       (make-vect 1 0))
  220.         (make-segment (make-vect 0 1)
  221.                       (make-vect 1 1))
  222.         (make-segment (make-vect 1 0)
  223.                       (make-vect 1 1))))
  224. (define outline-painter (segments->painter outline-segments))
  225.  
  226. (define x-segments
  227.   (list (make-segment (make-vect 0 0)
  228.                       (make-vect 1 1))
  229.         (make-segment (make-vect 0 1)
  230.                       (make-vect 1 0))))
  231. (define x-painter (segments->painter x-segments))
  232.  
  233. (define diamond-segments
  234.   (list (make-segment (make-vect 1/2 0)
  235.                       (make-vect 1 1/2))
  236.         (make-segment (make-vect 1 1/2)
  237.                       (make-vect 1/2 1))
  238.         (make-segment (make-vect 1/2 0)
  239.                       (make-vect 0 1/2))
  240.         (make-segment (make-vect 0 1/2)
  241.                       (make-vect 1/2 1))))
  242. (define diamond-painter (segments->painter diamond-segments))
  243.  
  244. (define wave-segments
  245.   (list
  246.     ; head
  247.     (make-segment (make-vect 3/8 0)
  248.                   (make-vect 5/8 0))
  249.     (make-segment (make-vect 3/8 0)
  250.                   (make-vect 3/8 1/4))
  251.     (make-segment (make-vect 3/8 1/4)
  252.                   (make-vect 5/8 1/4))
  253.     (make-segment (make-vect 5/8 0)
  254.                   (make-vect 5/8 1/4))
  255.     ; arms
  256.     (make-segment (make-vect 0 1/4)
  257.                   (make-vect 1 3/4))
  258.     ; body
  259.     (make-segment (make-vect 1/2 1/4)
  260.                   (make-vect 1/2 3/4))
  261.     ; legs
  262.     (make-segment (make-vect 1/4 1)
  263.                   (make-vect 1/2 3/4))
  264.     (make-segment (make-vect 1/2 3/4)
  265.                   (make-vect 3/4 1))))
  266. (define wave (segments->painter wave-segments))
  267.  
  268. ;; TRY THESE
  269.  
  270. ;; unfortunately you have to uncomment them out one at a time and reload between images
  271.  
  272. ;; ((up-split outline-painter 6) canvas)
  273. ;; (send target save-file "test-image-up-6-outline.png" 'png)
  274.  
  275. ;; ((right-split x-painter 6) canvas)
  276. ;; (send target save-file "test-image-right-6-x.png" 'png)
  277.  
  278. ;; ((corner-split diamond-painter 6) canvas)
  279. ;; (send target save-file "test-image-corner-6-diamond.png" 'png)
  280.  
  281. ;; ((square-limit wave 6) canvas)
  282. ;; (send target save-file "test-image-square-6-wave.png" 'png)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement