MetaPost Advanced Graphics
This page describes shading and tools for generating not-so-simple line drawings.
Shading or Filling a Closed Path
Shading is done with the fill
statement. In its simplest form, the fill statement requires a path expression that gives the boundary of the region to be filled. In the syntax
fill path expression
the argument should be a cyclic path, i.e., a path that describes a closed curve via the ..cycle
or --cycle
notation. For example, the fill statement below builds a closed path by extending the roughly semicircular path p. This path has a counter-clockwise orientation, but that does not matter because the fill statement uses PostScript's non-zero winding number rule.
beginfig(21); path p; p = (-1cm,0)..(0,-1cm)..(1cm,0); fill p{up}..(0,0){-1,-2}..{up}cycle; draw p..(0,1cm)..cycle; endfig;
The general fill statement
fill path expression withcolor color expression
specifies a shade of gray or (if you have a color printer) some rainbow color. The color expression can have five possible values, mapping to four possible color models:
Actual input | Remapped meaning |
---|---|
withcolor rgbcolorc | withrgbcolor c |
withcolor cmykcolorc | withcmykcolor c |
withcolor numericc | withgreyscale c |
withcolor false | withoutcolor |
withcolor true | current default color model |
For the specific color models, there are also:
fill path expression withrgbcolor rgbcolor expression
An image object cannot have more then one color model, the last withcolor
, withrgbcolor
, withcmykcolor
, withgreyscale
or withoutcolor
specification sets the color model for any particular object.
The model withoutcolor
needs a bit more explanation: selecting this model means that MetaPost will not write a color selection statement to the PostScript output file for this object.
The 'current default' color model can be set up using the internal variable defaultcolormodel
.
Value | Color model |
---|---|
1 | no model |
3 | greyscale |
5 | rgb (default) |
7 | cmyk |
Below are shown several applications of the fill command to fill areas with shades of gray. The paths involved are intersecting circles a and b and a path ab that bounds the region inside both circles. Circles a and b are derived from fullcircle
. Path ab is then initialized using a predefined macro buildcycle
that will be discussed shortly.
beginfig(22); path a, b, aa, ab; a = fullcircle scaled 2cm; b = a shifted (0,1cm); aa = halfcircle scaled 2cm; ab = buildcycle(aa, b); picture pa, pb; pa = thelabel(btex $A$ etex, (0,-.5cm)); pb = thelabel(btex $B$ etex, (0,1.5cm)); fill a withcolor .7white; fill b withcolor .7white; fill ab withcolor .4white; unfill bbox pa; draw pa; unfill bbox pb; draw pb; label.lft(btex $U$ etex, (-1cm,.5cm)); draw bbox currentpicture; endfig;
Filling circle a with the light gray color .7white and then doing the same with circle b doubly fills the region where the disks overlap. The rule is that each fill statement assigns the given color to all points in the region covered, wiping out whatever was there previously including lines and text as well as filled regions. Thus it is important to give fill commands in the right order. In the above example, the overlap region gets the same color twice, leaving it light gray after the first two fill statements. The third fill statement assigns the darker color .4white to the overlap region.
At this point the circles and the overlap region have their final colors but there are no cutouts for the labels. The cutouts are achieved by the unfill statements that effectively erase the re- gions bounded by bbox pa and bbox pb. More precisely, unfill is shorthand for filling withcolor background, where background is normally equal to white as is appropriate for printing on white paper. If necessary, you can assign a new color value to background.
The labels need to be stored in pictures pa and pb to allow for measuring their bounding box before actually drawing them. The macro thelabel creates such pictures and shifts them into position so that they are ready to draw. Using the resulting pictures in draw statements of the form
draw picture expression
adds them to currentpicture so that they overwrite a portion of what has already been drawn. In the figure, only the white rectangles produced by unfill get overwritten.
Building Cycles*
The buildcycle command constructs paths for use with the fill or unfill macros. When given two or more paths such as aa and b, the buildcycle macro tries to piece them together so as to form a cyclic path. In this case path aa is a semicircle that starts just to the right of the intersection with path b, then passes through b and ends just outside the circle on the left as shown in Figure 24a.
Figure 24b shows how buildcycle forms a closed cycle from the pieces of paths aa and b. The buildcycle macro detects the two intersections labeled 1 and 2 in Figure 24b. Then it constructs the cyclic path shown in bold in the figure by going forward along path aa from intersection 1 to intersection 2 and then forward around the counter-clockwise path b back to intersection 1. It turns out that buildcycle(a,b) would have produced the same result, but the reasoning behind this is a little confusing.