cgal/Kernel_23/doc_tex/Kernel_23/predicates_constructions.tex

131 lines
5.9 KiB
TeX

\section{Predicates and Constructions}
\subsection{Predicates}
Predicates are at the heart of a geometry kernel. They are basic units
for the composition of geometric algorithms and encapsulate decisions.
Hence their correctness is crucial for the control flow and hence for
the correctness of an implementation of a geometric algorithm. \cgal\ uses
the term predicate in a generalized sense. Not only components returning a
Boolean value are called predicates but also components returning an
enumeration type like a \ccc{Comparison_result} or an \ccc{Orientation}.
We say components, because predicates are implemented both as functions and
function objects (provided by a kernel class).
\cgal\ provides predicates for the \ccHtmlNoLinksFrom{orientation} of point
sets (\ccc{orientation}, \ccc{leftturn}, \ccc{rightturn}, \ccc{collinear},
\ccc{coplanar}), for comparing points according to some given order,
especially for comparing \ccHtmlNoLinksFrom{Cartesian} coordinates
(e.g.~\ccc{lexicographically_xy_smaller}), in-circle and in-sphere tests,
and predicates to compare distances.
\subsection{Constructions}
Functions and function objects that generate objects that are neither
of type \ccc{bool} nor enum types are called constructions.
Constructions involve computation of new numerical values and may be
imprecise due to rounding errors unless a kernel with an exact number type is
used.
Affine transformations (\ccc{Aff_transformation_2<Kernel>},
\ccc{Aff_transformation_3<Kernel>}) allow to generate new object instances under
arbitrary affine transformations. These transformations include translations,
rotations (in 2D only) and scaling. Most of the geometric objects in a
kernel have a member function \ccc{transform(Aff_transformation t)}
which applies the transformation to the object instance.
{\cgal} also provides a set of functions that detect or compute the
\ccHtmlNoLinksFrom{intersection}\ccIndexMainItem{intersection}
between objects of the 2D kernel, and many objects in the 3D kernel,
and functions to calculate their
squared distance\ccIndexMainItem{distance}\ccIndexSubitem{distance}{squared}.
Moreover, some member functions of kernel objects are constructions.
So there are routines that compute the square of the Euclidean distance, but no
routines that compute the distance itself. Why?
First of all, the two values can be derived from each other quite easily (by
taking the square root or taking the square). So, supplying only the one and
not the other is only a minor inconvenience for the user.
Second, often either value can be used. This is for example the case when
(squared) distances are compared.
Third, the library wants to stimulate the use of the squared distance instead
of the distance. The squared distance can be computed in more cases and the
computation is cheaper.
We do this by not providing the perhaps more natural routine,
The problem of a distance routine is that it needs the \ccStyle{sqrt}
operation.
This has two drawbacks:
\begin{itemize}
\item
The \ccStyle{sqrt} operation can be costly. Even if it is not very costly for
a specific number type and platform, avoiding it is always cheaper.
\item
There are number types on which no \ccStyle{sqrt} operation is defined,
especially integer types and rationals.
\end{itemize}
\subsection{Intersections and variant return types}
Some functions can return different types of objects. To achieve this
in a type safe way {\cgal} uses return values of type
\ccStyle{boost::optional< boost::variant< T \ldots\ > >} were T... is a
list of all possible resulting geometric objects. The exact result
type of an intersection can be determined through the metafunction
\ccc{cpp11::result_of<Kernel::Intersect_2(Type1, Type2)>} or
\ccc{cpp11::result_of<Kernel::Intersect_3(Type1, Type2)>}, where
\ccc{Type1} and \ccc{Type2} are the types of the objects used in the
intersection computation. See
\ccAnchor{http://www.boost.org/libs/utility/utility.htm#result_of}{boost::result\_of}
for more information about this mechanism.
\ccExample
In the following example, \ccc{result_of} is used to query the return
value for the \ccHtmlNoLinksFrom{intersection} computation:
\ccHtmlLinksOff%
\begin{cprog}
typedef Cartesian<double> K;
typedef K::Point_2 Point_2;
typedef K::Segment_2 Segment_2;
Segment_2 segment_1, segment_2;
std::cin >> segment_1 >> segment_2;
/* C++11 */
auto v = intersection(segment_1, segment_2);
/* C++03 */
/*cpp11::result_of<K::Intersect_2(Segment_2, Segment_2)>::type */
/* v = intersection(segment_1, segment_2); */
if(v) {
/* not empty */
if (const Point_2 *p = boost::get<Point_2>(&*v) ) {
/* do something with *p */
} else if (const Segment_2 *s = boost::get<Segment_2>(&*v) ) {
/* do something with *s */
}
} else {
/* empty intersection */
}
\end{cprog}
\ccHtmlLinksOn%
\subsection{Constructive Predicates}
For testing where a point $p$ lies with respect to a plane defined by three
points $q$, $r$ and $s$, one may be tempted to construct the plane
\ccc{Plane_3<Kernel>(q,r,s)} and use the method \ccc{oriented_side(p)}.
This may pay off if many tests with respect to the plane are made.
Nevertheless, unless the number type is exact, the constructed plane
is only approximated, and round-off errors may lead
\ccc{oriented_side(p)} to return an \ccHtmlNoLinksFrom{orientation}
which is different from the \ccHtmlNoLinksFrom{orientation} of $p$, $q$, $r$,
and $s$.
In {\cgal}, we provide predicates in which such
geometric decisions are made directly with a reference to the input points
$p$, $q$, $r$, $s$, without an intermediary object like a plane.
For the above test, the recommended way to get the result is to use
\ccc{orientation(p,q,r,s)}. For exact number types, the situation is different.
If several tests are to be made with the same
plane, it pays off to construct the plane and to use \ccc{oriented_side(p)}.