cgal/Kernel_23/doc/Kernel_23/Kernel_23.txt

712 lines
33 KiB
Plaintext

namespace CGAL {
/*!
\mainpage User Manual
\anchor Chapter_2D_and_3D_Geometry_Kernel
\anchor chapterkernel23
\cgalAutoToc
\authors Hervé Brönnimann, Andreas Fabri, Geert-Jan Giezeman, Susan Hert, Michael Hoffmann, Lutz Kettner, Sylvain Pion, and Stefan Schirra
\section kernel_intro Introduction
\cgal, the *Computational Geometry Algorithms Library*, is written in
\cpp and consists of three major parts.
The first part is the kernel, which consists of constant-size non-modifiable
geometric primitive objects and operations on these objects.
The objects are represented both as stand-alone classes that are
parameterized by a representation class, which specifies
the underlying number types used for calculations and as members of the
kernel classes, which allows for more flexibility and adaptability of the
kernel.
The second part is a collection of basic geometric data structures and
algorithms, which are parameterized by traits classes that define the
interface between the data structure or algorithm and the primitives they use.
In many cases, the kernel classes provided in \cgal can be used as traits
classes for these data structures and algorithms.
The third part of the library consists of non-geometric support facilities,
such as circulators, random sources, I/O support for debugging and for
interfacing \cgal to various visualization tools.
This part of the reference manual covers the kernel.
The kernel contains objects of constant size, such as point, vector,
direction, line, ray, segment, triangle, iso-oriented rectangle and
tetrahedron.
With each type comes a set of functions which can be applied to an object
of this type.
You will typically find access functions (e.g. to the coordinates of a point),
tests of the position of a point relative to the object, a function returning
the bounding box, the length, or the area of an object, and so on.
The \cgal kernel further contains basic operations such as affine
transformations, detection and computation of intersections, and distance
computations.
\subsection Kernel_23Robustness Robustness
The correctness proof of nearly all geometric algorithms presented
in theory papers assumes exact computation with real numbers.
This leads to a fundamental problem with the implementation of geometric
algorithms.
Naively, often the exact real arithmetic is replaced by inexact floating-point
arithmetic in the implementation.
This often leads to acceptable results for many input data.
However, even for the implementation of the simplest geometric
algorithms this simplification occasionally does not work.
Rounding errors introduced by an inaccurate arithmetic may lead to
inconsistent decisions, causing unexpected failures for some correct
input data.
There are many approaches to this problem, one of them is to compute
exactly (compute so accurate that all decisions made by the algorithm
are exact) which is possible in many cases but more expensive
than standard floating-point arithmetic.
C. M. Hoffmann \cgalCite{h-gsm-89}, \cgalCite{h-pargc-89} illustrates some
of the problems arising in the implementation of geometric algorithms
and discusses some approaches to solve them.
A more recent overview is given in \cgalCite{s-rpigc-00}.
The exact computation paradigm is discussed by Yap and Dubé
\cgalCite{yd-ecp-95} and Yap \cgalCite{y-tegc-97}.
In \cgal you can choose the underlying number types and arithmetic.
You can use different types of arithmetic simultaneously and the choice can
be easily changed, e.g. for testing.
So you can choose between implementations with fast but occasionally inexact
arithmetic and implementations guaranteeing exact computation and exact
results.
Of course you have to pay for the exactness in terms of execution time
and storage space.
See the dedicated chapter
for more details on number types and their capabilities and performance.
\section kernel_rep Kernel Representations
Our object of study is the \f$ d\f$-dimensional affine Euclidean space.
Here we are mainly concerned with cases \f$ d=2\f$ and \f$ d=3\f$.
Objects in that space are sets of points. A common way to represent
the points is the use of %Cartesian coordinates,
which assumes a reference frame (an origin and \f$ d\f$ orthogonal axes).
In that framework, a point is represented by a \f$ d\f$-tuple
\f$ (c_0,c_1,\ldots,c_{d-1})\f$,
and so are vectors in the underlying linear space. Each point is
represented uniquely by such %Cartesian coordinates.
Another way to represent points is by homogeneous coordinates. In that
framework, a point is represented by a \f$ (d+1)\f$-tuple
\f$ (h_0,h_1,\ldots,h_d)\f$.
Via the formulae \f$ c_i = h_i/h_d\f$,
the corresponding point with %Cartesian coordinates
\f$ (c_0,c_1,\ldots,c_{d-1})\f$
can be computed. Note that homogeneous coordinates are not unique.
For \f$ \lambda\ne 0\f$, the tuples \f$ (h_0,h_1,\ldots,h_d)\f$ and
\f$ (\lambda\cdot h_0,\lambda\cdot h_1,\ldots,\lambda\cdot h_d)\f$
represent the same point.
For a point with %Cartesian coordinates \f$ (c_0,c_1,\ldots,c_{d-1})\f$ a
possible homogeneous representation is \f$ (c_0,c_1,\ldots,c_{d-1},1)\f$.
%Homogeneous coordinates in fact allow to represent
objects in a more general space, the projective space
\f$ \mathbb{P}^d\f$.
In \cgal we do not compute in projective geometry. Rather, we use
homogeneous coordinates to avoid division operations,
since the additional coordinate can serve as a common denominator.
\subsection Kernel_23GenericityThroughParameterization Genericity Through Parameterization
Almost all the kernel objects (and the corresponding functions) are
templates with a parameter that allows the user to choose the
representation of the kernel objects. A type that is used as an
argument for this parameter must fulfill certain requirements on
syntax and semantics. The list of requirements defines an abstract
kernel concept. For all kernel objects types, the types
`CGAL::Type<Kernel>` and
`Kernel::Type` are identical.
\cgal offers four families of concrete models for the concept Kernel,
two based on the %Cartesian representation of
points and two based on the homogeneous representation of points. The
interface of the kernel objects is designed such that it works well
with both %Cartesian and homogeneous
representation. For example, points in 2D have a constructor with
three arguments as well (the three homogeneous coordinates of the
point). The common interfaces parameterized with a kernel class allow
one to develop code independent of the chosen representation. We said
"families" of models, because both families are parameterized too.
A user can choose the number type used to represent the coordinates.
For reasons that will become evident later, a kernel class provides
two typenames for number types, namely `Kernel::FT` and `Kernel::RT`.
The type `Kernel::FT` must fulfill the
requirements on what is called a `FieldNumberType` in \cgal. This
roughly means that `Kernel::FT` is a type for which operations
\f$ +\f$, \f$ -\f$, \f$ *\f$ and \f$ /\f$ are defined with semantics (approximately)
corresponding to those of a field in a mathematical sense. Note that,
strictly speaking, the built-in type `int` does not fulfill the
requirements on a field type, since `int`s correspond to elements
of a ring rather than a field, especially operation \f$ /\f$ is not the
inverse of \f$ *\f$. The requirements on the type `Kernel::RT` are
weaker. This type must fulfill the requirements on what is called a
`RingNumberType` in \cgal. This roughly means that
`Kernel::RT` is a type for which operations \f$ +\f$, \f$ -\f$, \f$ *\f$ are
defined with semantics (approximately) corresponding to those of a
ring in a mathematical sense.
\subsection Kernel_23CartesianKernels Cartesian Kernels
With `Cartesian<FieldNumberType>` you can choose a
%Cartesian representation of coordinates. When you
choose %Cartesian representation you have to
declare at the same time the type of the coordinates. A number type
used with the `Cartesian` representation class should be a
FieldNumberType as described above. As mentioned above, the built-in
type `int` is not a FieldNumberType. However, for some
computations with %Cartesian representation, no
division operation is needed, i.e., a `RingNumberType` is sufficient in
this case. With `Cartesian<FieldNumberType>`, both
\link Cartesian::FT Cartesian<FieldNumberType>::FT\endlink and
\link Cartesian::RT Cartesian<FieldNumberType>::RT\endlink are mapped to
`FieldNumberType`.
`Cartesian<FieldNumberType>` uses reference counting internally to
save copying costs. \cgal also provides
`Simple_cartesian<FieldNumberType>`, a kernel that uses
%Cartesian representation but no reference
counting. Debugging is easier with
`Simple_cartesian<FieldNumberType>`, since the coordinates are
stored within the class and hence direct access to the coordinates is
possible. Depending on the algorithm, it can also be slightly more or
less efficient than `Cartesian<FieldNumberType>`. Again, in
`Simple_cartesian<FieldNumberType>` both
\link Simple_cartesian::FT Simple_cartesian<FieldNumberType>::FT \endlink and
\link Simple_cartesian::RT Simple_cartesian<FieldNumberType>::RT \endlink are mapped to
`FieldNumberType`.
\subsection Kernel_23HomogeneousKernels Homogeneous Kernels
%Homogeneous coordinates permit to avoid division operations in
numerical computations, since the additional coordinate can serve as a
common denominator. Avoiding divisions can be useful for exact
geometric computation. With `Homogeneous<RingNumberType>` you can
choose a homogeneous representation for the coordinates of the kernel
objects. As for the %Cartesian representation, one
has to declare the type used to store the coordinates. Since the
homogeneous representation does not use divisions, the number type
associated with a homogeneous representation class must be a model for
the weaker concept `RingNumberType` only. However, some operations
provided by this kernel involve divisions, for example computing
squared distances or %Cartesian coordinates. To
keep the requirements on the number type parameter of
`Homogeneous` low, the number type
`Quotient<RingNumberType>` is used for operations that require
divisions. This number type can be viewed as an adaptor which turns a
`RingNumberType` into a `FieldNumberType`. It maintains numbers as
quotients, i.e., a numerator and a denominator. With
`Homogeneous<RingNumberType>`,
\link Homogeneous::FT Homogeneous<RingNumberType>::FT \endlink is equal to
`Quotient<RingNumberType>`, while
\link Homogeneous::RT Homogeneous<RingNumberType>::RT\endlink is equal to
`RingNumberType`.
`Homogeneous<RingNumberType>` uses reference counting internally
to save copying costs. \cgal also provides
`Simple_homogeneous<RingNumberType>`, a kernel that uses
homogeneous representation but no reference
counting. Debugging is easier with
`Simple_homogeneous<RingNumberType>`, since the coordinates are
stored within the class and hence direct access to the coordinates is
possible. Depending on the algorithm, it can also be slightly more or
less efficient than `Homogeneous<RingNumberType>`. Again, in
`Simple_homogeneous<RingNumberType>` the type
\link Simple_homogeneous::FT Simple_homogeneous<RingNumberType>::FT \endlink is equal to
`Quotient<RingNumberType>` while
\link Simple_homogeneous::RT Simple_homogeneous<RingNumberType>::RT \endlink is equal to
`RingNumberType`.
\subsection Kernel_23NamingConventions Naming Conventions
The use of kernel classes not only avoids problems, it also makes all
\cgal classes very uniform. They always consist of:
<OL>
<LI>The *capitalized base name* of the geometric object, such as
`Point`, `Segment`, or `Triangle`.
<LI>An *underscore* followed by the *dimension* of the object,
for example \f$ \_2\f$, \f$ \_3\f$, or \f$ \_d\f$.
<LI>A *kernel class* as parameter, which itself is
parameterized with a number type, such as
`Cartesian<double>` or
`Homogeneous<leda_integer>`.
</OL>
\subsection Kernel_23KernelasaTraitsClass Kernel as a Traits Class
Algorithms and data structures in the basic library of \cgal are
parameterized by a traits class that subsumes the objects on which the
algorithm or data structure operates as well as the operations to do
so. For most of the algorithms and data structures in the basic
library you can use a kernel as a traits class. For some algorithms
you even do not have to specify the kernel; it is detected
automatically using the types of the geometric objects passed to the
algorithm. In some other cases, the algorithms or data structures
needs more than is provided by the kernel concept. In these cases, a
kernel can not be used as a traits class.
\subsection Kernel_23ChoosingaKernelandPredefinedKernels Choosing a Kernel and Predefined Kernels
If you start with integral %Cartesian coordinates,
many geometric computations will involve integral numerical values
only. Especially, this is true for geometric computations that
evaluate only predicates, which are tantamount to determinant
computations. Examples are triangulation of point sets and convex hull
computation. In this case, the %Cartesian
representation is probably the first choice, even with a ring type.
You might use limited precision integer types like `int` or
`long`, use `double` to present your integers (they have more
bits in their mantissa than an `int` and overflow nicely), or an
arbitrary precision integer type like the wrapper `Gmpz` for the
GMP integers, `leda_integer`, or `MP_Float`. Note, that unless
you use an arbitrary precision ring type, incorrect results might
arise due to overflow.
If new points are to be constructed, for example the
intersection point of two lines, computation of
%Cartesian coordinates usually involves divisions.
Hence, one needs to use a `FieldNumberType` with
%Cartesian representation, or alternatively, switch
to homogeneous representation. The type `double` is a - though
imprecise - model for `FieldNumberType`. You can also put any
`RingNumberType` into the `Quotient` adaptor to get a field type
which then can be put into `Cartesian`. But using homogeneous
representation on the `RingNumberType` is usually the better option.
Other valid `FieldNumberType`s are `leda_rational` and
`leda_real`.
If it is crucial for you that the computation is reliable, the right
choice is probably a number type that guarantees exact computation.
The `Filtered_kernel` provides a way to apply filtering techniques
\cgalCite{cgal:bbp-iayed-01} to achieve a kernel with exact and efficient
predicates. Still other people will prefer the built-in
type <TT>double</TT>, because they need speed and can live with
approximate results, or even algorithms that, from time to time,
crash or compute incorrect results due to accumulated rounding errors.
\subsubsection Kernel_23PredefinedKernels Predefined Kernels
For the user's convenience, \cgal provides 5 typedefs to generally useful
kernels.
<UL>
<LI>They are all %Cartesian kernels.
<LI>They all support constructions of points from <TT>double</TT> %Cartesian
coordinates.
<LI>All these 5 kernels provide exact geometric predicates.
<LI>They handle geometric constructions differently:
<UL>
<LI>`Exact_predicates_inexact_constructions_kernel`: provides exact
geometric predicates, but geometric constructions may be inexact due to
round-off errors. It is however enough for many \cgal algorithms, and
faster than the kernels with exact constructions below.
<LI>`Exact_predicates_exact_constructions_kernel`: provides exact
geometric constructions, in addition to exact geometric predicates.
<LI>`Exact_predicates_exact_constructions_kernel_with_sqrt`:
same as `Exact_predicates_exact_constructions_kernel`, but the
number type is a model of concept `FieldWithSqrt`.
\cgalFootnote{Currently it requires having either LEDA or CORE installed.}.
<LI>`Exact_predicates_exact_constructions_kernel_with_kth_root`
same as `Exact_predicates_exact_constructions_kernel`, but the
number type is a model of concept `FieldWithKthRoot`.
\cgalFootnote{Currently it requires having either LEDA or CORE installed.}.
<LI>`Exact_predicates_exact_constructions_kernel_with_root_of`:
same as `Exact_predicates_exact_constructions_kernel`, but the
number type is a model of concept `FieldWithRootOf`.
\cgalFootnote{Currently it requires having either LEDA or CORE installed.}.
</UL>
</UL>
\section Kernel_23Kernel Kernel Geometry
\subsection Kernel_23PointsandVectors Points and Vectors
In \cgal we strictly distinguish between points, vectors and directions.
A *point* is a point in the Euclidean space
\f$ \E^d\f$, a *vector* is the difference of two points \f$ p_2\f$, \f$ p_1\f$
and denotes the direction and the distance from \f$ p_1\f$ to \f$ p_2\f$ in the
vector space \f$ \mathbb{R}^d\f$, and a *direction* is a vector where we forget
about its length.
They are different mathematical concepts. For example, they behave
different under affine transformations and an addition of two
points is meaningless in affine geometry. By putting them in different
classes we not only get cleaner code, but also type checking by the
compiler which avoids ambiguous expressions. Hence, it pays twice to
make this distinction.
\cgal defines a symbolic constant \ref ORIGIN of type `Origin`
which denotes the point at the origin. This constant is used in the conversion
between points and vectors. Subtracting it from a point \f$ p\f$ results in the
locus vector of \f$ p\f$.
\code{.cpp}
Cartesian<double>::Point_2 p(1.0, 1.0), q;
Cartesian<double>::Vector_2 v;
v = p - ORIGIN;
q = ORIGIN + v;
assert( p == q );
\endcode
In order to obtain the point corresponding to a vector \f$ v\f$ you simply
have to add \f$ v\f$ to \ref ORIGIN. If you want to determine
the point \f$ q\f$ in the middle between two points \f$ p_1\f$ and \f$ p_2\f$, you can write\cgalFootnote{you might call \cgalFootnoteCode{midpoint(p_1,p_2)} instead.}
\code{.cpp}
q = p_1 + (p_2 - p_1) / 2.0;
\endcode
Note that these constructions do not involve any performance overhead for
the conversion with the currently available representation classes.
\subsection Kernel_23KernelObjects Kernel Objects
Besides points (`Kernel::Point_2`, `Kernel::Point_3`),
vectors (`Kernel::Vector_2`, `Kernel::Vector_3`), and
directions (`Kernel::Direction_2`, `Kernel::Direction_3`),
\cgal provides lines, rays, segments, planes,
triangles, tetrahedra, iso-rectangles, iso-cuboids, circles and spheres.
Lines (`Kernel::Line_2`, `Kernel::Line_3`) in \cgal are oriented. In
two-dimensional space, they induce a partition of the plane
into a positive side and a negative side.
Any two points on a line induce an orientation
of this line.
A ray (`Kernel::Ray_2`, `Kernel::Ray_3`) is semi-infinite interval on a line,
and this line is oriented from the finite endpoint of this interval towards
any other point in this interval. A segment (`Kernel::Segment_2`,
`Kernel::Segment_3`) is a bounded interval on a directed line,
and the endpoints are ordered so that they induce the same direction
as that of the line.
Planes are affine subspaces of dimension two in \f$ \E^3\f$, passing through
three points, or a point and a line, ray, or segment.
\cgal provides a correspondence between any plane in the ambient
space \f$ \E^3\f$ and the embedding of \f$ \E^2\f$ in that space.
Just like lines, planes are oriented and partition space into a positive side
and a negative side.
In \cgal, there are no special classes for half-spaces. Half-spaces in 2D and
3D are supposed to be represented by oriented lines and planes, respectively.
Concerning polygons and polyhedra, the kernel provides triangles,
iso-oriented rectangles, iso-oriented cuboids and tetrahedra.
More complex polygons\cgalFootnote{Any sequence of points can be seen as a (not necessary simple) polygon or polyline. This view is used frequently in the basic library as well.}
and polyhedra or polyhedral surfaces can be obtained
from the basic library (`Polygon_2`, `Polyhedron_3`),
so they are not part of the kernel.
As with any Jordan curves, triangles, iso-oriented rectangles and circles
separate the plane into two regions, one bounded and one unbounded.
\subsection Kernel_23OrientationandRelativePosition Orientation and Relative Position
Geometric objects in \cgal have member functions that test the
position of a point relative to the object. Full dimensional objects
and their boundaries are represented by the same type,
e.g. half-spaces and hyperplanes are not distinguished, neither are balls and
spheres and discs and circles. Such objects split the ambient space into two
full-dimensional parts, a bounded part and an unbounded part
(e.g. circles), or two unbounded parts (e.g. hyperplanes). By default these
objects are oriented, i.e., one of the resulting parts is called the
positive side, the other one is called the negative side. Both of
these may be unbounded.
These objects have a member function `oriented_side()` that
determines whether a test point is on the positive side, the negative
side, or on the oriented boundary. These function returns a value of type
`Oriented_side`.
Those objects that split the space in a bounded and an unbounded part, have
a member function `bounded_side()` with return type
`Bounded_side`.
If an object is lower dimensional, e.g. a triangle in three-dimensional
space or a segment in two-dimensional space, there is only a test whether a
point belongs to the object or not. This member function, which takes a
point as an argument and returns a Boolean value, is called `%has_on()`.
\section Kernel_23Predicates Predicates and Constructions
\subsection Kernel_23Predicates_1 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 `Comparison_result` or an `Orientation`.
We say components, because predicates are implemented both as functions and
function objects (provided by a kernel class).
\cgal provides predicates for the orientation of point
sets (`orientation()`, `left_turn()`, `right_turn()`, `collinear()`,
`coplanar()`), for comparing points according to some given order,
especially for comparing %Cartesian coordinates
(e.g. `lexicographically_xy_smaller()`), in-circle and in-sphere tests,
and predicates to compare distances.
\subsection Kernel_23Constructions Constructions
Functions and function objects that generate objects that are neither
of type `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 (`Kernel::Aff_transformation_2`,
`Kernel::Aff_transformation_3`) 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 `transform(Aff_transformation t)`
which applies the transformation to the object instance.
\cgal also provides a set of functions that detect or compute the
intersection
between objects of the 2D kernel, and many objects in the 3D kernel,
and functions to calculate their
squared distance.
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 `sqrt`
operation.
This has two drawbacks:
<UL>
<LI>The `sqrt` operation can be costly. Even if it is not very costly for
a specific number type and platform, avoiding it is always cheaper.
<LI>There are number types on which no `sqrt` operation is defined,
especially integer types and rationals.
</UL>
\subsection Kernel_23VariantReturnValues Intersections and Variant Return Types
Some functions, for example \link intersection_linear_grp `intersection()`\endlink,
can return different types of objects. To achieve this in a type-safe way \cgal uses
return values of type `std::optional< std::variant< T... > >` where `T...` is a
list of all possible resulting geometric objects. The exact result type of an intersection
can be specified through the placeholder type specifier `auto`.
Example
-------
In the following example, `auto` is used to specify the type of the return value
for the intersection computation:
\code{.cpp}
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;
/* use auto */
auto v = intersection(segment_1, segment_2);
if (v) {
/* not empty */
if (const Point_2 *p = std::get_if<Point_2>(&*v) ) {
/* do something with *p */
} else {
const Segment_2 *s = std::get_if<Segment_2>(&*v);
/* do something with *s */
}
} else {
/* empty intersection */
}
\endcode
\subsection Kernel_23ConstructivePredicates 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
`Kernel::Plane_3(q,r,s)` and use the method `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
`oriented_side(p)` to return an orientation
which is different from the real 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
`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 `oriented_side(p)`.
\section sectionextensiblekernel Extensible Kernel
This manual section describe how users can plug user defined
geometric classes in existing \cgal kernels. This is best
illustrated by an example.
\subsection Kernel_23Introduction Introduction
\cgal defines the concept of a geometry kernel. Such a kernel provides types,
construction objects and generalized predicates. Most implementations
of Computational Geometry algorithms and data structures in the basic
library of \cgal were done in a way that classes or functions can be
parametrized with a geometric traits class.
In most cases this geometric traits class must be a model of the \cgal geometry
kernel concept (but there are some exceptions).
\subsection Kernel_23AnExtensiveExample An Extensive Example
Assume we have the following point class, where the coordinates are
stored in an array of `doubles`, where we have another data member
`color`, which shows up in the constructor.
\cgalExample{Kernel_23/MyPointC2.h}
As said earlier the class is pretty minimalistic, for
example it has no `bbox()` method. One
might assume that a basic library algorithm which computes
a bounding box (e.g, to compute the bounding box of a polygon),
will not compile. Luckily it will, because it does not
use of member functions of geometric objects, but it makes
use of the functor `Kernel::Construct_bbox_2`.
To make the right thing happen with `MyPointC2` we
have to provide the following functor.
\cgalExample{Kernel_23/MyConstruct_bbox_2.h}
Things are similar for random access to the %Cartesian
coordinates of a point. As the coordinates are stored
in an array of `doubles` we can use `double*` as
random access iterator.
\cgalExample{Kernel_23/MyConstruct_coord_iterator.h}
The last functor we have to provide is the one which constructs
points. That is you are not forced to add the constructor
with the `Origin` as parameter to your class, nor the constructor with
homogeneous coordinates.
The functor is a kind of glue layer between the \cgal algorithms
and your class.
\cgalExample{Kernel_23/MyConstruct_point_2.h}
Now we are ready to put the puzzle together. We won't explain it in
detail, but you see that there are `typedefs` to the new point
class and the functors. All the other types are inherited.
\cgalExample{Kernel_23/MyKernel.h}
Finally, we give an example how this new kernel can be used.
Predicates and constructions work with the new point, they
can be a used to construct segments and triangles with, and
data structures from the Basic Library, as the Delaunay
triangulation work with them.
The kernel itself can be
made robust by plugging it in the `Filtered_kernel`.
\cgalExample{Kernel_23/MyKernel.cpp}
\subsection Kernel_23Limitations Limitations
The point class must have member functions `x()` and `y()`
(and `z()` for the 3d point). We will probably
introduce function objects that take care of coordinate
access.
As we enforce type equality between `MyKernel::Point_2` and `Point_2<MyKernel>`,
the constructor with the color as third argument is not available.
\section sectionprojectiontraits Projection Traits Classes
It is sometimes useful to apply 2D algorithms to the projection of 3D points on
a plane. Examples are
triangulated terrains, which are points with elevation, or surface
reconstruction from parallel slices, where one wants to check the simplicity
or orientation of polygons.
For this purpose \cgal provides several projection traits classes,
which are a model of traits class concepts of 2D triangulations,
2D polygon and 2D convex hull traits classes. The projection traits classes
are listed in the "Is Model Of" sections of the concepts.
\section Kernel_23Design Design and Implementation History
At a meeting at Utrecht University in January 1995,
Olivier Devillers, Andreas Fabri, Wolfgang Freiseisen,
Geert-Jan Giezeman, Mark Overmars, Stefan Schirra, Otfried Schwarzkopf
(now Otfried Cheong), and Sven Sch&ouml;nherr
discussed the foundations of the \cgal kernel.
Many design and software engineering issues were addressed,
e.g. naming conventions, coupling of classes
(flat versus deep class hierarchy),
memory allocation, programming conventions, mutability of
atomic objects, points and vectors, storing additional information,
orthogonality of operations on the kernel objects,
viewing non-constant-size objects like polygons as
dynamic data structures (and hence not as part of the (innermost) kernel).
The people attending the meeting delegated the compilation of
a draft specification to Stefan Schirra.
The resulting draft specification was intentionally modeled on \cgal's
precursors \protocgal and \plageo as well as on the geometric part of \leda.
The specification already featured coexistence of
%Cartesian and
homogeneous representation of point/vector data and parameterization
by number type(s).
During the discussion of the draft a kernel design group was formed.
The members of this group were Andreas Fabri, Geert-Jan Giezeman,
Lutz Kettner, Stefan Schirra, and Sven Sch&ouml;nherr.
The work of the kernel design group led to significant changes and
improvements of the original design, e.g. the strong separation between
points and vectors. Probably the most important enhancement was the design
of a common superstructure for the previously uncoupled
%Cartesian and
homogeneous representations. One can say, that the kernel was designed
by this group.
The kernel was later revised based on suggestions by Herv&eacute; Br&ouml;nnimann,
Bernd G&auml;rtner, Michael Hoffmann, and Lutz Kettner.
A first version of the kernel was internally made available at the beginning
of the \cgal-project (<span class="textsc">esprit ltr iv</span> project number 21957).
Since then many more people contributed to the evolution of the kernel
through discussions on the \cgal mailing lists.
The implementation based on
%Cartesian representation was (initially) provided
by Andreas Fabri, the homogeneous representation (initially) by Stefan Schirra.
Intersection and distance computations were implemented by Geert-Jan Giezeman.
Further work has been done by Susan Hert on the overall maintenance of the
kernel.
Philippe Guigue has provided efficient intersection tests for 3D triangles.
Andreas Fabri, Michael Hoffmann and Sylvain Pion have improved the support for
the extensibility and adaptability of the kernel. Pedro Machado
Manh&atilde;es de Castro and Monique Teillaud introduced 3D circles. In 2010,
Pierre Alliez, St&eacute;phane Tayeb and Camille Wormser added intersection constructions
for 3D triangles and efficient intersection tests for bounding boxes.
\subsection Kernel_23Acknowledgment Acknowledgment
This work was supported
by the Graduiertenkolleg 'Algorithmische Diskrete Mathematik',
under grant DFG We 1265/2-1,
and by ESPRIT IV Long Term Research Projects No. 21957 (\cgal)
and No. 28155 (GALIA).
*/
} /* namespace CGAL */