new build infrastructure
[PyX/mjg.git] / manual / path.rst
blob3218174fe1a237bd723842766484f7707ad3d9ee
2 Module :mod:`path`
3 ==================
5 .. sectionauthor:: Jörg Lehmann <joergl@users.sourceforge.net>
8 .. _path:
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 .. _path:path:
19 .. module:: path
23 .. class:: path(*pathitems)
25    This class represents a PostScript like path consisting of the path elements
26    *pathitems*.
28    All possible path items are described in Sect. :ref:`path:pathitem`. Note that
29    there are restrictions on the first path element and likewise on each path
30    element after a :class:`closepath` directive. In both cases, no current point is
31    defined and the path element has to be an instance of one of the following
32    classes: :class:`moveto`, :class:`arc`, and :class:`arcn`.
34 Instances of the class :class:`path` provide the following methods (in
35 alphabetic order):
38 .. method:: path.append(pathitem)
40    Appends a *pathitem* to the end of the path.
43 .. method:: path.arclen()
45    Returns the total arc length of the path.\ :math:`^\dagger`
48 .. method:: path.arclentoparam(lengths)
50    Returns the parameter value(s) corresponding to the arc length(s) *lengths*.\
51    :math:`^\dagger`
54 .. method:: path.at(params)
56    Returns the coordinates (as 2-tuple) of the path point(s) corresponding to the
57    parameter value(s) *params*.\ :math:`^\ddagger` :math:`^\dagger`
60 .. method:: path.atbegin()
62    Returns the coordinates (as 2-tuple) of the first point of the path.\
63    :math:`^\dagger`
66 .. method:: path.atend()
68    Returns the coordinates (as 2-tuple) of the end point of the path.\
69    :math:`^\dagger`
72 .. method:: path.bbox()
74    Returns the bounding box of the path. Note that this returned bounding box may
75    be too large, if the path contains any :class:`curveto` elements, since for
76    these the control box, i.e., the bounding box enclosing the control points of
77    the Bézier curve is returned.
80 .. method:: path.begin()
82    Returns the parameter value (a :class:`normpathparam` instance) of the first
83    point in the path.
86 .. method:: path.curveradius(param=None, arclen=None)
88    Returns the curvature radius/radii (or None if infinite) at parameter value(s)
89    params.\ :math:`^\ddagger` This is the inverse of the curvature at this
90    parameter. Note that this radius can be negative or positive, depending on the
91    sign of the curvature.\ :math:`^\dagger`
94 .. method:: path.end()
96    Returns the parameter value (a :class:`normpathparam` instance) of the last
97    point in the path.
100 .. method:: path.extend(pathitems)
102    Appends the list *pathitems* to the end of the path.
105 .. method:: path.intersect(opath)
107    Returns a tuple consisting of two lists of parameter values corresponding to the
108    intersection points of the path with the other path *opath*, respectively.\
109    :math:`^\dagger` For intersection points which are not farther apart then
110    *epsilon* points, only one is returned.
113 .. method:: path.joined(opath)
115    Appends *opath* to the end of the path, thereby merging the last subpath (which
116    must not be closed) of the path with the first sub path of *opath* and returns
117    the resulting new path.\ :math:`^\dagger`
120 .. method:: path.normpath(epsilon=None)
122    Returns the equivalent :class:`normpath`. For the conversion and for later
123    calculations with this :class:`normpath` and accuracy of *epsilon* points is
124    used. If *epsilon* is *None*, the global *epsilon* of the :mod:`path` module is
125    used.
128 .. method:: path.paramtoarclen(params)
130    Returns the arc length(s) corresponding to the parameter value(s) *params*.\
131    :math:`^\ddagger` :math:`^\dagger`
134 .. method:: path.range()
136    Returns the maximal parameter value *param* that is allowed in the path methods.
139 .. method:: path.reversed()
141    Returns the reversed path.\ :math:`^\dagger`
144 .. method:: path.rotation(params)
146    Returns (a) rotations(s) which (each), which rotate the x-direction to the
147    tangent and the y-direction to the normal at that param.\ :math:`^\dagger`
150 .. method:: path.split(params)
152    Splits the path at the parameter values *params*, which have to be sorted in
153    ascending order, and returns a corresponding list of :class:`normpath`
154    instances.\ :math:`^\dagger`
157 .. method:: path.tangent(params, length=1)
159    Return (a) :class:`line` instance(s) corresponding to the tangent vector(s) to
160    the path at the parameter value(s) *params*.\ :math:`^\ddagger` The tangent
161    vector will be scaled to the length *length*.\ :math:`^\dagger`
164 .. method:: path.trafo(params)
166    Returns (a) trafo(s) which (each) translate to a point on the path corresponding
167    to the param, rotate the x-direction to the tangent and the y-direction to the
168    normal in that point.\ :math:`^\dagger`
171 .. method:: path.transformed(trafo)
173    Returns the path transformed according to the linear transformation *trafo*.
174    Here, ``trafo`` must be an instance of the :class:`trafo.trafo` class.\
175    :math:`^\dagger`
177 Some notes on the above:
179 * The :math:`\dagger` denotes methods which require a prior conversion of the
180   path into a :class:`normpath` instance. This is done automatically (using the
181   precision *epsilon* set globally using :meth:`path.set`). If you need a
182   different *epsilon* for a normpath, you also can perform the conversion
183   manually.
185 * Instead of using the :meth:`joined` method, you can also join two paths
186   together with help of the ``<<`` operator, for instance ``p = p1 << p2``.
188 * :math:`^\ddagger` In these methods, *params* may either be a single value or a
189   list. In the latter case, the result of the method will be a list consisting of
190   the results for every parameter.  The parameter itself may either be a length
191   (or a number which is then interpreted as a user length) or an instance of the
192   class :class:`normpathparam`. In the former case, the length refers to the arc
193   length along the path.
196 Path elements
197 -------------
199 .. _path:pathitem:
201 The class :class:`pathitem` is the superclass of all PostScript path
202 construction primitives. It is never used directly, but only by instantiating
203 its subclasses, which correspond one by one to the PostScript primitives.
205 Except for the path elements ending in ``_pt``, all coordinates passed to the
206 path elements can be given as number (in which case they are interpreted as user
207 units with the currently set default type) or in PyX lengths.
209 The following operation move the current point and open a new subpath:
212 .. class:: moveto(x, y)
214    Path element which sets the current point to the absolute coordinates (*x*,
215    *y*). This operation opens a new subpath.
218 .. class:: rmoveto(dx, dy)
220    Path element which moves the current point by (*dx*, *dy*).  This operation
221    opens a new subpath.
223 Drawing a straight line can be accomplished using:
226 .. class:: lineto(x, y)
228    Path element which appends a straight line from the current point to the point
229    with absolute coordinates (*x*, *y*), which becomes the new current point.
232 .. class:: rlineto(dx, dy)
234    Path element which appends a straight line from the current point to the a point
235    with relative coordinates (*dx*, *dy*), which becomes the new current point.
237 For the construction of arc segments, the following three operations are
238 available:
241 .. class:: arc(x, y, r, angle1, angle2)
243    Path element which appends an arc segment in counterclockwise direction with
244    absolute coordinates (*x*, *y*) of the center and  radius *r* from *angle1* to
245    *angle2* (in degrees).  If before the operation, the current point is defined, a
246    straight line is from the current point to the beginning of the arc segment is
247    prepended. Otherwise, a subpath, which thus is the first one in the path, is
248    opened. After the operation, the current point is at the end of the arc segment.
251 .. class:: arcn(x, y, r, angle1, angle2)
253    Path element which appends an arc segment in clockwise direction with absolute
254    coordinates (*x*, *y*) of the center and  radius *r* from *angle1* to *angle2*
255    (in degrees).  If before the operation, the current point is defined, a straight
256    line is from the current point to the beginning of the arc segment is prepended.
257    Otherwise, a subpath, which thus is the first one in the path, is opened. After
258    the operation, the current point is at the end of the arc segment.
261 .. class:: arct(x1, y1, x2, y2, r)
263    Path element which appends an arc segment of radius *r* connecting between
264    (*x1*, *y1*) and (*x2*, *y2*). ---
266 Bézier curves can be constructed using: \
269 .. class:: curveto(x1, y1, x2, y2, x3, y3)
271    Path element which appends a Bézier curve with the current point as first
272    control point and the other control points (*x1*, *y1*), (*x2*, *y2*), and
273    (*x3*, *y3*).
276 .. class:: rcurveto(dx1, dy1, dx2, dy2, dx3, dy3)
278    Path element which appends a Bézier curve with the current point as first
279    control point and the other control points defined relative to the current point
280    by the coordinates (*dx1*, *dy1*), (*dx2*, *dy2*), and (*dx3*, *dy3*).
282 Note that when calculating the bounding box (see Sect. :ref:`bbox`) of Bézier
283 curves, PyX uses for performance reasons the so-called control box, i.e., the
284 smallest rectangle enclosing the four control points of the Bézier curve. In
285 general, this is not the smallest rectangle enclosing the Bézier curve.
287 Finally, an open subpath can be closed using:
290 .. class:: closepath()
292    Path element which closes the current subpath.
294 For performance reasons, two non-PostScript path elements are defined,  which
295 perform multiple identical operations:
298 .. class:: multilineto_pt(points_pt)
300    Path element which appends straight line segments starting from the current
301    point and going through the list of points given  in the *points_pt* argument.
302    All coordinates have to  be given in PostScript points.
305 .. class:: multicurveto_pt(points_pt)
307    Path element which appends Bézier curve segments starting from the current point
308    and going through the list of each three control points given in the *points_pt*
309    argument. Thus, *points_pt* must be a sequence of 6-tuples.
312 Class :class:`normpath`
313 -----------------------
315 .. _path:normpath:
317 The :class:`normpath` class is used internally for all non-trivial path
318 operations, i.e. the ones marked by a :math:`\dagger` in the description of the
319 :class:`path` above. It represents a path as a list of subpaths, which are
320 instances of the class :class:`normsubpath`. These :class:`normsubpath`\ s
321 themselves consist of a list of :class:`normsubpathitems` which are either
322 straight lines (:class:`normline`) or Bézier curves (:class:`normcurve`).
324 A given path can easily be converted to the corresponding :class:`normpath`
325 using the method with this name::
327    np = p.normpath()
329 Additionally, you can specify the accuracy (in points) which is used in all
330 :class:`normpath` calculations by means of the argument *epsilon*, which
331 defaults to to :math:`10^{-5}` points. This default value can be changed using
332 the module function :func:`path.set`.
334 To construct a :class:`normpath` from a list of :class:`normsubpath` instances,
335 you pass them to the :class:`normpath` constructor:
338 .. class:: normpath(normsubpaths=[])
340    Construct a :class:`normpath` consisting of *subnormpaths*, which is a list of
341    :class:`subnormpath` instances.
343 Instances of :class:`normpath` offers all methods of regular :class:`path`\ s,
344 which also have the same semantics. An exception are the methods :meth:`append`
345 and :meth:`extend`. While they allow for adding of instances of
346 :class:`subnormpath` to the :class:`normpath` instance, they also keep the
347 functionality of a regular path and allow for regular path elements to be
348 appended. The later are converted to the proper normpath representation during
349 addition.
351 In addition to the :class:`path` methods, a :class:`normpath` instance also
352 offers the following methods, which operate on the instance itself, i.e., modify
353 it in place.
356 .. method:: normpath.join(other)
358    Join *other*, which has to be a :class:`path` instance, to the :class:`normpath`
359    instance.
362 .. method:: normpath.reverse()
364    Reverses the :class:`normpath` instance.
367 .. method:: normpath.transform(trafo)
369    Transforms the :class:`normpath` instance according to the linear transformation
370    *trafo*.
372 Finally, we remark that the sum of a :class:`normpath` and a :class:`path`
373 always yields a :class:`normpath`.
376 Class :class:`normsubpath`
377 --------------------------
380 .. class:: normsubpath(normsubpathitems=[], closed=0, epsilon=1e-5)
382    Construct a :class:`normsubpath` consisting of *normsubpathitems*, which is a
383    list of :class:`normsubpathitem` instances. If *closed* is set, the
384    :class:`normsubpath` will be closed, thereby appending a straight line segment
385    from the first to the last point, if it is not already present. All calculations
386    with the :class:`normsubpath` are performed with an accuracy of *epsilon*.
388 Most :class:`normsubpath` methods behave like the ones of a :class:`path`.
390 Exceptions are:
393 .. method:: normsubpath.append(anormsubpathitem)
395    Append the *anormsubpathitem* to the end of the :class:`normsubpath` instance.
396    This is only possible if the :class:`normsubpath` is not closed, otherwise an
397    exception is raised.
400 .. method:: normsubpath.extend(normsubpathitems)
402    Extend the :class:`normsubpath` instances by *normsubpathitems*, which has to be
403    a list of :class:`normsubpathitem` instances. This is only possible if the
404    :class:`normsubpath` is not closed, otherwise an exception is raised.
407 .. method:: normsubpath.close()
409    Close the :class:`normsubpath` instance, thereby appending a straight line
410    segment from the first to the last point, if it is not already present.
413 Predefined paths
414 ----------------
416 .. _path:predefined:
418 For convenience, some oft-used paths are already predefined. All of them are
419 subclasses of the :class:`path` class.
422 .. class:: line(x0, y0, x1, y1)
424    A straight line from the point (*x0*, *y0*) to the point (*x1*, *y1*).
427 .. class:: curve(x0, y0, x1, y1, x2, y2, x3, y3)
429    A Bézier curve with  control points  (*x0*, *y0*), :math:`\dots`, (*x3*, *y3*).\
432 .. class:: rect(x, y, w, h)
434    A closed rectangle with lower left point (*x*, *y*), width *w*, and height *h*.
437 .. class:: circle(x, y, r)
439    A closed circle with center (*x*, *y*) and radius *r*.
441 .. % %% Local Variables:
442 .. % %% mode: latex
443 .. % %% TeX-master: "manual.tex"
444 .. % %% ispell-dictionary: "british"
445 .. % %% End: