mirror of https://github.com/CGAL/cgal
316 lines
14 KiB
TeX
316 lines
14 KiB
TeX
% =============================================================================
|
|
% The CGAL Developers' Manual
|
|
% Chapter: Geometry Kernels
|
|
% -----------------------------------------------------------------------------
|
|
% file : kernels.tex
|
|
% authors: Stefan Schirra <stschirr@mpi-sb.mpg.de>
|
|
% -----------------------------------------------------------------------------
|
|
% $Revision$
|
|
% $Date$
|
|
% =============================================================================
|
|
|
|
\chapter{Geometry Kernels} \label{chap:kernels}
|
|
\ccChapterAuthor{Stefan Schirra ({\tt stschirr@mpi-sb.mpg.de})}
|
|
|
|
|
|
The layer of geometry kernels\ccIndexMainItem[t]{kernel}
|
|
provides basic geometric objects
|
|
and primitive operations on them.
|
|
It contains constant size\footnote{In dimension $d$, an object of
|
|
size $O(d)$ is considered to be of constant size.} geometric objects
|
|
and operations on these objects.
|
|
Each object is provided as both a stand-alone class, which is parameterized
|
|
by a kernel class, and as a type in the kernel class. Each operation and
|
|
construction in the kernel is provided via a function object class in the
|
|
\ccIndexMainItem[t]{function objects}
|
|
kernel class and also as either a member function or a global function.
|
|
See~\cite{hhkps-aegk-01} for more details about this design.
|
|
\ccIndexMainItemDef[t]{kernel traits}%
|
|
\ccIndexSubitem{traits class}{kernel as a}%
|
|
Ideally, if the kernel traits provide all the primitives required,
|
|
you can use a kernel as a traits class directly with your algorithm or
|
|
data structure; see also Chapter~\ref{chap:traits_classes}.
|
|
If you need primitives not provided by the kernel yet, please
|
|
read Section~\ref{sec:NewKernelTraits} below.
|
|
|
|
\section{Cartesian and homogeneous representation}
|
|
\label{sec:cart_and_hom_representation}
|
|
|
|
There are two different coordinate representations%
|
|
\ccIndexMainItem[t]{coordinate}%
|
|
\ccIndexMainItem[t]{representation}
|
|
available in the
|
|
kernel at present: Cartesian representation and homogeneous
|
|
representation. Cartesian representation%
|
|
\ccIndexSubitemDef{Cartesian}{representation}%
|
|
\ccIndexSubitemDef{coordinate}{Cartesian}%
|
|
\ccIndexSubitem{representation}{Cartesian}%
|
|
\ccIndexSubitem{kernel traits}{Cartesian}
|
|
is the one you are familiar with.
|
|
A \ccAnchor{http://www.geom.umn.edu/docs/reference/CRC-formulas/node4.html}{point in the plane} is given by its $x$- and its $y$-coordinates;%
|
|
\lcTex{\footnote{%
|
|
\path|http://www.geom.umn.edu/docs/reference/CRC-formulas/node4.html|}}
|
|
a \ccAnchor{http://www.geom.umn.edu/docs/reference/CRC-formulas/node39.html}{point in space} by its $x$-, $y$- and $z$-coordinates.\lcTex{\footnote{%
|
|
\path|http://www.geom.umn.edu/docs/reference/CRC-formulas/node39.html|}}
|
|
Homogeneous representation
|
|
\ccIndexSubitemDef{homogeneous}{representation}%
|
|
\ccIndexSubitemDef{coordinate}{homogeneous}%
|
|
\ccIndexSubitem{representation}{homogeneous}%
|
|
\ccIndexSubitem{kernel traits}{homogeneous}
|
|
can be seen as a divison-free representation
|
|
of Cartesian coordinates. There is an additional coordinate, sometimes called
|
|
the {\em homogenizing} coordinate.%
|
|
\ccIndexMainItemDef{homogenizing coordinate}
|
|
So with homogeneous representation in
|
|
2-space\lcTex{\footnote{%
|
|
\path|http://www.geom.umn.edu/docs/reference/CRC-formulas/node6.html|}},
|
|
we have \ccAnchor{http://www.geom.umn.edu/docs/reference/CRC-formulas/node6.html}{coordinates $(x,y,w)$}, where $w$ is the homogenizing coordinate,
|
|
and in 3-space\lcTex{\footnote{%
|
|
\path|http://www.geom.umn.edu/docs/reference/CRC-formulas/node43.html|}},
|
|
we have homogeneous \ccAnchor{http://www.geom.umn.edu/docs/reference/CRC-formulas/node43.html}{coordinates $(x,y,z,w)$}.
|
|
Since \cgal\ uses homogeneous representation for affine geometry (not for
|
|
projective geometry), we assume $w \neq 0$.
|
|
The Cartesian representation corresponding to $(x_0, x_1, \ldots, x_d, w)$
|
|
is $(x_0/w, x_1/w, \ldots, x_d/w)$. Hence, homogeneous representation
|
|
is not unique; $(\alpha x,\alpha y,\alpha z,\alpha w)$ is an alternative
|
|
representation to $(x,y,z,w)$ for any $\alpha \neq 0$.
|
|
Internally, \cgal\ always maintains a non-negative homogenizing coordinate.
|
|
|
|
With the homogeneous representation, division operations%
|
|
\ccIndexMainItem{division} can be avoided.
|
|
Homogeneous representation is advantageous over Cartesian representation
|
|
whenever systems of linear equations with integral coefficients
|
|
are to be solved. By Cramer's rule,
|
|
the rational solutions%
|
|
\ccIndexMainItem{rational computation} all have the same denominator $D$.
|
|
The Cartesian representation would be
|
|
$$(N_0/D, N_1/D, \ldots, N_{d-1}/D)$$
|
|
while a corresponding less space-consuming homogeneous representation is
|
|
$$(N_0, N_1, \ldots, N_{d-1}, D)$$
|
|
For example, computing the Cartesian coordinates $(x,y)$ of the
|
|
intersection point of lines with equations
|
|
$a_1 X + b_1 Y + c_1 = 0$ and $a_2 X + b_2 Y + c_2 = 0$ gives
|
|
\lcTex{
|
|
$$ (x,y) =
|
|
\Bigg(
|
|
\frac{\left|\begin{array}{cc}b_1& c_1 \\ b_2 & c_2\end{array}\right|}
|
|
{\left|\begin{array}{cc}a_1& b_1 \\ a_2 & b_2\end{array}\right|},
|
|
\frac{-\left|\begin{array}{cc}a_1& c_1 \\ a_2 & c_2\end{array}\right|}
|
|
{\phantom{-}\left|\begin{array}{cc}a_1& b_1 \\ a_2 & b_2\end{array}\right|}
|
|
\Bigg)
|
|
$$
|
|
}
|
|
\lcRawHtml{
|
|
<CENTER>
|
|
<IMG BORDER=0 SRC="images/Cartesian_ipoint.gif" ALIGN=CENTER ALT="Intersection point with Cartesian coordinates"><BR>
|
|
</CENTER>
|
|
}
|
|
while with homogeneous representation we have
|
|
\lcTex{
|
|
$$ (x,y,w) =
|
|
\Bigg(
|
|
{\left|\begin{array}{cc}b_1& c_1 \\ b_2 & c_2\end{array}\right|},
|
|
{-\left|\begin{array}{cc}a_1& c_1 \\ a_2 & c_2\end{array}\right|},
|
|
{\left|\begin{array}{cc}a_1& b_1 \\ a_2 & b_2\end{array}\right|}\Bigg)
|
|
$$
|
|
}
|
|
\lcRawHtml{
|
|
<CENTER>
|
|
<IMG BORDER=0 SRC="images/homogeneous_ipoint.gif" ALIGN=CENTER ALT="Intersection point with homogeneous coordinates"><BR>
|
|
</CENTER>
|
|
}
|
|
In general, however, homogeneous representation is not more space-efficient.
|
|
Naive conversion from a rational Cartesian represenatation
|
|
$$(N_0/D_0, N_1/D_1, \ldots, N_{d-1}/D_{d-1})$$ to a homogeneous
|
|
representation will lead to much bigger numbers, namely,
|
|
$$\textstyle
|
|
(N_0 \prod D_i /D_0, N_1\prod D_i /D_1, \ldots, N_{d-1}\prod D_i /D_{d-1},
|
|
\prod D_i )$$.
|
|
|
|
\section{Cartesian versus homogeneous computation}
|
|
\label{sec:CartesianHomogeneousComputation}
|
|
Homogeneous representation has the disadvantage that predicates become
|
|
more complicated. Testing equality of points is more complicated because
|
|
the homogeneous representation is not unique. In the orientation predicate,
|
|
the sign of a 3x3 determinant must be computed:
|
|
\lcTex{
|
|
$${\mbox{\small sign}}\left|
|
|
\begin{array}{ccc}
|
|
{x_1} & {y_1} & w_1 \\
|
|
{x_2} & {y_2} & w_2 \\
|
|
{x_3} & {y_3} & w_3 \\
|
|
\end{array}
|
|
\right|
|
|
$$
|
|
}
|
|
\lcRawHtml{
|
|
<CENTER>
|
|
<IMG BORDER=0 SRC="images/homogeneous_orientation.gif" ALIGN=CENTER ALT="Orientation test with homogeneous coordinates"><BR>
|
|
</CENTER>
|
|
}
|
|
With Cartesian representation, it is essentially a 2x2 determinant only:
|
|
\lcTex{
|
|
$$
|
|
{\mbox{\small sign}}\left|
|
|
\begin{array}{ccc}
|
|
{x_1} & {y_1} & 1 \\
|
|
{x_2} & {y_2} & 1 \\
|
|
{x_3} & {y_3} & 1 \\
|
|
\end{array}
|
|
\right| =
|
|
{\mbox{\small sign}}\left|
|
|
\begin{array}{ccc}
|
|
{x_1 - x_3} & {y_1 - y_3} & 0 \\
|
|
{x_2 - x_3} & {y_2 - y_3} & 0 \\
|
|
{x_3} & {y_3} & 1 \\
|
|
\end{array}
|
|
\right|
|
|
$$
|
|
}
|
|
\lcRawHtml{
|
|
<CENTER>
|
|
<IMG BORDER=0 SRC="images/Cartesian_orientation.gif" ALIGN=CENTER ALT="Orientation test with Cartesian coordinates"><BR>
|
|
</CENTER>
|
|
}
|
|
With homogeneous coordinates all formulas are homogeneous polynomials
|
|
\ccIndexSubitem{homogeneous}{polynomial}
|
|
in the coordinates, \ie, all monomials of homogeneous coordinates
|
|
have the same total degree.%
|
|
\footnote{the sum of the degrees of each variable in the monomial}
|
|
\ccIndexMainItem{total degree}%
|
|
For a sign test for some polynomial expression over Cartesian coordinates
|
|
you get a corresponding sign test with an expression over homogeneous
|
|
coordinates by replacing
|
|
each Cartesian coordinate $x_{ij}$ by $hx_{ij}/hw_j$ and then multiplying by
|
|
the least common multiple of the denominators, \ie, some multiple of
|
|
the $hw_j$.
|
|
Here, $x_{ij}$ denotes the $i$-th Cartesian coordinate,
|
|
$hx_{ij}$ denotes the $i$-th homogeneous coordinate, and
|
|
$hw_j$ denotes the homogenizing coordinate of point $j$.
|
|
Since all $hw_j$ are positive in \cgal, sign is not affected
|
|
by this multiplication.
|
|
|
|
\section{Available kernels}
|
|
At present, there are two homogeneous and two Cartesian kernels,
|
|
one with reference counting\ccIndexMainItem{reference counting}
|
|
(Chapter~\ref{chap:reference_counting}) and one without.
|
|
The corresponding kernel classes are
|
|
\begin{verbatim}
|
|
CGAL::Cartesian< NumberType >
|
|
CGAL::Homogeneous< NumberType >
|
|
CGAL::Simple_cartesian< NumberType >
|
|
CGAL::Simple_homogeneous< NumberType >
|
|
\end{verbatim}
|
|
\ccIndexMainItem{kernel traits}
|
|
\ccIndexSubitem{kernel}{\ccFont Cartesian}%
|
|
\ccIndexSubitem{kernel}{\ccFont Homogeneous}%
|
|
\ccIndexSubitem{kernel}{\ccFont Simple_cartesian}%
|
|
\ccIndexSubitem{kernel}{\ccFont Simple_homogeneous}%
|
|
These are all parameterized by a number type, which is used for storing
|
|
the coordinates and the arithmetic in the corresponding primitives and
|
|
predicates (unless the latter are specialised for using floating-point
|
|
filter techniques). Actually, parameterization of \ccc{Homogeneous<>}
|
|
involves two number types. While in the internal homogeneous representation,
|
|
an integral number type is sufficient, rational numbers must sometimes be
|
|
used outside the internal representation, for example, when the squared length
|
|
of a vector is computed. To represent such rational values, there is a second
|
|
number type whose default value is {\tt CGAL::Quotient< NumberType >}.
|
|
The type of this number type can be accessed as \ccc{Homogeneous<>::FT}.%
|
|
\ccIndexMainItem{\ccFont FT}
|
|
\ccIndexSubitem{kernel}{\ccFont FT}
|
|
The internally used number type can be accessed as \ccc{Homogeneous<>::RT}.%
|
|
\ccIndexMainItem{\ccFont RT}
|
|
\ccIndexSubitem{kernel}{\ccFont RT}
|
|
For the sake of a uniform interface for both representations, the
|
|
Cartesian kernels provide such types as well. For Cartesian representation,
|
|
both \ccc{FT} and \ccc{RT} map to same number type used everywhere in the
|
|
implementation of the Cartesian kernel.
|
|
|
|
\section{Kernel design and conventions}
|
|
\ccIndexSubitem{kernel}{design}%
|
|
\ccIndexSubitem{design}{kernel}%
|
|
Each kernel object is provided as both a stand-alone class, which is
|
|
parameterized by a kernel class (\ccc{Geo_object_D<K>}), and as a type
|
|
in the kernel class (\ccc{K::Geo_object_D}). While the former use may
|
|
be more natural for users not interested in the flexibility of the kernel
|
|
(and is compatable with the original kernel design \cite{Fabri98}), the
|
|
latter syntax should be used in all code distributed with the library
|
|
as it allows types in the kernel to be easily exchanged and modified.
|
|
Similarly, each operation and construction in the kernel is provided via
|
|
a function object class in the \ccIndexMainItem[t]{function objects}
|
|
kernel class and also as either a member function or a global function;
|
|
developers should use the function object classes to gain access to the
|
|
functionality. See~\cite{hhkps-aegk-01} for more details about this
|
|
design and how it is accomplished.
|
|
|
|
The classes for the geometric objects in the kernel have a
|
|
standardized interface.%
|
|
\ccIndexSubitem{kernel}{conventions}
|
|
\begin{itemize}
|
|
\item
|
|
All classes have a \ccc{bbox()} member function computing a bounding box.%
|
|
\ccIndexMainItem[C]{bbox}
|
|
\item
|
|
All classes have a \ccc{transform(Aff_transformation_d t)} member function
|
|
to compute the object transformed by \ccc{t}.%
|
|
\ccIndexMainItem[C]{transform}
|
|
\item
|
|
Oriented $d-1$ dimensional objects\footnote{Note that the dimension
|
|
of an object might depend on its use. A line in the plane has dimension
|
|
$d-1$. As a halfspace, it has dimension $d$.} provide member functions
|
|
\ccc{has_on_positive_side(Point_d)}%
|
|
\ccIndexMainItem[C]{has_on_positive_side}, \ccc{has_on_boundary(Point_d)}%
|
|
\ccIndexMainItem[C]{has_on_boundary},
|
|
and \ccc{has_on_negative_side(Point_d)}%
|
|
\ccIndexMainItem[C]{has_on_negative_side}. Furthermore, there is a member
|
|
function \ccc{oriented_side(Point_d)}%
|
|
\ccIndexMainItem[C]{oriented_side} returning an object of type
|
|
\ccc{CGAL::Oriented_side}.\ccIndexMainItem[C]{Oriented_side}
|
|
\item
|
|
Full-dimensional bounded objects provide member functions
|
|
\ccc{has_on_bounded_side(Point_d)}%
|
|
\ccIndexMainItem[C]{has_on_bounded_side}, \ccc{has_on_boundary(Point_d)}%
|
|
\ccIndexMainItem[C]{has_on_boundary},
|
|
and \ccc{has_on_unbounded_side(Point_d)}%
|
|
\ccIndexMainItem[C]{has_on_unbounded_side}. Furthermore, there is a member
|
|
function \ccc{bounded_side(Point_d)}%
|
|
\ccIndexMainItem[C]{bounded_side} returning an object of type
|
|
\ccc{CGAL::Bounded_side}.\ccIndexMainItem[C]{Bounded_side}
|
|
\item
|
|
Oriented objects have a member function \ccc{opposite()}%
|
|
\ccIndexMainItem[C]{opposite} returning
|
|
the same object with opposite orientation.
|
|
\end{itemize}
|
|
|
|
|
|
\section{Number-type based predicates}
|
|
\ccIndexSubitem{predicate}{number-type based}
|
|
For a number of predicates, there are versions that operate on
|
|
the coordinates directly, not on the geometric objects. These
|
|
number-type based predicates ease re-use with non-\cgal\ types.
|
|
|
|
\section{Missing functionality}
|
|
\label{sec:NewKernelTraits}
|
|
\ccIndexSubitem{predicate}{missing}
|
|
Kernel traits don't provide redundant functionality. In particular,
|
|
they don't provide a right turn predicate, since a left turn predicate
|
|
exists. Some adapters, in particular \ccc{Rightturn_by_leftturn},%
|
|
\ccIndexMainItem[C]{Rightturn_by_leftturn}
|
|
are available in the file
|
|
\ccc{CGAL/Kernel/traits_aids.h}.
|
|
|
|
Whenever you need a predicate that is not present in the current kernel
|
|
traits, you should first try to re-use the available predicates (you
|
|
might rewrite the code or implement the new predicate using existing ones).
|
|
If this is not feasible (especially for efficiency reasons), we have to
|
|
decide on adding the new predicate to the kernel traits.
|
|
If the new predicate is not too special, it will be added.
|
|
Otherwise you cannot use the kernel as a traits class, but have
|
|
to use additional traits.%
|
|
\ccIndexSubitem{traits class}{additional}
|
|
|
|
See Section \ref{sec:CartesianHomogeneousComputation} on how to derive the
|
|
homogeneous version of a predicate from the Cartesian version.
|
|
|
|
|