\chapter{Basic graphics}

\sectionauthor{J\"org Lehmann}{joergl@users.sourceforge.net} 

\label{graphics}

\section{Introduction}

The path module allows one to construct PostScript-like
\textit{paths}, which are one of the main building blocks for the
generation of drawings. A PostScript path is an arbitrary shape built
up of straight lines, arc segments and cubic Bezier curves. Such a
path does not have to be connected but may also consist of multiple
connected segments, which will be called \textit{sub paths} in the
following.

Usually, a path is constructed by passing a list of the path
primitives \class{moveto}, \class{lineto}, \class{curveto}, etc., to the
constructor of the \class{path} class. The following code snippet, for
instance, defines a path \var{p} that consists of a straight line
from the point $(0, 0)$ to the point $(1, 1)$
\begin{verbatim}
from pyx import *
p = path.path(path.moveto(0, 0), path.lineto(1, 1))
\end{verbatim}
Equivalently, one can also use the predefined \class{path} subclass
\class{line} and write
\begin{verbatim}
p = path.line(0, 0, 1, 1)
\end{verbatim}

While you can already do some geometrical operations with the
just created path (see next section), we need another \PyX{} object
in order to be actually able to draw the path, namely
an instance of the \class{canvas} class. By convention, we use
the name \var{c} for this instance:
\begin{verbatim}
c = canvas.canvas()
\end{verbatim}
In order to draw the path on the canvas, we use the \method{stroke()} method
of the \class{canvas} class, i.e.,
\begin{verbatim}
c.stroke(p)
c.writeEPSfile("line")
\end{verbatim}
To complete the example, we have added a \method{writeEPSfile()} call,
which writes the contents of the canvas into the given file.

Let us as second example define a path which consists of more than 
one sub path:
\begin{verbatim}
cross = path.path(path.moveto(0, 0), path.rlineto(1, 1),
                  path.moveto(1, 0), path.rlineto(-1, 1))
\end{verbatim}
The first sub path is again a straight line from $(0, 0)$ to $(1, 1)$,
with the only difference that we now have used the \class{rlineto}
class, whose arguments count relative from the last point in the path.
The second \class{moveto} instance opens a new sub path starting at the
point $(1, 0)$ and ending at $(0, 1)$. Note that although both lines
intersect at the point $(1/2, 1/2)$, they count as separate sub paths.
The general rule is that each occurence of \class{moveto} opens a new
sub path. This means that if one wants to draw a rectangle, one should
not use
\begin{verbatim}
# wrong: do not use moveto when you want a single sub path
rect1 = path.path(path.moveto(0, 0), path.lineto(0, 1),
                  path.moveto(1, 0), path.lineto(1, 1),
                  path.moveto(1, 1), path.lineto(1, 1),
                  path.moveto(0, 1), path.lineto(0, 0))
\end{verbatim}
which would construct a rectangle consisting of four disconnected
sub paths. Instead the correct way of defining a rectangle is 
\begin{verbatim}
# correct: a rectangle consisting of a single closed sub path
rect2 = path.path(path.moveto(0, 0), path.lineto(0, 1), 
                  path.lineto(1, 1), path.lineto(1, 0),
                  path.closepath())
\end{verbatim}
%
\begin{figure}
\centerline{\includegraphics{rects}}
\caption{Not closed (left) and closed (midlle) rectangle. Filling a
  path (right) always closes it automatically.}
\label{fig:rects}
\end{figure}
Note that for the last straight line of the rectangle (from $(0, 1)$
back to the origin at $(0, 0)$)) we have used \class{closepath}.  This
directive adds a straight line from the current point to the first
point of the current sub path and furthermore \textit{closes} the sub
path, i.e., it joins the beginning and the end of the line segment.
The difference can be appreciated in Fig.~\ref{fig:rects}, where
also a filled (and at the same time stroked) rectangle is shown.
The corresponding code looks like
\begin{verbatim}
c.stroke(rect1, [deco.filled([color.grey(0.95)])])
\end{verbatim}
The important point to remember here is that when filling a path,
PostScript automatically closes it.  More details on the available
path elements can be found in Sect.~\ref{path:pathel}.

XXX more on styles and attributes and reference to corresponding section

Of course, rectangles are also predefined in \PyX{}, so above we could
have as well written
\begin{verbatim}
rect2 = path.rect(0, 0, 1, 1)
\end{verbatim}
Here, the first two arguments specify the origin of the rectangle
while the second two arguments define its width and height,
respectively. For more details on the predefined paths, we
refer the reader to Sect.~\ref{path:predefined}.

\section{Path operations}

Often, one not only wants to stroke or fill a path on the canvas
but before do some geometrical operations with it. For instance, one
might want to intersect one path with another one and the split the
paths at the intersection points and then join the segments together
in a new way. \PyX{} supports such tasks by means of a number
of path methods, which we will introduce in the following.

Suppose you want to draw the radii to the intersection points of a
circle with a straight line. This task can be done using the following
code which gives the result shown in Fig.~\ref{fig:radii}
\verbatiminput{radii.py}
\begin{figure}
\centerline{\includegraphics{radii}}
%\caption{}
\label{fig:radii}
\end{figure}
Passing another path, here \var{line}, to the \method{intersect()} method
of \var{circle}, we obtain a tuple of parameter values of the
intersection points. The first element of the tuple is a list of
parameter values for the path whose \method{intersect()} method we have
called, the second element is the corresponding list for the path
passed as argument to this method. In the present example, we only
need one list of parameter values, namely \var{isects_circle}.
Iterating over the elements of this list, we draw the radii, using the
\method{at()} path method to obtain the point corresponding to the
parameter value.

Another powerful feature of \PyX{} is its ability to split paths at a
given set of parameters. For instance, in order to fill in the
previous example the segment of the circle delimited by the straight
line (cf.\ Fig.~\ref{fig:radii2}), you first have to construct a path
corresponding to the outline of this segment. The following code
snippet does yield this \var{segment}
\begin{verbatim}
arc1, arc2 = circle.split(isects_circle)
arc = arc1.arclen()<arc2.arclen() and arc1 or arc2

isects_line.sort()
line1, line2, line3 = line.split(isects_line)

segment = line2 << arc
\end{verbatim}
\begin{figure}
\centerline{\includegraphics{radii2}}
%\caption{}
\label{fig:radii2}
\end{figure}
Here, we first split the circle using the \method{split()} method passing
the list of parameters obtained above. Since the circle is closed,
this yields two arc segments. We then use the \method{arclen()}, which
returns the arc length of the path, to find the shorter of the two
arcs. Before splitting the line, we have to take into account that
the \method{split()} method only accepts a sorted list of parameters.
Finally, we join the straight line and the arc segment. For
this, we make use of the \verb|<<| operator, which not only adds
the paths (which could be done using \samp{line2 + arc}), but also
joins the last sub path of \var{line2} and the first one of
\var{arc}. Thus, \var{segment} consists of only a single sub path
and filling works as expected.

An important issue when operating on paths is the parametrisation
used. Internally, \PyX{} uses a parametrisation which uses an interval
of length $1$ for each path element of a path. For instance, for a
simple straight line, the possible parameter values range from $0$ to
$1$, corresponding to the first and last point, respectively, of the
line. Appending another straight line, would extend this range to a
maximal value of $2$. You can always query this maximal value using
the \method{range()} method of the \class{path} class.  

However, the situation becomes more complicated if more complex
objects like a circle are involved. Then, one could be tempted to
assume that again the parameter value range from $0$ to $1$, because
the predefined circle consists just of one \class{arc} together with a
\class{closepath} element. However, as a simple \samp{path.circle(0,
  0, 1).range()} will tell, this is not the case: the actual range is
much larger. The reason for this behaviour lies in the internal path
handling of \PyX: Before performing any non-trivial geometrical
operation with a path, it will automatically be converted into an
instance of the \class{normpath} class (see also
Sect.~\ref{path:normpath}). These so generated paths are already
separated in their sub paths and only contain straight lines and
B\'ezier curve segments. Thus, as is easily imaginable, they are much
simpler to deal with.

A unique way of accessing a point on the path is to use the arc length
of the path segment from the first point of the path to the given
point. Thus, all \PyX{} path methods that accept a parameter value
also allow the user to pass an arc length. For instance, 
\begin{verbatim}
from math import pi

pt1 = path.circle(0, 0, 1).at(arclen=pi)
pt2 = path.circle(0, 0, 1).at(arclen=3*pi/2)

c.stroke(path.path(path.moveto(*pt1), path.lineto(*pt2)))
\end{verbatim}
will draw a straight line from a point at angle $180$ degrees (in
radians $\pi$) to another point at angle $270$ degrees (in radians
$3\pi/2$) on the unit circle.

More information on the available path methods can be found 
in Sect.~\ref{path:path}.

\section{Attributes: Styles and Decorations}

XXX to be done