-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy path09-4-shapes-separate-functions.rkt
executable file
·102 lines (80 loc) · 3.22 KB
/
09-4-shapes-separate-functions.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#lang scheme
;; 09-4-shapes-separate-functions.rkt
;; this version uses separate functions for dispatch and operation
(require rackunit)
(require "extras.rkt")
(require 2htdp/image)
(define-struct my-circle (x y r color) #:transparent)
(define-struct my-square (x y l color) #:transparent)
(define-struct my-composite (front back) #:transparent)
;; A Shape is one of
;; -- (make-my-circle Number Number Number ColorString)
;; -- (make-my-square Number Number Number ColorString)
;; -- (make-my-composite Shape Shape)
;; interp:
;; (x,y) is position in pixels (of center for circle, of UL corner for square)
;; r is radius of circle in pixels
;; l is length of side of square, in pixels
;; c is color, expressed as a ColorString.
;; in my-composite, front is the shape in front, back is the shape in back.
;; weight : Shape -> Number
;; GIVEN: a shape
;; RETURNS: the weight of the shape, assuming that each shape weighs 1
;; gram per pixel of area.
;; STRATEGY: Use template for Shape
(define (weight s)
(cond
[(my-circle? s) (my-circle-weight s)]
[(my-square? s) (my-square-weight s)]
[(my-composite? s) (my-composite-weight s)]))
;; my-circle-weight, my-square-weight, my-composite-weight : Shape -> Number
;; GIVEN: a shape
;; WHERE: the shape is of the specified variant
;; RETURNS: the weight of the shape, assuming that each shape weighs 1
;; gram per pixel of area.
(define (my-circle-weight s) (* pi (my-circle-r s) (my-circle-r s)))
(define (my-square-weight s) (* (my-square-l s) (my-square-l s)))
(define (my-composite-weight s) (+ (weight (my-composite-front s))
(weight (my-composite-back s))))
;; add-to-scene : Shape Scene -> Scene
;; RETURNS: a scene like the given one, but with the given shape
;; painted on it.
(define (add-to-scene s scene)
(cond
[(my-circle? s) (my-circle-add-to-scene s scene)]
[(my-square? s) (my-square-add-to-scene s scene)]
[(my-composite? s) (my-composite-add-to-scene s scene)]))
;; my-circle-add-to-scene, my-square-add-to-scene,
;; my-composite-add-to-scene : Shape Scene
;; GIVEN: A shape and a scene
;; WHERE: the shape is of the specified variant
;; RETURNS: a scene like the given one, but with the given shape
;; painted on it.
;; STRATEGY: Structural Decomposition on each struct
(define (my-circle-add-to-scene s scene)
(local
((define IMG (circle (my-circle-r s) "solid" (my-circle-color s))))
(place-image IMG
(my-circle-x s)
(my-circle-y s)
scene)))
(define (my-square-add-to-scene s scene)
(local
((define IMG (square (my-square-l s) "solid" (my-square-color s))))
(place-image IMG
(my-square-x s)
(my-square-y s)
scene)))
(define (my-composite-add-to-scene s scene)
;; paint the back image first, then the front image
(add-to-scene (my-composite-front s)
(add-to-scene (my-composite-back s)
scene)))
(define EMPTY-CANVAS (empty-scene 200 100))
(define s1 (make-my-circle 50 20 40 "red"))
(define s2 (make-my-square 80 70 40 "blue"))
(define s3 (make-my-composite s1 s2))
(begin-for-test
(check-= (weight s1) (* pi 1600) .1)
(check-equal? (weight s2) 1600)
(check-= (weight s3) (+ (* pi 1600) 1600) .1))