draw-line
, which takes two vectors representing the start and end points of the line and draws a line between those points.When I originally did the exercises in this section I didn't worry myself too much about this. After all, some of the exercises rely upon the existence of procedures that aren't addressed until later exercises, so I wouldn't necessarily be able to produce sensible pictures for each exercise until I'd completed them all.
Of course now I'm writing up the exercises after the fact, and have a full picture language at my disposal. So I decided I'd produce at least an implementation of
draw-line
that would allow me to produce some pictures to post in the exercises as I write them up.I've noted before that one of the interpreters I'm using is DrRacket, which has its own graphical interface toolkit. After a bit of head-scratching and hitting the docs, here's what I came up with:
#lang racket (require racket/gui/base) (define picture-size 300) (define bitmap (make-object bitmap% (+ picture-size 1) (+ picture-size 1))) (define bitmap-dc (new bitmap-dc% [bitmap bitmap])) (define frame (new frame% [label "SICP Picture Language"])) (define canvas (new canvas% [parent frame] [min-width (+ picture-size 1)] [min-height (+ picture-size 1)] [paint-callback (lambda (canvas dc) (send dc draw-bitmap bitmap 0 0))])) (define (draw-line start end) (send bitmap-dc draw-line (xcor-vect start) (ycor-vect start) (xcor-vect end) (ycor-vect end))) (define window (make-frame (make-vect 0 picture-size) (make-vect picture-size 0) (make-vect 0 (- 0 picture-size)))) (send frame show #t)You'll need the vector constructor and selectors from exercise 2.46 and the same for one of the frame representations from exercise 2.47 for these to work.
Note that
window
provides a frame that will map a picture with x and y coordinates in the ranges [0..1] into the [0..picture-size
] that's provided. It needs to map standard Cartesian coordinates into an inverted coordinate system as, like many windowing systems, the coordinates (0, 0) correspond to the top-left corner of the window, as opposed to the bottom-left as is used by the picture language.We can also give ourselves a shape to play with. I'm using a procedure I produced as part of exercise 2.49,
build-segments-list
, that basically takes a list of vectors and turns those into a list of segments. I've used this to produce a spiral:
(define spiral (segments->painter (build-segments-list (make-vect 0.0 0.0) (make-vect 1.0 0.0) (make-vect 1.0 1.0) (make-vect 0.0 1.0) (make-vect 0.0 0.1) (make-vect 0.9 0.1) (make-vect 0.9 0.9) (make-vect 0.1 0.9) (make-vect 0.1 0.2) (make-vect 0.8 0.2) (make-vect 0.8 0.8) (make-vect 0.2 0.8) (make-vect 0.2 0.3) (make-vect 0.7 0.3) (make-vect 0.7 0.7) (make-vect 0.3 0.7) (make-vect 0.3 0.4) (make-vect 0.6 0.4) (make-vect 0.6 0.6) (make-vect 0.4 0.6) (make-vect 0.4 0.5) (make-vect 0.5 0.5))))We can then display our spiral... Invoking this:
(spiral window)Produces this:
No comments:
Post a Comment