On this page:
2.1 Coordinates
2.1.1 Points
2.1.2 Displacements
8.1

2 Guide

2.1 Coordinates

2.1.1 Points

In order to make a computer draw a shape, a way to specify the key points of the shape is needed.

Note: This is different from racket/pict which reverses the direction of the y-axis.

MetaPict uses standard (x,y)-coordinates for this purpose. The location of a point is always relative to the reference point (0,0). The x-coordinate of a point is the number of units to the right of the reference point. The y-coordinate of a point is the number of units upward from the reference point.

Consider these points:

The coordinates of these points are:

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.

Let us write such a program, that connects point p1 and p6.
> (with-window (window -10 210 -5 105)
    (draw (curve (pt 0 100) .. (pt 200 0))))

The .. between the two points connects the two points with a line.

If we are to use the points repeatedly, it is better give them names.

def is shorthand for define

> (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)))

Let us connect the point p2 with p5 and p3 with p4.
> (with-window (window -10 210 -5 105)
    (draw (curve p1 .. p6)
          (curve p2 .. p5)
          (curve p3 .. p4)))

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.

The point p3 is p1 displaced by v twice. Use vec* to compute 2v. At the same time, let’s use defv to define multiple points at a time.

> (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))

'(   )