some updates to the webpage
[PyX.git] / manual / graphics.tex
blob43d0a22eeb2677f6249e5b310d6792494acf8156
1 \chapter{Basic graphics}
3 \sectionauthor{J\"org Lehmann}{joergl@users.sourceforge.net}
5 \label{graphics}
7 \section{Introduction}
9 The path module allows one to construct PostScript-like
10 \textit{paths}, which are one of the main building blocks for the
11 generation of drawings. A PostScript path is an arbitrary shape
12 consisting of straight lines, arc segments and cubic B\'ezier curves.
13 Such a path does not have to be connected but may also comprise
14 several disconnected segments, which will be called \textit{subpaths}
15 in the following.
17 XXX example for paths and subpaths (figure)
19 Usually, a path is constructed by passing a list of the path
20 primitives \class{moveto}, \class{lineto}, \class{curveto}, etc., to the
21 constructor of the \class{path} class. The following code snippet, for
22 instance, defines a path \var{p} that consists of a straight line
23 from the point $(0, 0)$ to the point $(1, 1)$
24 \begin{verbatim}
25 from pyx import *
26 p = path.path(path.moveto(0, 0), path.lineto(1, 1))
27 \end{verbatim}
28 Equivalently, one can also use the predefined \class{path} subclass
29 \class{line} and write
30 \begin{verbatim}
31 p = path.line(0, 0, 1, 1)
32 \end{verbatim}
34 While already some geometrical operations can be performed with this
35 path (see next section), another \PyX{} object is needed in order to
36 actually being able to draw the path, namely an instance of the
37 \class{canvas} class. By convention, we use the name \var{c} for this
38 instance:
39 \begin{verbatim}
40 c = canvas.canvas()
41 \end{verbatim}
42 In order to draw the path on the canvas, we use the \method{stroke()} method
43 of the \class{canvas} class, i.e.,
44 \begin{verbatim}
45 c.stroke(p)
46 c.writeEPSfile("line")
47 \end{verbatim}
48 To complete the example, we have added a \method{writeEPSfile()} call,
49 which writes the contents of the canvas to the file \file{line.eps}.
50 Note that an extension \file{.eps} is added automatically, if not
51 already present in the given filename. Similarly, if you want to
52 generate a PDF file instead, use
53 \begin{verbatim}
54 c.writePDFfile("line")
55 \end{verbatim}
57 As a second example, let us define a path which consists of more than
58 one subpath:
59 \begin{verbatim}
60 cross = path.path(path.moveto(0, 0), path.rlineto(1, 1),
61 path.moveto(1, 0), path.rlineto(-1, 1))
62 \end{verbatim}
63 The first subpath is again a straight line from $(0, 0)$ to $(1, 1)$,
64 with the only difference that we now have used the \class{rlineto}
65 class, whose arguments count relative from the last point in the path.
66 The second \class{moveto} instance opens a new subpath starting at the
67 point $(1, 0)$ and ending at $(0, 1)$. Note that although both lines
68 intersect at the point $(1/2, 1/2)$, they count as disconnected
69 subpaths. The general rule is that each occurrence of a \class{moveto}
70 instance opens a new subpath. This means that if one wants to draw a
71 rectangle, one should not use
72 \begin{verbatim}
73 rect1 = path.path(path.moveto(0, 0), path.lineto(0, 1),
74 path.moveto(0, 1), path.lineto(1, 1),
75 path.moveto(1, 1), path.lineto(1, 0),
76 path.moveto(1, 0), path.lineto(0, 0))
77 \end{verbatim}
78 which would construct a rectangle out of four disconnected
79 subpaths (see Fig.~\ref{fig:rects}a). In a better solution (see
80 Fig.~\ref{fig:rects}b), the pen is not lifted between the first and
81 the last point:
83 \begin{figure}
84 \centerline{\includegraphics{rects}}
85 \caption{Rectangle consisting of (a) four separate lines, (b) one open
86 path, and (c) one closed path. (d) Filling a
87 path always closes it automatically.}
88 \label{fig:rects}
89 \end{figure}
91 \begin{verbatim}
92 rect2 = path.path(path.moveto(0, 0), path.lineto(0, 1),
93 path.lineto(1, 1), path.lineto(1, 0),
94 path.lineto(0, 0))
95 \end{verbatim}
96 However, as one can see in the lower left corner of
97 Fig.~\ref{fig:rects}b, the rectangle is still incomplete. It needs to
98 be closed, which can be done explicitly by using for the last straight
99 line of the rectangle (from the point $(0, 1)$ back to the origin at $(0, 0)$)
100 the \class{closepath} directive:
101 \begin{verbatim}
102 rect3 = path.path(path.moveto(0, 0), path.lineto(0, 1),
103 path.lineto(1, 1), path.lineto(1, 0),
104 path.closepath())
105 \end{verbatim}
106 The \class{closepath} directive adds a straight line from the current
107 point to the first point of the current subpath and furthermore
108 \textit{closes} the sub path, i.e., it joins the beginning and the end
109 of the line segment. This results in the intended rectangle shown in
110 Fig.~\ref{fig:rects}c. Note that filling the path implicitly closes
111 every open subpath, as is shown for a single subpath in
112 Fig.~\ref{fig:rects}d), which results from
113 \begin{verbatim}
114 c.stroke(rect2, [deco.filled([color.grey(0.95)])])
115 \end{verbatim}
116 Here, we supply as second argument of the \method{stroke()} method a
117 list which in the present case only consists of a single element,
118 namely the so called decorator \class{deco.filled}. As it name says,
119 this decorator specifies that the path is not only being stroked but
120 also filled with the given color. More information about decorators,
121 styles and other attributes which can be passed as elements of the
122 list can be found in Sect.~\ref{graphics:attributes}. More details on
123 the available path elements can be found in Sect.~\ref{path:pathitem}.
125 To conclude this section, we should not forget to mention that
126 rectangles are, of course, predefined in \PyX{}, so above we could
127 have as well written
128 \begin{verbatim}
129 rect2 = path.rect(0, 0, 1, 1)
130 \end{verbatim}
131 Here, the first two arguments specify the origin of the rectangle
132 while the second two arguments define its width and height,
133 respectively. For more details on the predefined paths, we
134 refer the reader to Sect.~\ref{path:predefined}.
136 \section{Path operations}
138 Often, one wants to perform geometrical operations with a path before
139 placing it on a canvas by stroking or filling it. For instance, one
140 might want to intersect one path with another one, split the paths at
141 the intersection points, and then join the segments together in a new
142 way. \PyX{} supports such tasks by means of a number of path methods,
143 which we will introduce in the following.
145 Suppose you want to draw the radii to the intersection points of a
146 circle with a straight line. This task can be done using the following
147 code which results in Fig.~\ref{fig:radii}
148 \verbatiminput{radii.py}
149 \begin{figure}
150 \centerline{\includegraphics{radii}}
151 \caption{Example: Intersection of circle with line yielding two radii.}
152 \label{fig:radii}
153 \end{figure}
154 Here, the basic elements, a circle around the point $(0, 0)$ with
155 radius $2$ and a straight line, are defined. Then, passing the \var{line}, to
156 the \method{intersect()} method of \var{circle}, we obtain a tuple of
157 parameter values of the intersection points. The first element of the
158 tuple is a list of parameter values for the path whose
159 \method{intersect()} method has been called, the second element is the
160 corresponding list for the path passed as argument to this method. In
161 the present example, we only need one list of parameter values, namely
162 \var{isects_circle}. Using the \method{at()} path method to obtain
163 the point corresponding to the parameter value, we draw the radii for
164 the different intersection points.
166 Another powerful feature of \PyX{} is its ability to split paths at a
167 given set of parameters. For instance, in order to fill in the
168 previous example the segment of the circle delimited by the straight
169 line (cf.\ Fig.~\ref{fig:radii2}), one first has to construct a path
170 corresponding to the outline of this segment. The following code
171 snippet yields this \var{segment}
172 \begin{verbatim}
173 arc1, arc2 = circle.split(isects_circle)
174 if arc1.arclen() < arc2.arclen():
175 arc = arc1
176 else:
177 arc = arc2
179 isects_line.sort()
180 line1, line2, line3 = line.split(isects_line)
182 segment = line2 << arc
183 \end{verbatim}
184 \begin{figure}
185 \centerline{\includegraphics{radii2}}
186 \caption{Example: Intersection of circle with line yielding radii and
187 circle segment.}
188 \label{fig:radii2}
189 \end{figure}
190 Here, we first split the circle using the \method{split()} method passing
191 the list of parameters obtained above. Since the circle is closed,
192 this yields two arc segments. We then use the \method{arclen()}, which
193 returns the arc length of the path, to find the shorter of the two
194 arcs. Before splitting the line, we have to take into account that
195 the \method{split()} method only accepts a sorted list of parameters.
196 Finally, we join the straight line and the arc segment. For
197 this, we make use of the \verb|<<| operator, which not only adds
198 the paths (which could be done using \samp{line2 + arc}), but also
199 joins the last subpath of \var{line2} and the first one of
200 \var{arc}. Thus, \var{segment} consists of only a single subpath
201 and filling works as expected.
203 An important issue when operating on paths is the parametrisation
204 used. Internally, \PyX{} uses a parametrisation which uses an interval
205 of length $1$ for each path element of a path. For instance, for a
206 simple straight line, the possible parameter values range from $0$ to
207 $1$, corresponding to the first and last point, respectively, of the
208 line. Appending another straight line, would extend this range to a
209 maximal value of $2$.
211 However, the situation becomes more complicated if more complex
212 objects like a circle are involved. Then, one could be tempted to
213 assume that again the parameter value ranges from $0$ to $1$, because
214 the predefined circle consists just of one \class{arc} together with a
215 \class{closepath} element. However, this is not the case: the actual
216 range is much larger. The reason for this behaviour lies in the
217 internal path handling of \PyX: Before performing any non-trivial
218 geometrical operation with a path, it will automatically be converted
219 into an instance of the \class{normpath} class (see also
220 Sect.~\ref{path:normpath}). These so generated paths are already
221 separated in their subpaths and only contain straight lines and
222 B\'ezier curve segments. Thus, as is easily imaginable, they are much
223 simpler to deal with.
225 XXX explain normpathparams and things like p.begin(), p.end()-1,
227 A more geometrical way of accessing a point on the path is to use the
228 arc length of the path segment from the first point of the path to the
229 given point. Thus, all \PyX{} path methods that accept a parameter
230 value also allow the user to pass an arc length. For instance,
231 \begin{verbatim}
232 from math import pi
234 r = 2
235 pt1 = path.circle(0, 0, r).at(r*pi)
236 pt2 = path.circle(0, 0, r).at(r*3*pi/2)
238 c.stroke(path.path(path.moveto(*pt1), path.lineto(*pt2)))
239 \end{verbatim}
240 will draw a straight line from a point at angle $180$ degrees (in
241 radians $\pi$) to another point at angle $270$ degrees (in radians
242 $3\pi/2$) on a circle with radius $r=2$. Note however, that the mapping arc
243 length $\to$ point is in general discontinuous at the begin and the
244 end of a subpath, and thus \PyX{} does not guarantee any particular
245 result for this boundary case.
247 More information on the available path methods can be found
248 in Sect.~\ref{path:path}.
250 \section{Attributes: Styles and Decorations}
252 \label{graphics:attributes}
254 Attributes define properties of a given object when it is being used.
255 Typically, there are different kind of attributes which are usually
256 orthogonal to each other, while for one type of attribute, several
257 choices are possible. An example is the stroking of a path. There,
258 linewidth and linestyle are different kind of attributes. The linewidth
259 might be normal, thin, thick, etc, and the linestyle might be solid,
260 dashed etc.
262 Attributes always occur in lists passed as an optional keyword argument
263 to a method or a function. Usually, attributes are the first keyword
264 argument, so one can just pass the list without specifying the keyword.
265 Again, for the path example, a typical call looks like
267 \begin{verbatim}
268 c.stroke(path, [style.linewidth.Thick, style.linestyle.dashed])
269 \end{verbatim}
271 Here, we also encounter another feature of \PyX's attribute system. For
272 many attributes useful default values are stored as member variables of
273 the actual attribute. For instance, \code{style.linewidth.Thick} is
274 equivalent to \code{style.linewidth(0.04, type="w", unit="cm")}, that is
275 $0.04$ width cm (see Sect.~\ref{unit} for more information about
276 \PyX's unit system).
278 Another important feature of \PyX{} attributes is what is call attributed
279 merging. A trivial example is the following:
280 \begin{verbatim}
281 # the following two lines are equivalent
282 c.stroke(path, [style.linewidth.Thick, style.linewidth.thin])
283 c.stroke(path, [style.linewidth.thin])
284 \end{verbatim}
285 Here, the \code{style.linewidth.thin} attribute overrides the preceding
286 \code{style.linewidth.Thick} declaration. This is especially important
287 in more complex cases where \PyX defines default attributes for a
288 certain operation. When calling the corresponding methods with an
289 attribute list, this list is appended to the list of defaults.
290 This way, the user can easily override certain defaults, while leaving
291 the other default values intact. In addition, every attribute kind
292 defines a special clear attribute, which allows to selectively delete
293 a default value. For path stroking this looks like
294 \begin{verbatim}
295 # the following two lines are equivalent
296 c.stroke(path, [style.linewidth.Thick, style.linewidth.clear])
297 c.stroke(path)
298 \end{verbatim}
299 The clear attribute is also provided by the base classes of
300 the various styles. For instance, \class{style.strokestyle.clear}
301 clears all strokestyle subclasses and thus \class{style.linewidth} and
302 \class{style.linestyle}. Since all attributes derive from
303 \class{attr.attr}, you can remove all defaults using
304 \code{attr.clear}. An overview over the most important attribute typesprovided
305 by PyX is given in the following table.
306 \medskip
307 \begin{center}
308 \begin{tabular}{l|l|p{0.3\linewidth}}
309 Attribute category & description & examples\\
310 \hline
311 \class{deco.deco} & decorator specifying the way the path is drawn &
312 \class{deco.stroked}\newline
313 \class{deco.filled}\newline
314 \class{deco.arrow}
316 \class{style.strokestyle} & style used for path stroking &
317 \class{style.linecap}\newline
318 \class{style.linejoin}\newline
319 \class{style.miterlimit}\newline
320 \class{style.dash}\newline
321 \class{style.linestyle}\newline
322 \class{style.linewidth}\newline
323 \class{color.color}
325 \class{style.fillstyle} & style used for path filling &
326 \class{color.color}\newline\class{pattern.pattern}
328 \class{deformer.deformer} &
329 operations changing the shape of the path
331 \class{deformer.cycloid}\newline
332 \class{deformer.smoothed}
334 \class{text.textattr} & attributes used for typesetting &
335 \class{text.halign}\newline
336 \class{text.valign}\newline
337 \class{text.mathmode}\newline
338 \class{text.phantom}\newline
339 \class{text.size}\newline
340 \class{text.parbox}
342 \class{trafo.trafo}
343 & transformations applied when drawing object
345 \class{trafo.mirror}\newline
346 \class{trafo.rotate}\newline
347 \class{trafo.scale}\newline
348 \class{trafo.slant}\newline
349 \class{trafo.translate}
350 \end{tabular}
351 \end{center}
352 \medskip
354 XXX specify which classes in the table are in fact instances
356 Note that operations usually allow for certain attribute categories
357 only. For example when stroking a path, text attributes are not
358 allowed, while stroke attributes and decorators are. Some attributes
359 might belong to several attribute categories like colours, which are
360 both, stroke and fill attributes.
362 Last, we discuss another important feature of \PyX's attribute system.
363 In order to allow the easy customisation of predefined attributes, it
364 is possible to create a modified attribute by calling of an attribute
365 instance, thereby specifying new parameters. A typical example is to
366 modify the way a path is stroked or filled by constructing appropriate
367 \class{deco.stroked} or \class{deco.filled} instances.
368 For instance, the code
369 \begin{verbatim}
370 c.stroke(path, [deco.filled([color.rgb.green])])
371 \end{verbatim}
372 draws a path filled in green with a black outline. Here,
373 \code{deco.filled} is already an instance which is modified to fill
374 with the given color. Note that an equivalent version would
376 \begin{verbatim}
377 c.draw(path, [deco.stroked, deco.filled([color.rgb.green])])
378 \end{verbatim}
379 In particular, you can see that \class{deco.stroked} is already an
380 attribute instance, since otherwise you were not allowed to pass
381 it as a parameter to the draw method. Another example where
382 the modification of a decorator is useful are arrows. For instance, the following
383 code draws an arrow head with a more acute angle (compared to the
384 default value of $45$ degrees):
385 \begin{verbatim}
386 c.stroke(path, [deco.earrow(angle=30)])
387 \end{verbatim}
390 XXX changeable attributes