2 Guide
2.1 Coordinates
2.1.1 Points
Note: This is different from racket/pict which reverses the direction of the y-axis.
Consider these points:
p1=(0,100) |
| p2=(100,100) |
| p3=(200,100) |
p4=(0,0) |
| p5=(100,0) |
| p6=(200,0) |
Notice that the point p4=(0,0) is the reference point. The point p3=(200,100) is located 200 units to the right of p4 and 100 units upwards.
In order to write a MetaPict program to draw a shape, a good strategy is to draw the shape on paper. Determine the coordinates for the key points, and then write the MetaPict program that draws lines or curves between the points.
The .. between the two points connects the two points with a line.
> (def p1 (pt 0 100)) > (def p2 (pt 100 100)) > (def p3 (pt 200 100)) > (def p4 (pt 0 0)) > (def p5 (pt 100 0)) > (def p6 (pt 200 0))
> (with-window (window -10 210 -5 105) (draw (curve p1 .. p6)))
If you zoom, you will see that the lines have a thickness and that the ends are rounded. Imagine that you have a pen with a circular nib. The drawings produced by MetaPict will try to mimic the result you get by drawing with such a pen. In the chapter on pens you will learn to the control the thickness of the pen and the shape of the ends of lines.
2.1.2 Displacements
In the example above, the point p2=(100,100) was described as being 100 to the right and 100 upwards relative to the reference point (0,0).
An alternative way of describing the location of p2 would be to say that is located 100 to the right of p1 (and 0 upwards).
Such a displacement can be described with a vector. Since Racket uses the name "vector", we will represent displacement vectors with a vec structure. To displace a point p with a vector v, use pt+.
> (def v (vec 100 0)) > (def p1 (pt 0 100)) > (def p2 (pt+ p1 v)) > (def p3 (pt+ p2 v)) > (def p4 (pt 0 0)) > (def p5 (pt+ p4 v)) > (def p6 (pt+ p5 v))
> (with-window (window -10 210 -5 105) (draw (curve p1 .. p6) (curve p2 .. p5) (curve p3 .. p4)))
Note: defv is short for define-values.
> (def v (vec 100 0)) > (def 2v (vec* 2 v)) > (defv (p1 p2 p3) (values (pt 0 100) (pt+ p1 v) (pt+ p1 2v))) > (defv (p4 p5 p6) (values (pt 0 0) (pt+ p4 v) (pt+ p4 2v)))
> (with-window (window -10 210 -5 105) (draw (curve p1 .. p6) (curve p2 .. p5) (curve p3 .. p4)))
The displacements left, right, up, and, down. are predefined. As are the vector operations vec+,vec-, and, vec*. The displacement that moves a point a to point b is given by (pt- b a).
> (list left right up down) (list (vec -1 0) (vec 1 0) (vec 0 1) (vec 0 -1))
> (vec+ left up) (vec -1 1)
> (vec- left up) (vec -1 -1)
> (vec* 3 right) (vec 3 0)
> (pt- (pt 2 4) (pt 7 8)) (vec -5 -4)
It is common to need points that lie between two point A and B. The mediation operation is called med. The call (med 0.25 A B) will compute the point M on the line from A to B whose distance from A is 25% of the length of AB.
> (def A (pt 0 0)) > (def B (pt 3 2))
> (with-window (window -1 4 -1 3) (draw (dot-label "A" A (top)) (dot-label "C" (med 0.25 A B) (top)) (dot-label "D" (med 0.5 A B) (bot)) (dot-label "E" (med 0.75 A B) (bot)) (dot-label "B" B (bot))))
Note: (med x A B) is equivalent to (pt+ A (vec* x (pt- B A))).
Let’s use the knowledge from this section to write a small program to generate the character A. The shape depends on the parameters w (width), h (height) and the placement of the bar α.
> (define (A w h α) (set-curve-pict-size w h) (def p1 (pt 0 0)) (def p2 (pt (/ w 2) h)) (def p3 (pt w 0)) (def p4 (med α p1 p2)) (def p5 (med α p3 p2)) (with-window (window 0 w 0 h) (draw (curve p1 .. p2) (curve p2 .. p3) (curve p4 .. p5))))
> (list (A 10 20 0.3) (A 10 20 0.4) (A 10 20 0.5) (A 10 20 0.6)) '( )