From f5bb840950885cb915408d8d95b7f98f55979952 Mon Sep 17 00:00:00 2001 From: Robby Findler Date: Mon, 4 Jan 2010 01:39:09 +0000 Subject: [PATCH] added cropping to 2htdp/image svn: r17474 --- collects/2htdp/image.ss | 1 + collects/2htdp/private/image-more.ss | 199 +++++++++++------- collects/2htdp/tests/test-image.ss | 152 +++++++++---- collects/mrlib/image-core.ss | 105 ++++++--- .../teachpack/2htdp/scribblings/image-gen.ss | 3 + .../teachpack/2htdp/scribblings/image-toc.ss | 22 +- .../teachpack/2htdp/scribblings/image.scrbl | 20 +- .../2htdp/scribblings/img/157ab5efca7.png | Bin 179 -> 161 bytes .../2htdp/scribblings/img/164b8da7bf6.png | Bin 0 -> 1808 bytes .../2htdp/scribblings/img/201c231dce2.png | Bin 965 -> 983 bytes .../2htdp/scribblings/img/26bd803042c.png | Bin 117 -> 118 bytes .../2htdp/scribblings/img/28253f4c3c.png | Bin 1648 -> 1698 bytes .../2htdp/scribblings/img/2d1e52503d7.png | Bin 1085 -> 1070 bytes .../2htdp/scribblings/img/42f9f9e4cf.png | Bin 178 -> 159 bytes .../2htdp/scribblings/img/6c262f1d24.png | Bin 0 -> 533 bytes .../2htdp/scribblings/img/8e7c1870c7.png | Bin 0 -> 529 bytes .../2htdp/scribblings/img/9858b8d5d.png | Bin 1144 -> 1135 bytes .../2htdp/scribblings/img/ff2fcb7b87.png | Bin 354 -> 345 bytes 18 files changed, 356 insertions(+), 146 deletions(-) create mode 100644 collects/teachpack/2htdp/scribblings/img/164b8da7bf6.png create mode 100644 collects/teachpack/2htdp/scribblings/img/6c262f1d24.png create mode 100644 collects/teachpack/2htdp/scribblings/img/8e7c1870c7.png diff --git a/collects/2htdp/image.ss b/collects/2htdp/image.ss index f06b0b6675..6d1916580c 100644 --- a/collects/2htdp/image.ss +++ b/collects/2htdp/image.ss @@ -63,6 +63,7 @@ and they all have good sample contracts. (It is amazing what we can do with kids above above/align + crop rotate frame diff --git a/collects/2htdp/private/image-more.ss b/collects/2htdp/private/image-more.ss index 5fffad51ff..70cebcd30e 100644 --- a/collects/2htdp/private/image-more.ss +++ b/collects/2htdp/private/image-more.ss @@ -258,6 +258,18 @@ ; ; +;; crop : number number number number image -> image +;; crops an image to be w x h from (x,y) +(define/chk (crop x1 y1 width height image) + (let ([iw (min width (image-width image))] + [ih (min height (image-height image))]) + (make-image (make-crop (rectangle-points iw ih) + (make-translate (- x1) (- y1) (image-shape image))) + (make-bb iw + ih + (min ih (image-baseline image))) + #f))) + ;; frame : image -> image ;; draws a black frame around a image where the bounding box is ;; (useful for debugging images) @@ -282,24 +294,79 @@ ;; (in degrees) ;; LINEAR TIME OPERATION (sigh) (define/chk (rotate angle image) - (define left +inf.0) - (define top +inf.0) - (define right -inf.0) - (define bottom -inf.0) - (define (add-to-bounding-box/rotate simple-shape) - (let ([rotated-shape (rotate-simple angle simple-shape)]) - (let-values ([(this-left this-top this-right this-bottom) (simple-bb rotated-shape)]) - (set! left (min this-left left)) - (set! top (min this-top top)) - (set! right (max this-right right)) - (set! bottom (max this-bottom bottom))) - rotated-shape)) - (let* ([rotated (normalize-shape (image-shape image) add-to-bounding-box/rotate)]) - (make-image (make-translate (- left) (- top) rotated) - (make-bb (- right left) (- bottom top) (- bottom top)) + (let-values ([(rotated-shape ltrb) + (rotate-normalized-shape/bb angle + (normalize-shape (image-shape image)))]) + + (make-image (make-translate (- (ltrb-left ltrb)) (- (ltrb-top ltrb)) rotated-shape) + (make-bb (- (ltrb-right ltrb) (ltrb-left ltrb)) + (- (ltrb-bottom ltrb) (ltrb-top ltrb)) + (- (ltrb-bottom ltrb) (ltrb-top ltrb))) #f))) -;; simple-bb : simple-shape -> (values number number number number) +;; rotate-normalized-shape/bb : angle normalized-shape -> (values normalized-shape ltrb) +(define (rotate-normalized-shape/bb angle shape) + (cond + [(overlay? shape) + (let-values ([(top-shape top-ltrb) (rotate-normalized-shape/bb angle (overlay-top shape))] + [(bottom-shape bottom-ltrb) (rotate-simple/bb angle (overlay-bottom shape))]) + (values (make-overlay top-shape bottom-shape) + (union-ltrb top-ltrb bottom-ltrb)))] + [else + (rotate-cropped-simple/bb angle shape)])) + +;; rotate-cropped-shape/bb : angle cropped-simple-shape -> (values cropped-simple-shape ltrb) +(define (rotate-cropped-simple/bb angle shape) + (cond + [(crop? shape) + (let-values ([(rotated-shape ltrb) (rotate-cropped-simple/bb angle (crop-shape shape))]) + (let* ([rotated-points (rotate-points angle (crop-points shape))] + [crop-ltrb (points->ltrb rotated-points)]) + (values (make-crop rotated-points rotated-shape) + (intersect-ltrb crop-ltrb ltrb))))] + [else + (rotate-simple/bb angle shape)])) + +;; rotate-simple/bb : angle simple-shape -> (values simple-shape ltrb) +(define (rotate-simple/bb angle shape) + (let ([rotated-shape (rotate-simple angle shape)]) + (values rotated-shape (simple-bb rotated-shape)))) + +;; rotate-simple : angle simple-shape -> simple-shape +(define (rotate-simple θ simple-shape) + (cond + [(line-segment? simple-shape) + (make-line-segment (rotate-point (line-segment-start simple-shape) + θ) + (rotate-point (line-segment-end simple-shape) + θ) + (line-segment-color simple-shape))] + [(polygon? simple-shape) + (make-polygon (rotate-points θ (polygon-points simple-shape)) + (polygon-mode simple-shape) + (polygon-color simple-shape))] + [else + (let* ([unrotated (translate-shape simple-shape)] + [rotated (rotate-atomic θ unrotated)]) + (let-values ([(dx dy) + (c->xy (* (make-polar 1 (degrees->radians θ)) + (xy->c (translate-dx simple-shape) + (translate-dy simple-shape))))]) + (make-translate dx dy rotated)))])) + +(define-struct ltrb (left top right bottom)) +(define (union-ltrb ltrb1 ltrb2) + (make-ltrb (min (ltrb-left ltrb1) (ltrb-left ltrb2)) + (min (ltrb-top ltrb1) (ltrb-top ltrb2)) + (max (ltrb-right ltrb1) (ltrb-right ltrb2)) + (max (ltrb-bottom ltrb1) (ltrb-bottom ltrb2)))) +(define (intersect-ltrb ltrb1 ltrb2) + (make-ltrb (max (ltrb-left ltrb1) (ltrb-left ltrb2)) + (max (ltrb-top ltrb1) (ltrb-top ltrb2)) + (min (ltrb-right ltrb1) (ltrb-right ltrb2)) + (min (ltrb-bottom ltrb1) (ltrb-bottom ltrb2)))) + +;; simple-bb : simple-shape -> ltrb ;; returns the bounding box of 'shape' ;; (only called for rotated shapes, so bottom=baseline) (define (simple-bb simple-shape) @@ -309,36 +376,38 @@ [y1 (point-y (line-segment-start simple-shape))] [x2 (point-x (line-segment-end simple-shape))] [y2 (point-y (line-segment-end simple-shape))]) - (values (min x1 x2) - (min y1 y2) - (+ (max x1 x2) 1) - (+ (max y1 y2) 1)))] + (make-ltrb (min x1 x2) + (min y1 y2) + (+ (max x1 x2) 1) + (+ (max y1 y2) 1)))] [(polygon? simple-shape) - (let ([points (polygon-points simple-shape)]) - (let* ([fx (point-x (car points))] - [fy (point-y (car points))] - [left fx] - [top fy] - [right fx] - [bottom fy]) - (for-each (λ (point) - (let ([new-x (point-x point)] - [new-y (point-y point)]) - (set! left (min new-x left)) - (set! top (min new-y top)) - (set! right (max new-x right)) - (set! bottom (max new-y bottom)))) - (cdr points)) - (values left top right bottom)))] + (points->ltrb (polygon-points simple-shape))] [else (let ([dx (translate-dx simple-shape)] [dy (translate-dy simple-shape)]) (let-values ([(l t r b) (np-atomic-bb (translate-shape simple-shape))]) - (values (+ l dx) - (+ t dy) - (+ r dx) - (+ b dy))))])) + (make-ltrb (+ l dx) + (+ t dy) + (+ r dx) + (+ b dy))))])) +;; points->ltrb : (cons point (listof points)) -> (values number number number number) +(define (points->ltrb points) + (let* ([fx (point-x (car points))] + [fy (point-y (car points))] + [left fx] + [top fy] + [right fx] + [bottom fy]) + (for-each (λ (point) + (let ([new-x (point-x point)] + [new-y (point-y point)]) + (set! left (min new-x left)) + (set! top (min new-y top)) + (set! right (max new-x right)) + (set! bottom (max new-y bottom)))) + (cdr points)) + (make-ltrb left top right bottom))) (define (np-atomic-bb atomic-shape) (cond @@ -376,28 +445,7 @@ (max ax bx cx dx) (max ay by cy dy)))) -;; rotate-simple : angle simple-shape -> simple-shape -(define (rotate-simple θ simple-shape) - (cond - [(line-segment? simple-shape) - (make-line-segment (rotate-point (line-segment-start simple-shape) - θ) - (rotate-point (line-segment-end simple-shape) - θ) - (line-segment-color simple-shape))] - [(polygon? simple-shape) - (make-polygon (map (λ (p) (rotate-point p θ)) - (polygon-points simple-shape)) - (polygon-mode simple-shape) - (polygon-color simple-shape))] - [else - (let* ([unrotated (translate-shape simple-shape)] - [rotated (rotate-atomic θ unrotated)]) - (let-values ([(dx dy) - (c->xy (* (make-polar 1 (degrees->radians θ)) - (xy->c (translate-dx simple-shape) - (translate-dy simple-shape))))]) - (make-translate dx dy rotated)))])) +(define (rotate-points θ points) (map (λ (p) (rotate-point p θ)) points)) (define (center-point np-atomic-shape) (let-values ([(l t r b) (np-atomic-bb np-atomic-shape)]) @@ -515,11 +563,11 @@ mode color))) -(define (rectangle-points width height) - (list (make-point 0 0) - (make-point width 0) - (make-point width height) - (make-point 0 height))) +(define (rectangle-points width height [dx 0] [dy 0]) + (list (make-point dx dy) + (make-point (+ dx width) dy) + (make-point (+ dx width) (+ height dy)) + (make-point dx (+ dy height)))) (define/chk (line x1 y1 color) @@ -631,11 +679,15 @@ mode color)) (define (make-a-polygon points mode color) - (let ([poly (make-polygon points mode color)]) - (let-values ([(l t r b) (simple-bb poly)]) - (make-image (make-translate (- l) (- t) poly) - (make-bb (- r l) (- b t) (- b t)) - #f)))) + (let* ([poly (make-polygon points mode color)] + [ltrb (simple-bb poly)] + [l (ltrb-left ltrb)] + [t (ltrb-top ltrb)] + [r (ltrb-right ltrb)] + [b (ltrb-bottom ltrb)]) + (make-image (make-translate (- l) (- t) poly) + (make-bb (- r l) (- b t) (- b t)) + #f))) (define (gcd a b) (cond [(zero? b) a] @@ -761,7 +813,8 @@ above/align rotate - + crop + frame show-image diff --git a/collects/2htdp/tests/test-image.ss b/collects/2htdp/tests/test-image.ss index b853a33b81..513e7f0bae 100644 --- a/collects/2htdp/tests/test-image.ss +++ b/collects/2htdp/tests/test-image.ss @@ -1,4 +1,17 @@ #lang scheme/base +#| +;; snippet of code for experimentation +(define images + (list (round-numbers (rotate 180 (line 20 30 "red"))) + (round-numbers (line 20 30 "red")))) + +(define t (new text%)) +(define f (new frame% [label ""] [width 600] [height 400])) +(define ec (new editor-canvas% [parent f] [editor t])) +(for ((i (in-list images))) (send t insert i)) +(send f show #t) +|# + (require "../../mrlib/image-core.ss" "../private/image-more.ss" "../private/img-err.ss" @@ -599,6 +612,32 @@ => (make-translate 135 170 (make-ellipse 50 100 0 'solid "blue"))) +(test (normalize-shape (image-shape + (beside (rectangle 10 10 'solid 'black) + (crop 0 0 5 5 (rectangle 10 10 'solid 'green))))) + => + (make-overlay + (make-polygon + (list (make-point 0 0) + (make-point 10 0) + (make-point 10 10) + (make-point 0 10)) + 'solid + "black") + (make-crop + (list (make-point 10 0) + (make-point 15 0) + (make-point 15 5) + (make-point 10 5)) + (make-polygon + (list (make-point 10 0) + (make-point 20 0) + (make-point 20 10) + (make-point 10 10)) + 'solid + "green")))) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; @@ -764,11 +803,13 @@ ;; ;; note: the regular-polygon and the rectangle generate the points in reverse directions. -(check-equal? (round-numbers (regular-polygon 100 4 'outline 'green)) - (round-numbers (rectangle 100 100 'outline 'green))) +(test (round-numbers (regular-polygon 100 4 'outline 'green)) + => + (round-numbers (rectangle 100 100 'outline 'green))) -(check-equal? (swizzle (list 0 1 2 3 4) 2) - (list 0 2 4 1 3)) +(test (swizzle (list 0 1 2 3 4) 2) + => + (list 0 2 4 1 3)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -776,42 +817,48 @@ ;; text ;; -(check-equal? (beside/align "baseline" - (text "a" 18 "black") - (text "b" 18 "black")) - (text "ab" 18 "black")) +(test (beside/align "baseline" + (text "a" 18 "black") + (text "b" 18 "black")) + => + (text "ab" 18 "black")) -(check-equal? (round-numbers - (image-width (rotate 45 (text "One" 18 'black)))) - (round-numbers - (let ([t (text "One" 18 'black)]) - (image-width (rotate 45 (rectangle (image-width t) - (image-height t) - 'solid 'black)))))) +(test (round-numbers + (image-width (rotate 45 (text "One" 18 'black)))) + => + (round-numbers + (let ([t (text "One" 18 'black)]) + (image-width (rotate 45 (rectangle (image-width t) + (image-height t) + 'solid 'black)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; triangle ;; -(check-equal? (round-numbers (rotate 180 (isosceles-triangle 60 330 "solid" "lightseagreen"))) - (round-numbers (isosceles-triangle 60 30 "solid" "lightseagreen"))) +(test (round-numbers (rotate 180 (isosceles-triangle 60 330 "solid" "lightseagreen"))) + => + (round-numbers (isosceles-triangle 60 30 "solid" "lightseagreen"))) -(check-equal? (triangle 40 'outline 'black) - (regular-polygon 40 3 'outline 'black)) +(test (triangle 40 'outline 'black) + => + (regular-polygon 40 3 'outline 'black)) -(check-equal? (equal~? (rotate (+ 180 45) (right-triangle 50 50 'solid 'black)) - (isosceles-triangle 50 90 'solid 'black) - 0.001) - #t) +(test (equal~? (rotate (+ 180 45) (right-triangle 50 50 'solid 'black)) + (isosceles-triangle 50 90 'solid 'black) + 0.001) + => + #t) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; square ;; -(check-equal? (square 10 'solid 'black) - (rectangle 10 10 'solid 'black)) +(test (square 10 'solid 'black) + => + (rectangle 10 10 'solid 'black)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -819,28 +866,33 @@ ;; rhombus ;; -(check-equal? (equal~? (rhombus 10 90 'solid 'black) - (rotate 45 (square 10 'solid 'black)) - 0.01) - #t) +(test (equal~? (rhombus 10 90 'solid 'black) + (rotate 45 (square 10 'solid 'black)) + 0.01) + => + #t) -(check-equal? (equal~? (rhombus 50 150 'solid 'black) - (rotate 90 (rhombus 50 30 'solid 'black)) - 0.01) - #t) +(test (equal~? (rhombus 50 150 'solid 'black) + (rotate 90 (rhombus 50 30 'solid 'black)) + 0.01) + => + #t) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; lines ;; -(check-equal? (image-width (line 10 20 'black)) - 11) -(check-equal? (image-height (line 10 20 'black)) - 21) +(test (image-width (line 10 20 'black)) + => + 11) +(test (image-height (line 10 20 'black)) + => + 21) -(check-equal? (round-numbers (rotate 90 (line 10 20 'black))) - (round-numbers (line 20 -10 'black))) +(test (round-numbers (rotate 90 (line 10 20 'black))) + => + (round-numbers (line 20 -10 'black))) (check-equal? (round-numbers (line 20 30 "red")) (round-numbers (rotate 180 (line 20 30 "red")))) @@ -984,3 +1036,25 @@ (check-equal? (begin (scale 2 (make-object bitmap% 10 10)) (void)) (void)) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; cropping +;; + +(test (crop 0 0 10 10 (rectangle 20 20 'solid 'black)) + => + (rectangle 10 10 'solid 'black)) + +(test (equal~? (crop 0 0 40 40 (circle 40 'solid 'red)) + (rotate 180 (crop 40 40 40 40 (circle 40 'solid 'red))) + 0.1) + => + #t) + +(test (beside (rectangle 10 10 'solid 'black) + (crop 0 0 10 10 (rectangle 10 10 'solid 'green))) + => + (beside (rectangle 10 10 'solid 'black) + (rectangle 10 10 'solid 'green))) diff --git a/collects/mrlib/image-core.ss b/collects/mrlib/image-core.ss index b1b0e9d081..8e42f4fd54 100644 --- a/collects/mrlib/image-core.ss +++ b/collects/mrlib/image-core.ss @@ -117,6 +117,9 @@ has been moved out). ;; - (make-scale x-factor y-factor shape) (define-struct/reg-mk scale (x y shape) #:transparent #:omit-define-syntaxes) ;; +;; - (make-crop (listof vector) shape) +(define-struct/reg-mk crop (points shape) #:transparent #:omit-define-syntaxes) +;; ;; - atomic-shape ;; an atomic-shape is either: @@ -160,11 +163,15 @@ has been moved out). (λ (x y) 42) (λ (x y) 3))) ;; a normalized-shape (subtype of shape) is either -;; - (make-overlay normalized-shape simple-shape) +;; - (make-overlay normalized-shape cropped-simple-shape) +;; - cropped-simple-shape + +;; a cropped-simple-shape is either +;; - (make-crop (listof points) cropped-simple-shape) ;; - simple-shape ;; a simple-shape (subtype of shape) is -;; - (make-translate dx dy np-atomic-shape) +;; - (make-translate dx dy np-atomic-shape)) ;; - polygon ;; - line-segment @@ -275,7 +282,7 @@ has been moved out). (define/public (get-normalized-shape) (unless normalized? - (set! shape (normalize-shape shape values)) + (set! shape (normalize-shape shape)) (set! normalized? #t)) shape) @@ -395,10 +402,16 @@ has been moved out). [dy 0] [x-scale 1] [y-scale 1] + [crops '()] ;; (listof (listof point)) [bottom #f]) (define (scale-point p) (make-point (+ dx (* x-scale (point-x p))) (+ dy (* y-scale (point-y p))))) + (define (add-crops shape) + (let loop ([crops crops]) + (cond + [(null? crops) shape] + [else (make-crop (car crops) (loop (cdr crops)))]))) (cond [(translate? shape) (loop (translate-shape shape) @@ -406,6 +419,7 @@ has been moved out). (+ dy (* y-scale (translate-dy shape))) x-scale y-scale + crops bottom)] [(scale? shape) (loop (scale-shape shape) @@ -413,30 +427,41 @@ has been moved out). dy (* x-scale (scale-x shape)) (* y-scale (scale-y shape)) + crops bottom)] [(overlay? shape) (loop (overlay-bottom shape) - dx dy x-scale y-scale + dx dy x-scale y-scale crops (loop (overlay-top shape) - dx dy x-scale y-scale bottom))] + dx dy x-scale y-scale crops + bottom))] + [(crop? shape) + (loop (crop-shape shape) + dx dy x-scale y-scale + (cons (map scale-point (crop-points shape)) crops) + bottom)] [(polygon? shape) (let* ([this-one - (make-polygon (map scale-point (polygon-points shape)) - (polygon-mode shape) - (polygon-color shape))]) + (add-crops + (make-polygon (map scale-point (polygon-points shape)) + (polygon-mode shape) + (polygon-color shape)))]) (if bottom (make-overlay bottom (f this-one)) (f this-one)))] [(line-segment? shape) (let ([this-one - (make-line-segment (scale-point (line-segment-start shape)) - (scale-point (line-segment-end shape)) - (line-segment-color shape))]) + (add-crops + (make-line-segment (scale-point (line-segment-start shape)) + (scale-point (line-segment-end shape)) + (line-segment-color shape)))]) (if bottom (make-overlay bottom (f this-one)) (f this-one)))] [(np-atomic-shape? shape) - (let ([this-one (make-translate dx dy (scale-np-atomic x-scale y-scale shape))]) + (let ([this-one + (add-crops + (make-translate dx dy (scale-np-atomic x-scale y-scale shape)))]) (if bottom (make-overlay bottom (f this-one)) (f this-one)))] @@ -510,7 +535,7 @@ has been moved out). ; ; -;; render-image : normalized-shape dc dx dy -> void +;; render-image : image dc dx dy -> void (define (render-image image dc dx dy) (let ([pen (send dc get-pen)] [brush (send dc get-brush)] @@ -519,33 +544,33 @@ has been moved out). (let loop ([shape (send image get-normalized-shape)]) (cond [(overlay? shape) - (render-simple-shape (overlay-bottom shape) dc dx dy) + (render-cropped-simple-shape (overlay-bottom shape) dc dx dy) (loop (overlay-top shape))] [else - (render-simple-shape shape dc dx dy)])) + (render-cropped-simple-shape shape dc dx dy)])) (send dc set-pen pen) (send dc set-brush brush) (send dc set-font font) (send dc set-text-foreground fg))) +(define (render-cropped-simple-shape shape dc dx dy) + (cond + [(crop? shape) + (let ([old-region (send dc get-clipping-region)] + [new-region (new region% [dc dc])] + [path (polygon-points->path (crop-points shape))]) + (send new-region set-path path dx dy) + (when old-region (send new-region intersect old-region)) + (send dc set-clipping-region new-region) + (render-cropped-simple-shape (crop-shape shape) dc dx dy) + (send dc set-clipping-region old-region))] + [else + (render-simple-shape shape dc dx dy)])) + (define (render-simple-shape simple-shape dc dx dy) (cond [(polygon? simple-shape) - (let ([path (new dc-path%)] - [points (polygon-points simple-shape)]) - (send path move-to (point-x (car points)) (point-y (car points))) - (let loop ([point (make-rectangular (point-x (car points)) (point-y (car points)))] - [last-point (car points)] - [points (cdr points)]) - (unless (null? points) - (let* ([vec (make-rectangular (- (point-x (car points)) - (point-x last-point)) - (- (point-y (car points)) - (point-y last-point)))] - [endpoint (+ point vec (make-polar -1 (angle vec)))]) - (send path line-to (real-part endpoint) (imag-part endpoint)) - (loop endpoint (car points) (cdr points))))) - (send path line-to (point-x (car points)) (point-y (car points))) + (let ([path (polygon-points->path (polygon-points simple-shape))]) (send dc set-pen (mode-color->pen (polygon-mode simple-shape) (polygon-color simple-shape))) (send dc set-brush (mode-color->brush (polygon-mode simple-shape) (polygon-color simple-shape))) (send dc draw-path path dx dy 'winding))] @@ -599,6 +624,23 @@ has been moved out). (imag-part p) #f 0 θ))))]))])) +(define (polygon-points->path points) + (let ([path (new dc-path%)]) + (send path move-to (point-x (car points)) (point-y (car points))) + (let loop ([point (make-rectangular (point-x (car points)) (point-y (car points)))] + [last-point (car points)] + [points (cdr points)]) + (unless (null? points) + (let* ([vec (make-rectangular (- (point-x (car points)) + (point-x last-point)) + (- (point-y (car points)) + (point-y last-point)))] + [endpoint (+ point vec (make-polar -1 (angle vec)))]) + (send path line-to (real-part endpoint) (imag-part endpoint)) + (loop endpoint (car points) (cdr points))))) + (send path line-to (point-x (car points)) (point-y (car points))) + path)) + #| the mask bitmap and the original bitmap are all together in a single bytes! @@ -742,7 +784,8 @@ the mask bitmap and the original bitmap are all together in a single bytes! (struct-out point) make-overlay overlay? overlay-top overlay-bottom make-translate translate? translate-dx translate-dy translate-shape - make-scale scale-x scale-y scale-shape + make-scale scale? scale-x scale-y scale-shape + make-crop crop? crop-points crop-shape make-ellipse ellipse? ellipse-width ellipse-height ellipse-angle ellipse-mode ellipse-color make-text text? text-string text-angle text-y-scale text-color text-angle text-size text-face text-family text-style text-weight text-underline diff --git a/collects/teachpack/2htdp/scribblings/image-gen.ss b/collects/teachpack/2htdp/scribblings/image-gen.ss index 753806ba2e..72828ed4c7 100644 --- a/collects/teachpack/2htdp/scribblings/image-gen.ss +++ b/collects/teachpack/2htdp/scribblings/image-gen.ss @@ -1,5 +1,8 @@ #lang scheme/gui +;; Run this file is generate the images in the img/ directory, +;; picked up by image-examples from image.scrbl + (require 2htdp/private/image-more lang/posn mrlib/image-core) diff --git a/collects/teachpack/2htdp/scribblings/image-toc.ss b/collects/teachpack/2htdp/scribblings/image-toc.ss index 314d641b85..b3bd0c0cda 100644 --- a/collects/teachpack/2htdp/scribblings/image-toc.ss +++ b/collects/teachpack/2htdp/scribblings/image-toc.ss @@ -8,8 +8,8 @@ (list (list '(image-height (rectangle 100 100 "solid" "black")) 'val 100) (list '(image-baseline (rectangle 100 100 "solid" "black")) 'val 100) - (list '(image-height (text "Hello" 24 "black")) 'val 41.0) - (list '(image-baseline (text "Hello" 24 "black")) 'val 31.0) + (list '(image-height (text "Hello" 24 "black")) 'val 24.0) + (list '(image-baseline (text "Hello" 24 "black")) 'val 18.0) (list '(image-height (overlay (circle 20 "solid" "orange") (circle 30 "solid" "purple"))) @@ -34,6 +34,24 @@ 'image "f7f1480d58.png") (list '(frame (ellipse 20 20 "outline" "black")) 'image "6a5a617f28.png") + (list + '(above + (beside + (crop 40 40 40 40 (circle 40 "solid" "palevioletred")) + (crop 0 40 40 40 (circle 40 "solid" "lightcoral"))) + (beside + (crop 40 0 40 40 (circle 40 "solid" "lightcoral")) + (crop 0 0 40 40 (circle 40 "solid" "palevioletred")))) + 'image + "164b8da7bf6.png") + (list + '(crop 40 60 40 60 (ellipse 80 120 "solid" "dodgerblue")) + 'image + "6c262f1d24.png") + (list + '(crop 0 0 40 40 (circle 40 "solid" "chocolate")) + 'image + "8e7c1870c7.png") (list '(ellipse 60 60 "solid" "blue") 'image "d92d6a49f1.png") (list '(scale/xy 3 2 (ellipse 20 30 "solid" "blue")) diff --git a/collects/teachpack/2htdp/scribblings/image.scrbl b/collects/teachpack/2htdp/scribblings/image.scrbl index f1a3554df1..3e4a15ef98 100644 --- a/collects/teachpack/2htdp/scribblings/image.scrbl +++ b/collects/teachpack/2htdp/scribblings/image.scrbl @@ -453,7 +453,7 @@ other. The top and bottom pair of angles is @scheme[angle] and the left and righ } -@section{Rotating, Scaling, and Framing Images} +@section{Rotating, Scaling, Cropping, and Framing Images} @defproc[(rotate [angle angle?] [image image?]) image?]{ Rotates @scheme[image] by @scheme[angle] degrees in a counter-clockwise direction. @@ -488,6 +488,24 @@ other. The top and bottom pair of angles is @scheme[angle] and the left and righ (ellipse 60 60 "solid" "blue")] } +@defproc[(crop [x real?] [y real?] + [width (and/c real? (not/c negative?))] + [height (and/c real? (not/c negative?))] + [image image?]) + image?]{ + + Crops @scheme[image] to the rectangle with the upper left at the point (@scheme[x],@scheme[y]) + and with @scheme[width] and @scheme[height]. + + @image-examples[(crop 0 0 40 40 (circle 40 "solid" "chocolate")) + (crop 40 60 40 60 (ellipse 80 120 "solid" "dodgerblue")) + (above + (beside (crop 40 40 40 40 (circle 40 "solid" "palevioletred")) + (crop 0 40 40 40 (circle 40 "solid" "lightcoral"))) + (beside (crop 40 0 40 40 (circle 40 "solid" "lightcoral")) + (crop 0 0 40 40 (circle 40 "solid" "palevioletred"))))] + +} @defproc[(frame [image image?]) image?]{ Returns an image just like @scheme[image], except diff --git a/collects/teachpack/2htdp/scribblings/img/157ab5efca7.png b/collects/teachpack/2htdp/scribblings/img/157ab5efca7.png index 59966a6bc9cb7c65315d62b114d4b63f4abd4bf8..bcf769afe8de2c984725ef8df112b22ebbd21633 100644 GIT binary patch delta 132 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 delta 943 zcmV;g15o_e2gL`FB!7%aL_t(og}s=|ZrVT;hR0)kQEY4=#7<-6kU}mBY9ba{W|vjF zYV&w~g{sTGLR6`dxb;$@H`J8oIhJ^o*>gSpPrsNoz7@9!heK82t`qpWm%FWk|ZP3 z5}0)(gxc-4rfGx0V4g<|L{XHYD5|RBpI|22vaE8syeRdh7=}4GI7p|{i?KCLySuyd zJnz53fijs)KA$HDBASg5s#Ge?X7laTK%1MJg+gI+|HH3kxm;c@7yw`xMyXVq+{IVy z`}_M=tF>HkfPcTey`9PKcDwa@eHCC|tyU|vu)l2Abtj)|>8eyJwrz*mnx^6F#!}?E zZmm{(#dcly;o)J`U|+hf2Q>rw<4}EGsTz&OKX$v_UKnE=H>i1X&MvpLHsbwx{xl;QfC-9NhdLx8HRxj!(bwE zT<+7mPm}Wnp>U~O;$2Ky06;t*kMTT@5Bj|Gd7Ih(-u&)Y4@kfZ>Ecqk^#2aLJ4-Cf z(lkvVgs!fxA{(fOyvm@`95suHVv-7PCf=P?CV!LJ-`^(?Le*+@Z9UXiu~`#+ zkbeY0I6Xa$#lrUtQ@(*c&nuNmola*dU`djWj*g~Y0?hpOuh;AKdVQhWn2<=4%;j>5 zqRa}w-Fdv_>S1eZE1%D^EQ^W3u>k-GAzjxSjmB_@JE8=F5T?`V-QC@Jszn4lkZGE_ zt{a9iwd0W_nM@{Asgxv16h+OGZ~=B8$0%_u%kr<-VzC&*FdWCREc+jI=?^*D$xjHr R#4`W@002ovPDHLkV1gAK(Sra0 diff --git a/collects/teachpack/2htdp/scribblings/img/26bd803042c.png b/collects/teachpack/2htdp/scribblings/img/26bd803042c.png index ba29f9ce76abc6a7ea578a6eb2e50b4642609e73..b68c8817267346d22ac828ef6ab1e4291017ff27 100644 GIT binary patch delta 87 zcmV-d0I2_Uc90}eJxN4CRCt{2*1-t?Fc1PkP5(V_dhiZHK>y2pm2E|{J!t_;0m0baf5-|biEuR1Y002ovPDHLkV1jZTC0qai delta 86 zcmXRbouCqEgHJ$Rd*56>-mmRSO nH)-d9!JGeYHs)woS4CNgP2rb+By~%j0SG)@{an^LB{Ts5-H{?q diff --git a/collects/teachpack/2htdp/scribblings/img/28253f4c3c.png b/collects/teachpack/2htdp/scribblings/img/28253f4c3c.png index b9aa3d8d5f5d03cbf003181379d872d59fdf14e4..b6c51246fe49d3fba6f54fd216398d0abd06df22 100644 GIT binary patch delta 1682 zcmV;D25tH945AH?B!6j1L_t(|oYk6bY!hW1z<<5owQJYgOTkVmZXLp0H}?{@;wE7_ z$cUl{qWeH}iI_zVh6IVmw-JpA0)Y`V(~zh^CZC2O_y#dV&5Q(R!pkBNNKrQ#P82qS zmAS3$voN;=^vY=jP_RT&{wG0=L^;R#sMATx>F# zB2*PZ2qC(=yI(IUxeqdv;-?+6*}Qo1;?0{kcXV`!Ft~E%N_~C3WH6-KFgEk&&u?jI z85$ZALa=@N_Eh`m!{hPv_xE$^)G3?ImTDP&?AfyiA%Db~ty@>Z|6riNoH=uvo0|iH z0HU{7Sgitnf~{}|$f=f_fFwy}Wn~*TZai}2h~MuYc`gm&?YCLKKD?d}I^a7v1>b`g z{K*xaElIalRTaA3B_$>0<>d<(E>u-@LLHgQmnRh2U>PhM+x5fGa2~p#3ogP%_zixC zeh^Ft1%GD24R9me2y@_OmO)kO|q41sO5V?97=M-e(++qL{r*eM$~+Ot*P7s;i?PmyQk$98Sas z$HU5%vAuum?p_Do$q~{*MFo5J#;hd;ySp#J5`Q?I1gDtP*Ynj^WM{{$Cj-6E5h$Nv4awJ|B=MdsD=^6=f;;6n(4NZM9dD0c4_gM&g3yz6#PKA8ou19}sw z>sM9r*kj_$FGVn@%XrlLXmPPJ#jTK_26jN_4BY`gbij6a*y$9*!_&|WAsdE=m&0d~ zynlo6HGB=vf*q=$5=x;M^1-ZO5MF}w@B^HN<8TtL0kGrgr;+2D2N~L3uEDOZ<$9aJ zP2hl8FdJq;Cj13`W7`$zfq_VEold9M>$O^~@p$va+_?hk;_5>m2M!#FXM~K7?@x1c zM<%h!d9&QGVMF}VLI^(0&mVbcJ_cigrGM9~SreK-$LsxGQBml5-b;W^ zL=fJAo8mJrC@9#sZ(nd)=`gnUD>XF_PLbaJf!$E1Q&)zSs(SF?!9XC82;))jZGX#_ zS>bBb{M-qzz>=sray~S`KDZ3xt+x_qJc691DA(WvSUDU`y?FbrNe2fgqoWWWtD z4+_G=e@+hT*6F-Sx{>WB6Yx4bp&(!f z^xShi{`ibIX+c7k!=JNfpmiGEy!ay9w#}5279?c3B5Ys4qp(wZ2UaVst!&vc(_%4@ zP?SaEiv&CitKeeH*7x4a>C-ecBuFkAV#}7RQ>=Mg;TiBwN}qqhuXT0e+kbBpofMe-z(abz-)U@YOq`HLBr-FBe7H+ngWB5K^6^V^DM1P?emM%Lq+42AQmr};gb?D+JHyjqKinTCotKw)`0(LWdrm|KaJgu24~b^MM{umB z=GdxLZnwLxt}f+SW->CsEw@ZQP`z|%^`=e9*3pavP*@n@NM&V`Rey9L0TfLN+y(=; z-=2IM?TlUTw6t->MMcb>of099NB~A76&2%(m+SrFB-u!#f0ry7SG;<4@>O&(=6(0w z*UMb4iKp@3BkX!RoumJ6+QfhVXL;9C(5_tqgvTR>hEkUYwG#F_(_oO+R#vYjD=Vc} cQWO6I7SV>bHnv2t01E&B07*qoM6N<$f}mbOu>b%7 delta 1631 zcmV-l2B7((4e$(*B!4$aL_t(&fz6t0Y*SSnz<<4cus-J8)(r%PY+bems7}U&0kT9G z@{pIPG46viA!sB7d?dU=42ZH1>d+}_O-@d>+wB<{8R_ZicDvndHlq&Ri1+pD%$-Y5&$Tsc z-e_;Hudkm9lYikZbU>fVc+rubo}S|)FE6jCsA$%#S$e%bKvfYD5tqyL#ZynMgOr5$ zsmErsEm^W;-@bi~jg8_5ot>Q(6%_`9L2JYCwa_6%`g1 zI-O37#WJRjf&2Hz6itGKu+XyV!5}7+F64J8kOMhE_WlE%&;{M_FZ4nW+=D^T!K07_7D$04pKB_F z&x+Tthw=X1Zl4u4N^nvkHHyQ7Qc@CnzjCp+_gp-_I2zWjWx;~bRg`}^I$ncYi4ju6 zym=fw8n%{#%k>vL1C0rA3XM+3=FQaAk)q-*>3@T=GVcd7d;)zSn!FqiIeS)A!-qvh z{y$?T)PN_E#)XA);)L|~tCtoLYUa!te-a$Eg@S6T?7%|1vlm#QQQ_2EYo7pco3E0P-O@T+i{qEog>T zXn%sAp#cT}_;~wve8ahkp}U-ubN|MT=ORCH8e~ESq(eH`pd0S`UVnoN+<^|9I(2GG zOUw9Mj>!0F=1hU*QN@Ui+S=M^TF6lQ{vjtv;6|cGmRq-Ojb2(rIFp;}?KEGeQ*28;^Lu7$m(7z*q2egt{hp zB`xjZ#fxz=9`UxqgOK_8cQ^#AAXuuZBX(^jG$0Sl{lqtT+!JW_*WiYduBS+AMp4W&CN~Y21J*l1WR+PaG9U?b3 zdM7m~roO&B-^N!^HQ`8m_9Ui-cz;nyPA>G@eiv#c5N7XQ4jhP;lNuBh#ot@tb@&8C zWdNIvZ@^*3xym!_y8sa+GU1!pk-Y8 zybtXwR>+kr@lJ}N@+B6F4NBp=ao)Y~DSQeAPz=+c1Ac?ftgO~EXQCX~Mt_NcNt1xp zfxL(D&fX8Rv%FltFN!uusaTew6=P^2Vr(N?+qI^Xe~Sh($zJ5f%`FJD^E#DX=`iKT6hRVM9k)4 z^)10$$m!FkwYD7r5s|#SVSn!jfd-U%z5ejw!&Twc2L=hdqV3JS`~${xa19tMEy?D0EFN=r-Leml`Rs!;#}=8ot=ETr@~JHffWyI!8D^_S?qgWo_?dY@5jw*iX zrNpa5L?G|nT;|Tz#6~?n@5PHprarcB*UBaWMpDpcp9#qP`H?r=t;P1X7L)y86|(3qW&=gR zC+5AX)S<{7s=@*QLd)&3t|NqWk}6V6j&@|Z&Lrnb@~$`{6brp|c=TW}9eX(w+x;lD zGn;x*61z6BDt{(amnYKYz1!0}y`}#~Pnak~-e;Np~b9ekIBn*Qs1>t%>cD6`*6 zx&O82|)c=b!x_Xbh@)*5eBgd3;D z`3c!Vw>lt%LPzOWPB{q2+SgaS3km(o@xsG9&EMu~JcGpkA9&99q~w>qix2eQkK~1D zxp{7N-~;&JuN{2vvN{F;U4^Tk6kAyu01AonA4l_YZn-)z0Q~cvl$lYRYGnu^TE0Fe zRvu%m1b_d2FEv-lIMK^Wd{PAfyl_*MvR0fajpFt<5&+<(do5ko)ugA@d`!n$shu{v zLV8-o1Y@X=X(@_H9rJ>@y!AB_p>|RyXyn^VV0H`YJMgTj$4UkcQ%o1a0I=(G z2PWEM%V{UtJ?4PQdD%UPhdyh3ifK3qp^>jS)_;p&CC~3V$!t4BHPxyP2&27c*p-rg z(#Mt+xIQNS_gf1!-z!iYdh;yXziMZn&O0;brQ7GEverU}QFoXaImdPFSd-Y+$!Y0n z?e8zdrMcz@2#P~PCzzK$W>8g9+aMQfaQ7#9=7LmOY)=SMWtUF)aW(A+0+O`V@mVpkNU@Vx4t=|p||sqG(7fss0s zlM05sD`*lVe*Pu?XC@ihms=coCQSeUz*zJ2-tuk#EAU=$>ycyCMO*_DCp^JG@byTL z8wUVU@MmIsGWYi^Erhe_Q2ybzvR;40=YQZAT|M)ip80P7tf%*u+doUv1pt8IaWEro z&U-biGZ_qD3WhILp6VJ^%=wFgUle?@*eOd+Rpv-qr06`w|shLc7lGZEtI_y{*OewieslT5NA?X;*I({Wm}h{m;~-cgye?P!q*+ U{ruK(enQAJO#}cK>l7o?>>|Z3^BrlvLlQdEn5ektZ5n7HvptvEkxT7Z z%x*2rZLR!g>3;}>^^VY`KzOFR?|jdF=epx0;q(c1>ISu7ULDoa#tS&QmAZiUk z>5<3S=rGm)BE^Zw&JZha(}2{NHv6rX{zWsi=4o2k5YV@qOzfv)&r`^9={5E?b(lR_ zx$wEVe8sp|j+V6dRdSSN?!6Y&K1uyijgnZpwk&GYr z73Gxov9T6>1n>DyXp7a=F#s4EoPI-TWoZCVBxCf|qFSg&2L^yYK2zr}v|@PN!txd4 z?2%IK8h`7GIsK*Tt&n}Lj%umXIsjnlT(z>~q}Ap%Q=gUr0Jr7_V!_;GRla6mv!z#K zBTSe(U)_-Tw{pY4?Xiug-WJ7J+(}qxUabZ}Lu81=d>BWcrM#AL!2Nq^CV(&i3?5>T z(|W@r=nnMoVHRrVWoUrd{$}&5n5Kg;JoyRF^?xAvzn*{ST{iYyOGgVLVCW+*I$Y1i zSMpdxgENPfOFy_$kU4}D&=VhX{d-p4?CN^QgsJ1|N)vni| zPMiC^dUix9%zA&2k^&k$#3Wy1Zm%-etc(BrTAezsmgl`mxd;Xl`{}{ASvJ_XEn(G% z(0@zj?1{?ER~0v_dSMez9H1Y3g=V^}8Y%1deM|!~XY`9FE2&euR=iiQpX)(=Pg9%s zQjsCj&iQStUsa>3!u4-Xq<>0hE z05*>}l6K~OGhADii)S~*$7;7ml~R>ZSqZAeP)Qb5C8VhW#S|Gn&v1EG$T57L;qxS| z+}U(Z^S%X4Xk5F*wM$KTnyndKo2j|@-tOXiyNmDbF21+B_}=caQN11JRiRz5?IK9? jEyB(|)&xg&Lrd{5Uwn+*un`RYr?2mxof#UsfA99K|F&@yZ@>6x(y2AYLe;#|VDQ_( e-2C#Hc~4n`nm4a>edB1s00f?{elF{r5}E+TzdV}& delta 150 zcmV;H0BQf90kQ#*B!78HL_t(oh3(d{5x_7A13)>Kq0}*!*?_rR*;|n^b)d?fbhNss z)YyBkweUS8&8$#-6A`tdyJs&~>+xP>%a$!$wrtt|vu~1f&O)<0n1GR)_4YX^Z9R}M zLu+wGBv3hb?KRo5Wy_W=TlUA?tu~3$)`Jl5V%@q5@y z5y@`rWo8aU=V|uL8Gg(Tv$G@B8_o9y1V=82j0WYsftR{y8(CyD$imt0__zP2Z`({4~CsYb}snc z7Huzwh-_Ixp32T>@Ysm#-RO@;akeaBCqiUrw9n&lHbGL7@zx8so7e}xarmz(m zPa7sRyzEK}3B5hd-5zzBtTadap#arFVV7sIIoVbvV>|4@{d&8_EN#_-w-W4%a9fh_ zTtw8{!4PJ4HD`Ec@U_q8ahdLT6a)JxfyY8O1ADcPlc*I9Pf3n;C52iMa(6P&_J;Tw zvV^-eR8n24-P=ADuiID&nO8ElSI1E+V#v`e+?nm}$L%ss=NPCR*ouskB&vCM?aW|v z+uDcy7_OEu?q;c)*by%d<0#LxUR+t)xghZMk6}|VS~- zt&QU6*_}x_yh({sX{~u%&!y5!qw?vx=^f126l8TdP1M5OR8Qgh$U^u}HdaKz-G%Nit%b|m1Sx{M z6Ww1~4g&z3zvQT{37&47;4*f6x);WRHo?Ey;+9)E-?b0^(S|qv%-XoE@b|U>rNnH% ziNC=D`(b5Fmos+5-`Ge9=Z+T`z$G@N$%SDS6I`h+hc{5-f(`uD7Plvu!Jq7WKJ6K*0;6+036Jwv(k74QM32e T7%(VR00000NkvXXu0mjf=R*F> literal 0 HcmV?d00001 diff --git a/collects/teachpack/2htdp/scribblings/img/9858b8d5d.png b/collects/teachpack/2htdp/scribblings/img/9858b8d5d.png index d3abd4688e285e450e438312da0426722774f4a8..e5bec8f1d1f4846edccb0d4fe1dd3e5ed77e3f90 100644 GIT binary patch delta 1114 zcmV-g1f~1<2=54xB!4zZL_t(|obB3QOj}hP!13QX=iaurw}rMqS2`NXv`8l<2uj?v z%IL@@Q)8T27N(gm%d$kHFI!?_;-2Q8C7Sp=pA3nQ8s_4b44FC;F>{-f>FDO4+JZoV z(!Xo(y*)m_DAWFhaxV|}^VHm)+_G=Lcnl{HGrlD>1|kV!@Lb4X3d`o0KmY^DExe~+~E{Qrroo_N5jFc z$V}Vf%tPsvsqpB#h2Fp{s&QhI3)gor4c(-^gJ4ZX*-+NE7Veq?HwQxg{z?C?qM_x= z3N+%EB7W)5bAJK=5G`ul$u#+x<~^*g9+h(jL~oode7#Xxk~Yw{qQyh-2i_&*uMmSnj%_D5bZC(&1}j-x*$S%T4*^>62XCdj6B)%@)04 zZd^LIKb{EDl_MAcsKkCfG!&b6D%Mqo#ANpTU_29DPR9W7%eQZYL!F9Nl_eI)UOt{$ zdX1$tGk^ZwYsvmR2905AMiuXIUeX0M9zAjML8eG4-s z%w82S(MU>XR4h3~G2akXI-_C+2gY04LuD--Hw~gewjBg>=0sE5S4ziJpyhd1YeE8-sm(UmEp9UK zxnXrQtnLN?0NSzZgS|)hnytUdSyl+EM_ng$&kh?*uK#W`^K3gC9AnSD{$$U-w{-lR zEPr`<5G`^a*1mYj=sBiEdA65DpF>E3e&WYhfBpVwY@vBWD_7%f*mY3T_KHSpDRw_B z{`_Ql%%s2X_LW1yTYH2IU)9JQZ7pi*W4FD)+Px*7oGdA4F-YyMi+0yVN#rK|zR-kk z>P~NTu4Ub+fEiThA-2bf-OFz2A$jLRA%7JtVhNLSxX(J=X8|A;YYYdw!+&=#OuH9n zTjTT2EG_VaW))o>u4%!wE!eW1)Om<`J7KsATG!aU8fTnZ`3?X;B{mstOvV~hF09yrFP3p?Uol>=l_`&WbFm()73xi gJ&00Tder9gFKr4(t;m-mRR91007*qoM6N<$f_WV?Hvj+t delta 1123 zcmV-p1f2Wt2>1w)B!53iL_t(&f$f@EY#T)!hyOEs*lRn9kH$&tq*hZqcN$96s!>UE z&{j=b5vd5Z1xk5=N|g}e0kwz+UVusijUCr*y{DX76l?S-x~CE z2R+>pe{(p{oJtt8S7)=GKqOQ;u(65QvV*AZCbo1EgccR)T>xytbZhF!+>Hai*?nxn zR8$8U5jlv=3V)GV;pRvh00<4#?jh?3DaRp-u@-azNW6X_+x-?r?3q63o_KQ3Jt*+> zz3b+;A;7+mbRDM~4p0c^s+swIivsEX<*{o&KD)HgSQf!7h&*`4InOv(;lQ0|HO^x+ z$}%7_6nmx*PJDIYpM~w^b_h>Jl`t2UQR@~@lh)H8$bB2PG7e&RY~1TBZoL z4bvJU!T``U@EXFr(mn-2SEBo$*Mc-(TI`b@y?<{ht&|^xq4!N4Q;p#6x@zbCmm69~ z6t&6&BB1A0rhagF0lVytFyDXjbYs`2%8BKI)T6$)b*|$p--@eNv_z`+k*9a=e+6Mq z3Ae16+lix}8yrJxf{V5D4ia|^ygu~QVWaggS=F*Y>QVQ3?a|K+RomCkj~V96>a9ON z^nc6)yN{gL>I1UqWq{B?%M60y&A^gXPkbUb6h$Uc#4f%l5sN| zvm~NcHf~894^z$|jS*=~NNYwK6Ve#bx(wuA*r4}1Fp*{|d`yLJrKrse_YIe%@m$P3 zmapluqI%1V>Mbv-x4fv{@}hdni|Q>es<*tT-twY)%ZutQFRHh^sNV9Tddmw5mOapR puJjGp^p(ENRUq;I_d^5#z`se)MOMd6EFJ&=002ovPDHLkV1momB@+Mu diff --git a/collects/teachpack/2htdp/scribblings/img/ff2fcb7b87.png b/collects/teachpack/2htdp/scribblings/img/ff2fcb7b87.png index 0930b8b91a3e00a376c1c086fed05adc338c79a5..093bb06a488e0fd691f41c8e7f68f81cca397c0d 100644 GIT binary patch delta 318 zcmaFFbdza8ySE z_TsnsuU^UDU3WXwx4)$JDewFw?UR?TZ=d*Tp+!YczS7l_Pg~{c^_RPsIp;4>^fsT_ z5tEVg&wt9pz&3YDxzq|cHq)$ delta 327 zcmcb~^oVJKO1-A1i(^Pc>)UIN-b{`X$3B*4o7?PYzv>V(y(59Ylf}t}2%m_-+A)u^45j6pIdeI^NWaj)4hKy-uF#n-K~Cc zU)vgU$*vP^$DaLnk(5iVnDQ{N%^k*A{>O8+`Ha5Z`sGsH_ok`WYrRg-wD&d@i%xXT z+2?!egT~>-Jm=$PUi97_y=G3>?A42Ew!fWzBtYzU;+uBuPk&6xmL+}84T6~W?bNhA zTW-}?PX3nVV7)11+285rD}z^eoZapTvF)aIG5?_*#U&f_j;-fgysN{aa^CuAqy74; XysRHwTz<=w0SG)@{an^LB{Ts5C!U`J