diff --git a/collects/2htdp/image.rkt b/collects/2htdp/image.rkt index d73e3be9b1..6f25be17a4 100644 --- a/collects/2htdp/image.rkt +++ b/collects/2htdp/image.rkt @@ -42,9 +42,14 @@ and they all have good sample contracts. (It is amazing what we can do with kids (provide-primitives overlay overlay/align + overlay/offset + overlay/align/offset overlay/xy + underlay underlay/align + underlay/offset + underlay/align/offset underlay/xy beside diff --git a/collects/2htdp/private/image-more.rkt b/collects/2htdp/private/image-more.rkt index 034e664431..eef7f82a29 100644 --- a/collects/2htdp/private/image-more.rkt +++ b/collects/2htdp/private/image-more.rkt @@ -328,6 +328,33 @@ #t) (cdr rst)))]))) +(define/chk (overlay/offset image1 dx dy image2) + (overlay/offset/internal 'middle 'middle image1 dx dy image2)) + +(define/chk (overlay/align/offset x-place y-place image1 dx dy image2) + (overlay/offset/internal x-place y-place image1 dx dy image2)) + +(define/chk (underlay/offset image1 dx dy image2) + (overlay/offset/internal 'middle 'middle image2 (- dx) (- dy) image1)) + +(define/chk (underlay/align/offset x-place y-place image1 dx dy image2) + (overlay/offset/internal x-place y-place image2 (- dx) (- dy) image1)) + +(define (overlay/offset/internal x-place y-place fst orig-dx orig-dy snd) + (let* ([fst-x-spot (find-x-spot x-place fst)] + [fst-y-spot (find-y-spot y-place fst)] + [snd-x-spot (find-x-spot x-place snd)] + [snd-y-spot (find-y-spot y-place snd)] + [dx (+ (- fst-x-spot snd-x-spot) orig-dx)] + [dy (+ (- fst-y-spot snd-y-spot) orig-dy)]) + (overlay/δ fst + (if (< dx 0) (- dx) 0) + (if (< dy 0) (- dy) 0) + snd + (if (< dx 0) 0 dx) + (if (< dy 0) 0 dy) + #t))) + ; ; @@ -403,20 +430,6 @@ (if (< dy 0) (- dy) 0) #f)))) -(define (overlay/offset image1 dx dy image2) - (overlay/offset/internal image1 dx dy image2 'middle 'middle)) - -(define (overlay/offset/internal image orig-dx orig-dy scene x-place y-place) - (let ([dx (- orig-dx (find-x-spot x-place image))] - [dy (- orig-dy (find-y-spot y-place image))]) - (overlay/δ image - (if (< dx 0) 0 dx) - (if (< dy 0) 0 dy) - scene - (if (< dx 0) (- dx) 0) - (if (< dy 0) (- dy) 0) - #f))) - (define/chk (scene+line image x1 y1 x2 y2 color) (let* ([dx (abs (min 0 x1 x2))] [dy (abs (min 0 y1 y2))]) @@ -1396,9 +1409,14 @@ (provide overlay overlay/align + overlay/offset + overlay/align/offset overlay/xy + underlay underlay/align + underlay/align/offset + underlay/offset underlay/xy beside diff --git a/collects/2htdp/tests/test-image.rkt b/collects/2htdp/tests/test-image.rkt index ab876a806e..9fbb447a85 100644 --- a/collects/2htdp/tests/test-image.rkt +++ b/collects/2htdp/tests/test-image.rkt @@ -675,12 +675,63 @@ (make-bb 100 100 100) #f)) +(test (overlay/offset (rectangle 10 100 'solid 'red) + 0 0 + (rectangle 100 10 'solid 'blue)) + => + (overlay (rectangle 10 100 'solid 'red) + (rectangle 100 10 'solid 'blue))) + +(test (overlay/align/offset "center" "center" + (rectangle 10 100 'solid 'red) + 0 0 + (rectangle 100 10 'solid 'blue)) + => + (overlay/align "center" "center" + (rectangle 10 100 'solid 'red) + (rectangle 100 10 'solid 'blue))) + +(test (overlay/align/offset "right" "top" + (rectangle 10 100 'solid 'red) + 0 0 + (rectangle 100 10 'solid 'blue)) + => + (overlay/align "right" "top" + (rectangle 10 100 'solid 'red) + (rectangle 100 10 'solid 'blue))) + +(test (underlay/offset (rectangle 10 100 'solid 'red) + 0 0 + (rectangle 100 10 'solid 'blue)) + => + (underlay (rectangle 10 100 'solid 'red) + (rectangle 100 10 'solid 'blue))) + +(test (underlay/align/offset "center" "center" + (rectangle 10 100 'solid 'red) + 0 0 + (rectangle 100 10 'solid 'blue)) + => + (underlay/align "center" "center" + (rectangle 10 100 'solid 'red) + (rectangle 100 10 'solid 'blue))) + +(test (underlay/align/offset "left" "bottom" + (rectangle 10 100 'solid 'red) + 0 0 + (rectangle 100 10 'solid 'blue)) + => + (underlay/align "left" "bottom" + (rectangle 10 100 'solid 'red) + (rectangle 100 10 'solid 'blue))) + (test (empty-scene 185 100) => (crop 0 0 185 100 (overlay (rectangle 185 100 'outline (pen "black" 2 'solid 'round 'round)) (rectangle 185 100 'solid 'white)))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; testing normalization diff --git a/collects/teachpack/2htdp/scribblings/image.scrbl b/collects/teachpack/2htdp/scribblings/image.scrbl index 8f5faf98c6..46dcd28f21 100644 --- a/collects/teachpack/2htdp/scribblings/image.scrbl +++ b/collects/teachpack/2htdp/scribblings/image.scrbl @@ -660,14 +660,59 @@ the @scheme[point-count] argument determines how many points the star has. } +@defproc[(overlay/offset [i1 image?] [x real?] [y real?] [i2 image?]) image?]{ + Just like @racket[overlay], this function lines up its image arguments on top of + each other. Unlike @racket[overlay], it moves @racket[i2] by @racket[x] pixels to + the right and @racket[y] down before overlaying them. + + @image-examples[(overlay/offset (circle 40 "solid" "red") + 10 10 + (circle 40 "solid" "blue")) + + (overlay/offset (overlay/offset (rectangle 60 20 "solid" "black") + -50 0 + (circle 20 "solid" "darkorange")) + 70 0 + (circle 20 "solid" "darkorange")) + (overlay/offset + (overlay/offset (circle 30 'solid (color 0 150 0 127)) + 26 0 + (circle 30 'solid (color 0 0 255 127))) + 0 26 + (circle 30 'solid (color 200 0 0 127)))] +} + +@defproc[(overlay/align/offset [x-place x-place?] [y-place y-place?] [i1 image?] [x real?] [y real?] [i2 image?]) + image?]{ + Overlays image @racket[i1] on top of @racket[i2], using @racket[x-place] and @racket[y-place] as the + starting points for the overlaying, and then adjusts @racket[i2] by @racket[x] to the right and + @racket[y] pixels down. + + This function combines the capabilities of @racket[overlay/align] and @racket[overlay/offset]. + + @image-examples[(overlay/align/offset + "right" "bottom" + (star-polygon 20 20 3 "solid" "navy") + 10 10 + (circle 30 "solid" "cornflowerblue")) + (overlay/align/offset + "left" "bottom" + (star-polygon 20 20 3 "solid" "navy") + -10 10 + (circle 30 "solid" "cornflowerblue"))] + +} + @defproc[(overlay/xy [i1 image?] [x real?] [y real?] [i2 image?]) image?]{ Constructs an image by overlaying @racket[i1] on top of @racket[i2]. The images are initially lined up on their upper-left corners and then @racket[i2] is shifted to the right by @racket[x] pixels to and down by @racket[y] pixels. - - This is the same as @racket[(underlay/xy i2 (- x) (- y) i1)]. + This is the same as @racket[(underlay/xy i2 (- x) (- y) i1)]. + + See also @racket[overlay/offset] and @racket[underlay/offset]. + @image-examples[(overlay/xy (rectangle 20 20 "outline" "black") 20 0 (rectangle 20 20 "outline" "black")) @@ -684,13 +729,7 @@ the @scheme[point-count] argument determines how many points the star has. (ellipse 10 10 "solid" "forestgreen")) 20 15 - (ellipse 10 10 "solid" "forestgreen")) - (overlay/xy - (overlay/xy (circle 30 'solid (color 0 150 0 127)) - 26 0 - (circle 30 'solid (color 0 0 255 127))) - 13 26 - (circle 30 'solid (color 200 0 0 127)))] + (ellipse 10 10 "solid" "forestgreen"))] } @defproc[(underlay [i1 image?] [i2 image?] [is image?] ...) image?]{ @@ -741,6 +780,56 @@ the @scheme[point-count] argument determines how many points the star has. } + +@defproc[(underlay/offset [i1 image?] [x real?] [y real?] [i2 image?]) image?]{ + Just like @racket[overlay], this function lines up its image arguments on top of + each other. Unlike @racket[overlay], it moves @racket[i2] by @racket[x] pixels to + the right and @racket[y] down before overlaying them. + + @image-examples[(underlay/offset (circle 40 "solid" "red") + 10 10 + (circle 40 "solid" "blue")) + + (underlay/offset (circle 40 "solid" "gray") + 0 -10 + (underlay/offset (circle 10 "solid" "navy") + -30 0 + (circle 10 "solid" "navy")))] +} + +@defproc[(underlay/align/offset [x-place x-place?] [y-place y-place?] [i1 image?] [x real?] [y real?] [i2 image?]) + image?]{ + Underlays image @racket[i1] underneath @racket[i2], using @racket[x-place] and @racket[y-place] as the + starting points for the combination, and then adjusts @racket[i2] by @racket[x] to the right and + @racket[y] pixels down. + + This function combines the capabilities of @racket[underlay/align] and @racket[underlay/offset]. + + @image-examples[(underlay/align/offset + "right" "bottom" + (star-polygon 20 20 3 "solid" "navy") + 10 10 + (circle 30 "solid" "cornflowerblue")) + (underlay/align/offset + "right" "bottom" + (underlay/align/offset + "left" "bottom" + (underlay/align/offset + "right" "top" + (underlay/align/offset + "left" "top" + (rhombus 120 90 "solid" "navy") + 16 16 + (star-polygon 20 11 3 "solid" "cornflowerblue")) + -16 16 + (star-polygon 20 11 3 "solid" "cornflowerblue")) + 16 -16 + (star-polygon 20 11 3 "solid" "cornflowerblue")) + -16 -16 + (star-polygon 20 11 3 "solid" "cornflowerblue"))] + +} + @defproc[(underlay/xy [i1 image?] [x real?] [y real?] [i2 image?]) image?]{ Constructs an image by underlaying @racket[i1] underneath @racket[i2]. The images are initially lined up on their upper-left corners and @@ -749,6 +838,8 @@ the @scheme[point-count] argument determines how many points the star has. This is the same as @racket[(overlay/xy i2 (- x) (- y) i1)]. + See also @racket[underlay/offset] and @racket[overlay/offset]. + @image-examples[(underlay/xy (rectangle 20 20 "outline" "black") 20 0 (rectangle 20 20 "outline" "black"))