Go to the first, previous, next, last section, table of contents.

Composing pictures

To build the traffic light picture we presented at the beginning of this section, the different Picture values for the lights will have to be combined together. The Picture type provides three basic composition operators:

Combining the PicOverlay operator with the structured translation operator in Section See section Structured translation, picture combinators that tile two pictures together can be expressed:


beside :: Picture -> Picture -> Picture
beside picA picB =
 Overlay
  (Move (OffDir East) picA)
  (Move (OffDir West) picB)

above :: Picture -> Picture -> Picture
above picA picB =
 Overlay
  (Move (OffDir South) picA)
  (Move (OffDir North) picB)

The beside combinator overlays two pictures, but translates their local origins such that picA will be shifted to the left of the vertical axis and picB wholly to the right. The combinator above uses the same trick, but this time the translation is with respect to the horizontal axis.

As an example of these various composition operators, we can finally present the construction of the traffic light example presented at the beginning of this section, starting with a combinator for placing an arbitrary text string within a coloured oval:


light :: Colour -> String -> Picture
light col lab =
 ConstrainOverlay 
     (Fixed Second 20)
     (Fixed Second 20)
     (withColour black $ centre $ Text lab)
     (filledCircle col 2)

The light combinator centres the text string lab within an ellipse that has horizontal and vertical extent 20 units bigger than that of the extent of the picture representing the string. Using this combinator we can construct the pictures for the individual lights:


redTLight    = light red    "R"
orangeTLight = light orange "O"
greenTLight  = light green  "G"

To align the lights horizontally, we want to use the horizontal tiling operator beside, but want to add some `air' between the lights first:


besideSpace :: Unit -> Picture -> Picture -> Picture 
besideSpace spc picA picB =
 beside  
   picA
   (Transform (xlt (spc,0)) $
    moveWest picB)

besideSpace uses a Transform constructor to enlarge the bounding box of picB before invoking beside. The three traffic lights then become just:

\vspace{0.15in} \hbox{ \hspace{0.5in} \begin{minipage}[b]{2in} \begin{verbatim} lights = foldr1 (besideSpace 10) [redTLight, orangeTLight, greenTLight] \end{verbatim} \end{minipage} \vbox{\vspace*{0.3in} \psfig{figure=lights.eps}}}

lights =
 foldr1
   (besideSpace 10)
   [redTLight, orangeTLight, 
    greenTLight]

Traffic lights

The final step is then adding a black background for the casing of the traffic lights:

\vspace{0.15in} \hbox{ \hspace{0.5in} \begin{minipage}[b]{2in} \begin{verbatim} trafficLight = ConstrainOverlay (Fixed Second 20) (Fixed Second 20) (Move (OffDir Centre) lights) (Move (OffDir Centre) (Rectangle (2,2))) \end{verbatim} \end{minipage} \vbox{\psfig{figure=tlight.eps} \vspace*{0.3in}}}

trafficLight =
 ConstrainOverlay
   (Fixed Second 20)
   (Fixed Second 20)
   (Move (OffDir Centre)
         lights)
   (Move (OffDir Centre)
         (Rectangle (2,2)))

Traffic lights

This example, while small, demonstrates the compositional programming style that follows naturally, where complete Pictures are formed by repeatedly applying picture combinators to existing Pictures.


Go to the first, previous, next, last section, table of contents.