another update of the download location (will hopefully finally fix easy_install)
[PyX/mjg.git] / manual / path.rst
blobf5727d15b8bddb707a4dc5c7e4960d08bab9f625
1 .. module:: path
3 ==================
4 Module :mod:`path`
5 ==================
7 .. sectionauthor:: Jörg Lehmann <joergl@users.sourceforge.net>
10 The :mod:`path` module defines several important classes which are documented in
11 the present section.
14 Class :class:`path` --- PostScript-like paths
15 ---------------------------------------------
17 .. class:: path(*pathitems)
19    This class represents a PostScript like path consisting of the path elements
20    *pathitems*.
22    All possible path items are described in Sect. :ref:`path_pathitem`. Note that
23    there are restrictions on the first path element and likewise on each path
24    element after a :class:`closepath` directive. In both cases, no current point is
25    defined and the path element has to be an instance of one of the following
26    classes: :class:`moveto`, :class:`arc`, and :class:`arcn`.
28 Instances of the class :class:`path` provide the following methods (in
29 alphabetic order):
32 .. method:: path.append(pathitem)
34    Appends a *pathitem* to the end of the path.
37 .. method:: path.arclen()
39    Returns the total arc length of the path.\ :math:`^\dagger`
42 .. method:: path.arclentoparam(lengths)
44    Returns the parameter value(s) corresponding to the arc length(s) *lengths*.\
45    :math:`^\dagger`
48 .. method:: path.at(params)
50    Returns the coordinates (as 2-tuple) of the path point(s) corresponding to the
51    parameter value(s) *params*.\ :math:`^\ddagger` :math:`^\dagger`
54 .. method:: path.atbegin()
56    Returns the coordinates (as 2-tuple) of the first point of the path.\
57    :math:`^\dagger`
60 .. method:: path.atend()
62    Returns the coordinates (as 2-tuple) of the end point of the path.\
63    :math:`^\dagger`
66 .. method:: path.bbox()
68    Returns the bounding box of the path. Note that this returned bounding box may
69    be too large, if the path contains any :class:`curveto` elements, since for
70    these the control box, i.e., the bounding box enclosing the control points of
71    the Bézier curve is returned.
74 .. method:: path.begin()
76    Returns the parameter value (a :class:`normpathparam` instance) of the first
77    point in the path.
80 .. method:: path.curveradius(param=None, arclen=None)
82    Returns the curvature radius/radii (or None if infinite) at parameter value(s)
83    params.\ :math:`^\ddagger` This is the inverse of the curvature at this
84    parameter. Note that this radius can be negative or positive, depending on the
85    sign of the curvature.\ :math:`^\dagger`
88 .. method:: path.end()
90    Returns the parameter value (a :class:`normpathparam` instance) of the last
91    point in the path.
94 .. method:: path.extend(pathitems)
96    Appends the list *pathitems* to the end of the path.
99 .. method:: path.intersect(opath)
101    Returns a tuple consisting of two lists of parameter values corresponding to the
102    intersection points of the path with the other path *opath*, respectively.\
103    :math:`^\dagger` For intersection points which are not farther apart then
104    *epsilon* points, only one is returned.
107 .. method:: path.joined(opath)
109    Appends *opath* to the end of the path, thereby merging the last subpath (which
110    must not be closed) of the path with the first sub path of *opath* and returns
111    the resulting new path.\ :math:`^\dagger`
114 .. method:: path.normpath(epsilon=None)
116    Returns the equivalent :class:`normpath`. For the conversion and for later
117    calculations with this :class:`normpath` and accuracy of *epsilon* points is
118    used. If *epsilon* is *None*, the global *epsilon* of the :mod:`path` module is
119    used.
122 .. method:: path.paramtoarclen(params)
124    Returns the arc length(s) corresponding to the parameter value(s) *params*.\
125    :math:`^\ddagger` :math:`^\dagger`
128 .. method:: path.range()
130    Returns the maximal parameter value *param* that is allowed in the path methods.
133 .. method:: path.reversed()
135    Returns the reversed path.\ :math:`^\dagger`
138 .. method:: path.rotation(params)
140    Returns (a) rotations(s) which (each), which rotate the x-direction to the
141    tangent and the y-direction to the normal at that param.\ :math:`^\dagger`
144 .. method:: path.split(params)
146    Splits the path at the parameter values *params*, which have to be sorted in
147    ascending order, and returns a corresponding list of :class:`normpath`
148    instances.\ :math:`^\dagger`
151 .. method:: path.tangent(params, length=1)
153    Return (a) :class:`line` instance(s) corresponding to the tangent vector(s) to
154    the path at the parameter value(s) *params*.\ :math:`^\ddagger` The tangent
155    vector will be scaled to the length *length*.\ :math:`^\dagger`
158 .. method:: path.trafo(params)
160    Returns (a) trafo(s) which (each) translate to a point on the path corresponding
161    to the param, rotate the x-direction to the tangent and the y-direction to the
162    normal in that point.\ :math:`^\dagger`
165 .. method:: path.transformed(trafo)
167    Returns the path transformed according to the linear transformation *trafo*.
168    Here, ``trafo`` must be an instance of the :class:`trafo.trafo` class.\
169    :math:`^\dagger`
171 Some notes on the above:
173 * The :math:`\dagger` denotes methods which require a prior conversion of the
174   path into a :class:`normpath` instance. This is done automatically (using the
175   precision *epsilon* set globally using :meth:`path.set`). If you need a
176   different *epsilon* for a normpath, you also can perform the conversion
177   manually.
179 * Instead of using the :meth:`joined` method, you can also join two paths
180   together with help of the ``<<`` operator, for instance ``p = p1 << p2``.
182 * :math:`^\ddagger` In these methods, *params* may either be a single value or a
183   list. In the latter case, the result of the method will be a list consisting of
184   the results for every parameter.  The parameter itself may either be a length
185   (or a number which is then interpreted as a user length) or an instance of the
186   class :class:`normpathparam`. In the former case, the length refers to the arc
187   length along the path.
190 .. _path_pathitem:
192 Path elements
193 -------------
195 The class :class:`pathitem` is the superclass of all PostScript path
196 construction primitives. It is never used directly, but only by instantiating
197 its subclasses, which correspond one by one to the PostScript primitives.
199 Except for the path elements ending in ``_pt``, all coordinates passed to the
200 path elements can be given as number (in which case they are interpreted as user
201 units with the currently set default type) or in PyX lengths.
203 The following operation move the current point and open a new subpath:
206 .. class:: moveto(x, y)
208    Path element which sets the current point to the absolute coordinates (*x*,
209    *y*). This operation opens a new subpath.
212 .. class:: rmoveto(dx, dy)
214    Path element which moves the current point by (*dx*, *dy*).  This operation
215    opens a new subpath.
217 Drawing a straight line can be accomplished using:
220 .. class:: lineto(x, y)
222    Path element which appends a straight line from the current point to the point
223    with absolute coordinates (*x*, *y*), which becomes the new current point.
226 .. class:: rlineto(dx, dy)
228    Path element which appends a straight line from the current point to the a point
229    with relative coordinates (*dx*, *dy*), which becomes the new current point.
231 For the construction of arc segments, the following three operations are
232 available:
235 .. class:: arc(x, y, r, angle1, angle2)
237    Path element which appends an arc segment in counterclockwise direction with
238    absolute coordinates (*x*, *y*) of the center and  radius *r* from *angle1* to
239    *angle2* (in degrees).  If before the operation, the current point is defined, a
240    straight line is from the current point to the beginning of the arc segment is
241    prepended. Otherwise, a subpath, which thus is the first one in the path, is
242    opened. After the operation, the current point is at the end of the arc segment.
245 .. class:: arcn(x, y, r, angle1, angle2)
247    Path element which appends an arc segment in clockwise direction with absolute
248    coordinates (*x*, *y*) of the center and  radius *r* from *angle1* to *angle2*
249    (in degrees).  If before the operation, the current point is defined, a straight
250    line is from the current point to the beginning of the arc segment is prepended.
251    Otherwise, a subpath, which thus is the first one in the path, is opened. After
252    the operation, the current point is at the end of the arc segment.
255 .. class:: arct(x1, y1, x2, y2, r)
257    Path element which appends an arc segment of radius *r* connecting between
258    (*x1*, *y1*) and (*x2*, *y2*). ---
260 Bézier curves can be constructed using: \
263 .. class:: curveto(x1, y1, x2, y2, x3, y3)
265    Path element which appends a Bézier curve with the current point as first
266    control point and the other control points (*x1*, *y1*), (*x2*, *y2*), and
267    (*x3*, *y3*).
270 .. class:: rcurveto(dx1, dy1, dx2, dy2, dx3, dy3)
272    Path element which appends a Bézier curve with the current point as first
273    control point and the other control points defined relative to the current point
274    by the coordinates (*dx1*, *dy1*), (*dx2*, *dy2*), and (*dx3*, *dy3*).
276 Note that when calculating the bounding box (see Sect. :mod:`bbox`) of Bézier
277 curves, PyX uses for performance reasons the so-called control box, i.e., the
278 smallest rectangle enclosing the four control points of the Bézier curve. In
279 general, this is not the smallest rectangle enclosing the Bézier curve.
281 Finally, an open subpath can be closed using:
284 .. class:: closepath()
286    Path element which closes the current subpath.
288 For performance reasons, two non-PostScript path elements are defined,  which
289 perform multiple identical operations:
292 .. class:: multilineto_pt(points_pt)
294    Path element which appends straight line segments starting from the current
295    point and going through the list of points given  in the *points_pt* argument.
296    All coordinates have to  be given in PostScript points.
299 .. class:: multicurveto_pt(points_pt)
301    Path element which appends Bézier curve segments starting from the current point
302    and going through the list of each three control points given in the *points_pt*
303    argument. Thus, *points_pt* must be a sequence of 6-tuples.
306 .. _path_normpath:
308 Class :class:`normpath`
309 -----------------------
311 The :class:`normpath` class is used internally for all non-trivial path
312 operations, i.e. the ones marked by a :math:`\dagger` in the description of the
313 :class:`path` above. It represents a path as a list of subpaths, which are
314 instances of the class :class:`normsubpath`. These :class:`normsubpath`\ s
315 themselves consist of a list of :class:`normsubpathitems` which are either
316 straight lines (:class:`normline`) or Bézier curves (:class:`normcurve`).
318 A given path can easily be converted to the corresponding :class:`normpath`
319 using the method with this name::
321    np = p.normpath()
323 Additionally, you can specify the accuracy (in points) which is used in all
324 :class:`normpath` calculations by means of the argument *epsilon*, which
325 defaults to to :math:`10^{-5}` points. This default value can be changed using
326 the module function :func:`path.set`.
328 To construct a :class:`normpath` from a list of :class:`normsubpath` instances,
329 you pass them to the :class:`normpath` constructor:
332 .. class:: normpath(normsubpaths=[])
334    Construct a :class:`normpath` consisting of *subnormpaths*, which is a list of
335    :class:`subnormpath` instances.
337 Instances of :class:`normpath` offers all methods of regular :class:`path`\ s,
338 which also have the same semantics. An exception are the methods :meth:`append`
339 and :meth:`extend`. While they allow for adding of instances of
340 :class:`subnormpath` to the :class:`normpath` instance, they also keep the
341 functionality of a regular path and allow for regular path elements to be
342 appended. The later are converted to the proper normpath representation during
343 addition.
345 In addition to the :class:`path` methods, a :class:`normpath` instance also
346 offers the following methods, which operate on the instance itself, i.e., modify
347 it in place.
350 .. method:: normpath.join(other)
352    Join *other*, which has to be a :class:`path` instance, to the :class:`normpath`
353    instance.
356 .. method:: normpath.reverse()
358    Reverses the :class:`normpath` instance.
361 .. method:: normpath.transform(trafo)
363    Transforms the :class:`normpath` instance according to the linear transformation
364    *trafo*.
366 Finally, we remark that the sum of a :class:`normpath` and a :class:`path`
367 always yields a :class:`normpath`.
370 Class :class:`normsubpath`
371 --------------------------
374 .. class:: normsubpath(normsubpathitems=[], closed=0, epsilon=1e-5)
376    Construct a :class:`normsubpath` consisting of *normsubpathitems*, which is a
377    list of :class:`normsubpathitem` instances. If *closed* is set, the
378    :class:`normsubpath` will be closed, thereby appending a straight line segment
379    from the first to the last point, if it is not already present. All calculations
380    with the :class:`normsubpath` are performed with an accuracy of *epsilon*.
382 Most :class:`normsubpath` methods behave like the ones of a :class:`path`.
384 Exceptions are:
387 .. method:: normsubpath.append(anormsubpathitem)
389    Append the *anormsubpathitem* to the end of the :class:`normsubpath` instance.
390    This is only possible if the :class:`normsubpath` is not closed, otherwise an
391    exception is raised.
394 .. method:: normsubpath.extend(normsubpathitems)
396    Extend the :class:`normsubpath` instances by *normsubpathitems*, which has to be
397    a list of :class:`normsubpathitem` instances. This is only possible if the
398    :class:`normsubpath` is not closed, otherwise an exception is raised.
401 .. method:: normsubpath.close()
403    Close the :class:`normsubpath` instance, thereby appending a straight line
404    segment from the first to the last point, if it is not already present.
407 .. _path_predefined:
409 Predefined paths
410 ----------------
413 For convenience, some oft-used paths are already predefined. All of them are
414 subclasses of the :class:`path` class.
417 .. class:: line(x0, y0, x1, y1)
419    A straight line from the point (*x0*, *y0*) to the point (*x1*, *y1*).
422 .. class:: curve(x0, y0, x1, y1, x2, y2, x3, y3)
424    A Bézier curve with  control points  (*x0*, *y0*), :math:`\dots`, (*x3*, *y3*).\
427 .. class:: rect(x, y, w, h)
429    A closed rectangle with lower left point (*x*, *y*), width *w*, and height *h*.
432 .. class:: circle(x, y, r)
434    A closed circle with center (*x*, *y*) and radius *r*.