converted more docs to new style
[PyX/mjg.git] / manual / path.tex
blobaef6b90a2494c5ba042c7c94597a9de96dcde314
1 \chapter{Basic graphics}
3 \sectionauthor{J\"org Lehmann}{joergl@users.sourceforge.net}
5 \label{path}
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 built
12 up of straight lines, arc segments and cubic Bezier curves. Such a
13 path does not have to be connected but may also consist of multiple
14 connected segments, which will be called \textit{sub paths} in the
15 following.
17 Usually, a path is constructed by passing a list of the path
18 primitives \verb|moveto|, \verb|lineto|, \verb|curveto|, etc., to the
19 constructor of the \verb|path| class. The following code snippet, for
20 instance, defines a path \verb|p| that consists of a straight line
21 from the point $(0, 0)$ to the point $(1, 1)$
22 \begin{verbatim}
23 from pyx import *
24 p = path.path(path.moveto(0, 0), path.lineto(1, 1))
25 \end{verbatim}
26 Equivalently, one can also use the predefined \verb|path| subclass
27 \verb|line| and write
28 \begin{verbatim}
29 p = path.line(0, 0, 1, 1)
30 \end{verbatim}
32 While you can already do some geometrical operations with the
33 just created path (see next section), we need another \PyX{} object
34 in order to be actually able to draw the path, namely
35 an instance of the \verb|canvas| class. By convention, we use
36 the name \verb|c| for this instance:
37 \begin{verbatim}
38 c = canvas.canvas()
39 \end{verbatim}
40 In order to draw the path on the canvas, we use the \verb|stroke| method
41 of the \verb|canvas| class, i.e.,
42 \begin{verbatim}
43 c.stroke(p)
44 c.writeEPSfile("line")
45 \end{verbatim}
46 To complete the example, we have added a \verb|writeEPSfile| call,
47 which writes the contents of the canvas into the given file.
49 Let us as second example define a path which consists of more than
50 one sub path:
51 \begin{verbatim}
52 cross = path.path(path.moveto(0, 0), path.rlineto(1, 1),
53 path.moveto(1, 0), path.rlineto(-1, 1))
54 \end{verbatim}
55 The first sub path is again a straight line from $(0, 0)$ to $(1, 1)$,
56 with the only difference that we now have used the \verb|rlineto|
57 class, whose arguments count relative from the last point in the path.
58 The second \verb|moveto| instance opens a new sub path starting at the
59 point $(1, 0)$ and ending at $(0, 1)$. Note that although both lines
60 intersect at the point $(1/2, 1/2)$, they count as separate sub paths.
61 The general rule is that each occurence of \verb|moveto| opens a new
62 sub path. This means that if one wants to draw a rectangle, one should
63 not use
64 \begin{verbatim}
65 # wrong: do not use moveto when you want a single sub path
66 rect1 = path.path(path.moveto(0, 0), path.lineto(0, 1),
67 path.moveto(1, 0), path.lineto(1, 1),
68 path.moveto(1, 1), path.lineto(1, 1),
69 path.moveto(0, 1), path.lineto(0, 0))
70 \end{verbatim}
71 which would construct a rectangle consisting of four disconnected
72 sub paths. Instead the correct way of defining a rectangle is
73 \begin{verbatim}
74 # correct: a rectangle consisting of a single closed sub path
75 rect2 = path.path(path.moveto(0, 0), path.lineto(0, 1),
76 path.lineto(1, 1), path.lineto(1, 0),
77 path.closepath())
78 \end{verbatim}
80 \begin{figure}
81 \centerline{\includegraphics{rects}}
82 \caption{Not closed (left) and closed (midlle) rectangle. Filling a
83 path (right) always closes it automatically.}
84 \label{fig:rects}
85 \end{figure}
86 Note that for the last straight line of the rectangle (from $(0, 1)$
87 back to the origin at $(0, 0)$)) we have used \verb|closepath|. This
88 directive adds a straight line from the current point to the first
89 point of the current sub path and furthermore \textit{closes} the sub
90 path, i.e., it joins the beginning and the end of the line segment.
91 The difference can be appreciated in Fig.~\ref{fig:rects}, where
92 also a filled (and at the same time stroked) rectangle is shown.
93 The corresponding code looks like
94 \begin{verbatim}
95 c.stroke(rect1, [deco.filled([color.grey(0.95)])])
96 \end{verbatim}
97 The important point to remember here is that when filling a path, PostScript
98 automatically closes it.
100 Of course, rectangles are also predefined in \PyX{}, so above we could
101 have as well written
102 \begin{verbatim}
103 rect2 = path.rect(0, 0, 1, 1)
104 \end{verbatim}
105 Here, the first two arguments specify the origin of the rectangle
106 while the second two arguments define its width and height,
107 respectively.
109 XXX arc, bezier example
111 \section{Path operations}
113 Often, one not only wants to stroke or fill a path on the canvas
114 but before do some geometrical operations with it. For instance, one
115 might want to intersect one path with another one and the split the
116 paths at the intersection points and then join the segments together
117 in a new way. \PyX{} supports such tasks by means of a number
118 of path methods, which we will introduce in the following.
120 Suppose you want to draw the radii to the intersection points of a
121 circle with a straight line. This task can be done using the following
122 code which gives the result shown in Fig.~\ref{fig:radii}
123 \verbatiminput{radii.py}
124 \begin{figure}
125 \centerline{\includegraphics{radii}}
126 %\caption{}
127 \label{fig:radii}
128 \end{figure}
129 Passing another path, here \verb|line|, to the \verb|intersect| method
130 of \verb|circle|, we obtain a tuple of parameter values of the
131 intersection points. The first element of the tuple is a list of
132 parameter values for the path whose \verb|intersect| method we have
133 called, the second element is the corresponding list for the path
134 passed as argument to this method. In the present example, we only
135 need one list of parameter values, namely \verb|isects_circle|.
136 Iterating over the elements of this list, we draw the radii, using the
137 \verb|at| path method to obtain the point corresponding to the
138 parameter value.
140 Another powerful feature of \PyX{} is its ability to split paths at a
141 given set of parameters. For instance, in order to fill in the
142 previous example the segment of the circle delimited by the straight
143 line (cf.\ Fig.~\ref{fig:radii2}), you first have to construct a path
144 corresponding to the outline of this segment. The following code
145 snippet does yield this \verb|segment|
146 \begin{verbatim}
147 arc1, arc2 = circle.split(isects_circle)
148 arc = arc1.arclen()<arc2.arclen() and arc1 or arc2
150 isects_line.sort()
151 line1, line2, line3 = line.split(isects_line)
153 segment = line2 << arc
154 \end{verbatim}
155 \begin{figure}
156 \centerline{\includegraphics{radii2}}
157 %\caption{}
158 \label{fig:radii2}
159 \end{figure}
160 Here, we first split the circle using the \verb|split| method passing
161 the list of parameters obtained above. Since the circle is closed,
162 this yields two arc segments. We then use the \verb|arclen|, which
163 returns the arc length of the path, to find the shorter of the two
164 arcs. Before splitting the line, we have to take into account that
165 the \verb|split| method only accepts a sorted list of parameters.
166 Finally, we join the straight line and the arc segment. For
167 this, we make use of the \verb|<<| operator, which not only adds
168 the paths (which could be done using \verb|line2 + arc|), but also
169 joins the last sub path of \verb|line2| and the first one of
170 \verb|arc|. Thus, \verb|segment| consists of only a single sub path
171 and filling works as expected.
173 XXX reverse, reversed, parametrisation, arclen parameters
176 \section{Module path}
178 The \module{path} module defines several important classes which are
179 documented in the present section.
181 \subsection{Class \class{path} --- PostScript-like paths}
183 \declaremodule{}{path}
185 \begin{classdesc}{path}{*pathels}
186 This class represents a PostScript like path consisting of the
187 elements \var{pathels}.
188 \end{classdesc}
190 Instances of the class \class{path} provide the following
191 methods (in alphabetic order):
193 \begin{methoddesc}{append}{pathel}
194 Appends a \var|pathel| to the end of the path.
195 \end{methoddesc}
197 \begin{methoddesc}{arclen}{}
198 Returns the total arc length of the path.$^\dagger$
199 \end{methoddesc}
201 \begin{methoddesc}{arclentoparam}{lengths}
202 Returns the parameter values corresponding to the arc lengths
203 \var{lengths}.$^\dagger$
204 \end{methoddesc}
206 \begin{methoddesc}{at}{param=None, arclen=None}
207 Returns the coordinates (as 2-tuple) of the path point corresponding to the
208 parameter value \var{param} or, alternatively, the arc length
209 \var{arclen}. The parameter value \var{param} (\var{arclen}) has to be smaller
210 or equal to \method{self.range()} (\method{self.arclen()}),
211 otherwise an exception is raised. At discontinuities in the path,
212 the limit from below is returned.$^\dagger$
213 \end{methoddesc}
215 \begin{methoddesc}{bbox}{}
216 Returns the bounding box of the path. Note that this returned
217 bounding box may be too large, if the path contains any
218 \class{curveto} elements, since for these the control box, i.e., the
219 bounding box enclosing the control points of the B\'ezier curve is
220 returned.
221 \end{methoddesc}
223 \begin{methoddesc}{begin}{}
224 Returns the coordinates (as 2-tuple) of the first point of the path.$^\dagger$
225 \end{methoddesc}
227 \begin{methoddesc}{curvradius}{param=None, arclen=None}
228 Returns the curvature radius (or None if infinite) at parameter
229 param or, alternatively, arc length \var{arclen}. This is the
230 inverse of the curvature at this parameter Please note that this
231 radius can be negative or positive, depending on the sign of the
232 curvature.$^\dagger$
233 \end{methoddesc}
235 \begin{methoddesc}{end}{}
236 Returns the coordinates (as 2-tuple) of the end point of the path.$^\dagger$
237 \end{methoddesc}
239 \begin{methoddesc}{intersect}{opath}
240 Returns a tuple consisting of two lists of parameter values
241 corresponding to the intersection points of the path with the other
242 path \var{opath}, respectively.$^\dagger$
243 \end{methoddesc}
245 \begin{methoddesc}{joined}{opath}
246 Appends \var{opath} to the end of the path, thereby merging the last
247 sub path (which must not be closed) of the path with the first sub
248 path of \var{opath} and returns the resulting new path.$^\dagger$
249 \end{methoddesc}
251 \begin{methoddesc}{range}{}
252 Returns the maximal parameter value \var{param} that is allowed in the
253 path methods.
254 \end{methoddesc}
256 \begin{methoddesc}{reversed}{}
257 Returns the reversed path.$^\dagger$
258 \end{methoddesc}
260 \begin{methoddesc}{split}{params}
261 Splits the path at the parameters \var{params}, which have to be
262 sorted in ascending order, and returns a corresponding list of
263 \class{normpath} instances.$^\dagger$
264 \end{methoddesc}
266 \begin{methoddesc}{tangent}{param=None, arclen=None, length=None}
267 Return a \class{line} instance corresponding to the tangent vector
268 to the path at the parameter value \var{param} or, alternatively, the arc length
269 \var{arclen}. The parameter value \var{param} (\var{arclen}) has to be smaller
270 or equal to \method{self.range()} (\method{self.arclen()}),
271 otherwise an exception is raised. At discontinuities in the path,
272 the limit from below is returned. If \var{length} is not
273 \texttt{None}, the tangent vector will be scaled correspondingly.$^\dagger$
274 \end{methoddesc}
277 \begin{methoddesc}{trafo}{param=None, arclen=None}
278 Returns a trafo which maps a point $(0, 1)$ to the tangent vector to
279 the path at the parameter value \var{param} or, alternatively, the
280 arc length \var{arclen}. The parameter value \var{param} (\var{arclen}) has to
281 be smaller or equal to \method{self.range()}
282 (\method{self.arclen()}), otherwise an exception is raised. At
283 discontinuities in the path, the limit from below is returned.$^\dagger$
284 \end{methoddesc}
286 \begin{methoddesc}{tranformed}{trafo}
287 Returns the path tranformed according to the linear transformation
288 \var{trafo}. Here, \texttt{trafo} must be an instance of the
289 \class{trafo.trafo} class.$^\dagger$
290 \end{methoddesc}
292 Some notes on the above:
293 \begin{itemize}
294 \item The $\dagger$ denotes methods which require a prior
295 conversion of the path into a \verb|normpath| instance. This is
296 done automatically, but if you need to call such methods often,
297 it is a good idea to do the conversion once for performance reasons.
298 \item Instead of using the \verb|glue| method, you can also glue two
299 paths together with help of the \verb|<<| operator, for instance
300 \verb|p = p1 << p2|.
301 \item In the methods accepting both a parameter value \verb|param| and
302 an arc length \verb|arclen|, exactly one of these arguments has to
303 provided.
304 \end{itemize}
306 \subsection{Path elements}
308 The class \class{pathel} is the superclass of all PostScript path
309 construction primitives. It is never used directly, but only by
310 instantiating its subclasses, which correspond one by one to the
311 PostScript primitives.
313 The following operation move the current point and open a new
314 sub path:
316 \begin{classdesc}{moveto}{x, y}
317 Path element which sets the current point to the absolute coordinates (\var{x},
318 \var{y}). This operation opens a new subpath.
319 \end{classdesc}
321 \begin{classdesc}{rmoveto}{dx, dy}
322 Path element which moves the current point by (\var{dx}, \var{dy}).
323 This operation opens a new subpath.
324 \end{classdesc}
326 Drawing a straight line can be accomplished using:
328 \begin{classdesc}{lineto}{x, y}
329 Path element which appends a straight line from the current point to the
330 point with absolute coordinates (\var{x}, \var{y}), which becomes
331 the new current point.
332 \end{classdesc}
334 \begin{classdesc}{rlineto}{dx, dy}
335 Path element which appends a straight line from the current point to the
336 a point with relative coordinates (\var{dx}, \var{dy}), which becomes
337 the new current point.
338 \end{classdesc}
340 For the construction of arc segment, the following three operations
341 are available:
343 \begin{classdesc}{arc}{x, y, r, angle1, angle2}
344 Path element which appends an arc segment in counterclockwise direction
345 with absolute coordinates (\var{x}, \var{y}) of the center and
346 radius \var{r} from \var{angle1} to \var{angle2} (in degrees).
347 If before the operation, the current point is defined, a straight line
348 is from the current point to the beginning of the arc segment is
349 prepended. Otherwise, a subpath, which thus is the first one in the
350 path, is opened. After the operation, the current point is at the end
351 of the arc segment.
352 \end{classdesc}
354 \begin{classdesc}{arcn}{x, y, r, angle1, angle2}
355 Path element which appends an arc segment in clockwise direction
356 with absolute coordinates (\var{x}, \var{y}) of the center and
357 radius \var{r} from \var{angle1} to \var{angle2} (in degrees).
358 If before the operation, the current point is defined, a straight line
359 is from the current point to the beginning of the arc segment is
360 prepended. Otherwise, a subpath, which thus is the first one in the
361 path, is opened. After the operation, the current point is at the end
362 of the arc segment.
363 \end{classdesc}
365 \begin{classdesc}{arct}{x1, y1, x2, y2, r}
366 Path element which appends an arc segment of radius \var{r}
367 connecting between (\var{x1}, \var{y1}) and (\var{x2}, \var{y2}).\\
368 \end{classdesc}
370 B\'ezier curves can be constructed using: \
372 \begin{classdesc}{curveto}{x1, y1, x2, y2, x3, y3}
373 Path element which appends a B\'ezier curve with
374 the current point as first control point and the other control points
375 (\var{x1}, \var{y1}), (\var{x2}, \var{y2}), and (\var{x3}, \var{y3}).
376 \end{classdesc}
378 \begin{classdesc}{rcurveto}{dx1, dy1, dx2, dy2, dx3, dy3}
379 Path element which appends a B\'ezier curve with
380 the current point as first control point and the other control points
381 defined relative to the current point by the coordinates
382 (\var{dx1}, \var{dy1}), (\var{dx2}, \var{dy2}), and (\var{dx3}, \var{dy3}).
383 \end{classdesc}
385 Finally, an open sub path can be closed using:
387 \begin{classdesc}{closepath}{}
388 Path element which closes the current subpath.
389 \end{classdesc}
391 XXX \class{multicurveto} and \class{multilineto}
393 Some notes on the above:
394 \begin{itemize}
395 \item All coordinates can be given as number (in which case they are
396 interpreted as user units with the currently set default type or in
397 \PyX\ lengths.
398 \item The bounding box (see below) of B\'ezier curves is actually
399 the box enclosing the control points, \textit{i.e.}\ not neccesarily the
400 smallest rectangle enclosing the B\'ezier curve.
401 \end{itemize}
403 \subsection{Class \class{normpath}}
405 The \class{normpath} class represents a specialized form of a
406 \class{path} containing only the elements \class{moveto},
407 \class{lineto}, \class{curveto} and \class{closepath}. Such normalized
408 paths are used for all of the more sophisticated path operations
409 which are denoted by a $\dagger$ in the description of the \class{path}
410 class above.
412 Any path can easily be converted to its normalized form by passing it
413 as parameter to the \class{normpath} constructor,
414 \begin{verbatim}
415 np = normpath(p)
416 \end{verbatim}
417 Additionally, you can specify the accuracy (in points) which is used
418 in all \class{normpath} calculations by means of the keyword argument
419 \var{epsilon}, which defaults to $10^{-5}$. Note that the sum of a
420 \class{normpath} and a \class{path} always yields a \class{normpath}.
422 XXX additional operations of normpaths
424 \subsection{Predefined paths}
426 For your convenience, some special PostScript paths are already defined.
427 All of them are sub classes of the \class{path} class.
429 \begin{classdesc}{line}{x1, y1, x2, y2, x3, y3}
430 A straight line from the point (\var{x1}, \var{y1}) to the point (\var{x2}, \var{y2}).
431 \end{classdesc}
433 \begin{classdesc}{curve}{x1, y1, x2, y2, x3, y3, x4, y4}
434 A B\'ezier curve with
435 control points (\var{x0}, \var{y0}), $\dots$, (\var{x3}, \var{y3}).\
436 \end{classdesc}
438 \begin{classdesc}{rect}{x, y, w, h}
439 A closed rectangle with lower left point (\var{x}, \var{y}), width \var{w}, and
440 height \var{h}.
441 \end{classdesc}
443 \begin{classdesc}{circle}{x, y, r}
444 A closed circle with center (\var{x}, \var{y}) and radius \var{r}.
445 \end{classdesc}
447 %%% Local Variables:
448 %%% mode: latex
449 %%% TeX-master: "manual.tex"
450 %%% ispell-dictionary: "british"
451 %%% End: