mirror of https://github.com/CGAL/cgal
344 lines
13 KiB
Plaintext
344 lines
13 KiB
Plaintext
namespace CGAL {
|
|
/*!
|
|
\example Convex_hull_2/array_convex_hull_2.cpp
|
|
\example Convex_hull_2/vector_convex_hull_2.cpp
|
|
\example Convex_hull_2/iostream_convex_hull_2.cpp
|
|
\example Convex_hull_2/convex_hull_yz.cpp
|
|
\example Kernel_23/points_and_segment.cpp
|
|
\example Kernel_23/surprising.cpp
|
|
\example Kernel_23/exact.cpp
|
|
*/
|
|
|
|
/*!
|
|
|
|
\page introduction Hello World
|
|
\cgalAutoToc
|
|
\author %CGAL Editorial Board
|
|
|
|
This chapter is for the %CGAL newbie, who knows C++ and has
|
|
a basic knowledge of geometric algorithms. The first section
|
|
shows how to define a point and segment class, and how to
|
|
apply geometric predicates on them. The section further raises
|
|
the awareness that that there are serious issues when using
|
|
floating point numbers for coordinates. In the second section
|
|
you see how the 2D convex hull function gets its input
|
|
and where it puts the result. The third section shows what
|
|
we mean with a \em Traits class, and the fourth section explains
|
|
the notion of \em concept and \em model.
|
|
|
|
\section intro_Three Three Points and One Segment
|
|
|
|
In this first example we see how to construct some points
|
|
and a segment, and we perform some basic operations on them.
|
|
|
|
All \cgal header files are in the subdirectory `include/CGAL`. All \cgal
|
|
classes and functions are in the namespace `CGAL`.
|
|
Classes start with a capital letter, global
|
|
function with a lowercase letter, and constants are all uppercase.
|
|
The dimension of an object is expressed with a suffix.
|
|
|
|
The geometric primitives, like the point type, are defined in a \em kernel.
|
|
The kernel we have chosen for this first example uses `double`
|
|
precision floating point numbers for the %Cartesian coordinates of the point.
|
|
|
|
Besides the types we see \em predicates like the orientation test for
|
|
three points, and \em constructions like the distance and midpoint
|
|
computation. A predicate has a discrete set of possible results,
|
|
whereas a construction produces either a number, or another
|
|
geometric entity.
|
|
|
|
|
|
|
|
\cgalExample{Kernel_23/points_and_segment.cpp}
|
|
|
|
|
|
|
|
To do geometry with floating point numbers can be surprising
|
|
as the next example shows.
|
|
|
|
\cgalExample{Kernel_23/surprising.cpp}
|
|
|
|
When reading the code, we would assume that it prints three times "collinear".
|
|
However we obtain:
|
|
|
|
\verbatim
|
|
not collinear
|
|
not collinear
|
|
collinear
|
|
\endverbatim
|
|
|
|
|
|
As the fractions are not representable as double precision number
|
|
the collinearity test will internally compute a determinant of a 3x3 matrix
|
|
which is close but not equal to zero, and hence the non collinearity for the
|
|
first two tests.
|
|
|
|
Something similar can happen with points that perform a left turn,
|
|
but due to rounding errors during the determinant computation, it
|
|
seems that the points are collinear, or perform a right turn.
|
|
|
|
If you need that the numbers get interpreted at their full precision
|
|
you can use a \cgal kernel that performs exact predicates and
|
|
extract constructions.
|
|
|
|
\cgalExample{Kernel_23/exact.cpp}
|
|
|
|
Here comes the output and you may still be surprised.
|
|
|
|
\verbatim
|
|
not collinear
|
|
collinear
|
|
collinear
|
|
\endverbatim
|
|
|
|
In the first block the points are still not collinear,
|
|
for the simple reason that the coordinates you see as text
|
|
get turned into floating point numbers. When they are then
|
|
turned into arbitrary precision rationals, they exactly
|
|
represent the floating point number, but not the text.
|
|
|
|
This is different in the second block, which corresponds
|
|
to reading numbers from a file. The arbitrary precision
|
|
rationals are then directly constructed from a string
|
|
so that they represent exactly the text.
|
|
|
|
In the third block you see that constructions as
|
|
midpoint constructions are exact, just as the name
|
|
of the kernel type suggests.
|
|
|
|
|
|
In many cases you will have floating point numbers that are "exact",
|
|
in the sense that they were computed by some application or obtained
|
|
from a sensor. They are not the string "0.1" or computed on the
|
|
fly as "1.0/10.0", but a full precision floating point number.
|
|
If they are input to an algorithm that makes no constructions
|
|
you can use a kernel that provides exact predicates, but inexact
|
|
constructions. An example for that is the convex hull algorithm
|
|
which we will see in the next section.
|
|
The output is a subset of the input, and the algorithm
|
|
only compares coordinates and performs orientation tests.
|
|
|
|
At a first glance the kernel doing exact predicates and constructions
|
|
seems to be the perfect choice, but performance requirements
|
|
or limited memory resources make that it is not. Also for many
|
|
algorithms it is irrelevant to do exact constructions. For example
|
|
a surface mesh simplification algorithm that iteratively contracts
|
|
an edge, by collapsing it to the midpoint of the edge.
|
|
|
|
Most \cgal packages explain what kind of kernel they need or support.
|
|
|
|
|
|
\section intro_convex_hull The Convex Hull of a Sequence of Points
|
|
|
|
All examples in this section compute the 2D convex hull of a set of points.
|
|
We show that algorithms get their input as a begin/end iterator pair
|
|
denoting a range of points, and that they write the result, in the
|
|
example the points on the convex hull, into an output iterator.
|
|
|
|
|
|
\subsection intro_array The Convex Hull of Points in a Built-in Array
|
|
|
|
In the first example we have as input an array of five points.
|
|
As the convex hull of these points is a subset of the input
|
|
it is safe to provide an array for storing the result which
|
|
has the same size.
|
|
|
|
\cgalExample{Convex_hull_2/array_convex_hull_2.cpp}
|
|
|
|
We saw in the previous section that \cgal comes
|
|
with several kernels. As the convex hull algorithm only makes
|
|
comparisons of coordinates and orientation tests of input points,
|
|
we can choose a kernel that provides exact predicates, but no
|
|
exact geometric constructions.
|
|
|
|
The convex hull function takes three arguments, the start
|
|
and past-the-end pointer for the input, and the start pointer of the
|
|
array for the result. The function returns the pointer
|
|
into the result array just behind the last convex hull
|
|
point written, so the pointer difference tells us how
|
|
many points are on the convex hull.
|
|
|
|
|
|
\subsection intro_vector The Convex Hull of Points in a Vector
|
|
|
|
In the second example we replace the built-in array
|
|
by a `std::vector` of the Standard Template Library.
|
|
|
|
\cgalExample{Convex_hull_2/vector_convex_hull_2.cpp}
|
|
|
|
We put some points in the vector calling the `push_back()`
|
|
method of the `std::vector` class.
|
|
|
|
We then call the convex hull function. The first two arguments,
|
|
`points.begin()` and `points.end()` are *iterators*, which are a
|
|
generalization of pointers: they can be dereferenced and
|
|
incremented. The convex hull function is *generic* in the sense
|
|
that it takes as input whatever can be dereferenced and incremented.
|
|
|
|
The third argument is where the result gets written to. In the
|
|
previous example we provided a pointer to allocated memory. The
|
|
generalization of such a pointer is the *output iterator*, which
|
|
allows to increment and assign a value to the dereferenced iterator.
|
|
In this example we start with an empty vector which grows as needed.
|
|
Therefore, we cannot simply pass it `result.begin()`, but an output
|
|
iterator generated by the helper function
|
|
`std::back_inserter(result)`. This output iterator does nothing when
|
|
incremented, and calls `result.push_back(..)` on the assignment.
|
|
|
|
|
|
If you know the \stl, the Standard Template Library, the above makes
|
|
perfect sense, as this is the way the \stl decouples algorithms from
|
|
containers. If you don't know the \stl, you maybe better first
|
|
familiarize yourself with its basic ideas.
|
|
|
|
|
|
\section intro_traits About Kernels and Traits Classes
|
|
|
|
In this section we show how we express the requirements that must
|
|
be fulfilled in order that a function like `convex_hull_2()`
|
|
can be used with an arbitrary point type.
|
|
|
|
If you look at the manual page of the function `convex_hull_2()`
|
|
and the other 2D convex hull algorithms, you see that they come in two
|
|
versions. In the examples we have seen so far the function that takes two
|
|
iterators for the range of input points and an output iterator for
|
|
writing the result to. The second version has an additional template
|
|
parameter `Traits`, and an additional parameter of this type.
|
|
|
|
\code{.cpp}
|
|
template<class InputIterator , class OutputIterator , class Traits >
|
|
OutputIterator
|
|
convex_hull_2(InputIterator first,
|
|
InputIterator beyond,
|
|
OutputIterator result,
|
|
const Traits & ch_traits)
|
|
\endcode
|
|
|
|
What are the geometric primitives a typical convex hull algorithm
|
|
uses? Of course, this depends on the algorithm, so let us consider
|
|
what is probably the simplest efficient algorithm, the so-called
|
|
"Graham/Andrew Scan". This algorithm first sorts the points from left
|
|
to right, and then builds the convex hull incrementally by adding one
|
|
point after another from the sorted list. To do this, it must at least
|
|
know about some point type, it should have some idea how to sort those
|
|
points, and it must be able to evaluate the orientation of a triple of
|
|
points.
|
|
|
|
And that is where the template parameter `Traits` comes in.
|
|
For `ch_graham_andrew()` it must provide the following nested types:
|
|
|
|
- `Traits::Point_2`
|
|
- `Traits::Less_xy_2`
|
|
- `Traits::Left_turn_2`
|
|
- `Traits::Equal_2`
|
|
|
|
|
|
As you can guess, `Left_turn_2` is responsible for the orientation
|
|
test, while `Less_xy_2` is used for sorting the points. The requirements these
|
|
types have to satisfy are documented in full with the concept
|
|
`ConvexHullTraits_2`.
|
|
|
|
|
|
|
|
The types are regrouped for a simple reason. The alternative would
|
|
have been a rather lengthy function template, and an even longer
|
|
function call.
|
|
|
|
\code{.cpp}
|
|
template <class InputIterator, class OutputIterator, class Point_2, class Less_xy_2, class Left_turn_2, class Equal_2>
|
|
OutputIterator
|
|
ch_graham_andrew( InputIterator first,
|
|
InputIterator beyond,
|
|
OutputIterator result);
|
|
\endcode
|
|
|
|
There are two obvious questions: What can be used as argument for
|
|
this template parameter? And why do we have template parameters at all?
|
|
|
|
To answer the first question, any model of the %CGAL concept `Kernel` provides
|
|
what is required by the concept `ConvexHullTraits_2`.
|
|
|
|
As for the second question, think about an application where we want to
|
|
compute the convex hull of 3D points projected into the `yz` plane. Using
|
|
the class `Projection_traits_yz_3` this is a small modification
|
|
of the previous example.
|
|
|
|
\cgalExample{Convex_hull_2/convex_hull_yz.cpp}
|
|
|
|
Another example would be about a user defined point type, or a point
|
|
type coming from a third party library other than %CGAL. Put the point
|
|
type together with the required predicates for this point type in the
|
|
scope of a class, and you can run `convex_hull_2()` with these
|
|
points.
|
|
|
|
Finally, let us explain why a traits object that is passed to the
|
|
convex hull function? It would allow to use a more general projection
|
|
traits object to store state, for example if the projection plane was
|
|
given by a direction, which is hardwired in the class
|
|
`Projection_traits_yz_3`.
|
|
|
|
|
|
\section intro_concept Concepts and Models
|
|
|
|
In the previous section we wrote that "Any model of the CGAL concept
|
|
Kernel provides what is required by the concept ConvexHullTraits_2".
|
|
|
|
A \em concept is a set of requirements on a type, namely that it has
|
|
certain nested types, certain member functions, or comes with certain
|
|
free functions that take the type as it. A \em model of a concept
|
|
is a class that fulfills the requirements of the concept.
|
|
|
|
Let's have a look at the following function.
|
|
|
|
\code{.cpp}
|
|
template <T>
|
|
T
|
|
duplicate(T t)
|
|
{
|
|
return t;
|
|
}
|
|
\endcode
|
|
|
|
If you want to instantiate this function with a class `C` this
|
|
class must at least provide a copy constructor, and we
|
|
say that class `C` must be a model of `CopyConstructible`.
|
|
A singleton class does not fulfill this requirment.
|
|
|
|
Another example is the function
|
|
|
|
\code{.cpp}
|
|
template <typename T>
|
|
T& std::min(const T& a, constT& b)
|
|
{
|
|
return (a<b)?a:b;
|
|
}
|
|
\endcode
|
|
|
|
This function only compiles if the `operator<<(..)` is defined for the type used as `T`,
|
|
and we say that the type must be a model of `LessThanComparable`.
|
|
|
|
An example for a concept with required free functions is the `HalfedgeListGraph` in the
|
|
\cgal package \ref PkgBGLSummary. In order to be a model of `HalfedgeListGraph` a class `G`
|
|
there must be a global function `halfedges(const G&)`, etc.
|
|
|
|
An example for a concept with a required traits class is `InputIterator`.
|
|
For a model of an `InputIterator` a specialization of the class
|
|
<a href="http://en.cppreference.com/w/cpp/iterator/iterator_traits"> `std::iterator_traits`</a>
|
|
must exist (or the generic template must be applicable).
|
|
|
|
\section intro_further Further Reading
|
|
|
|
We also recommend the standard text books "The C++ Standard Library, A
|
|
Tutorial and Reference" by Nicolai M. Josuttis from Addison-Wesley, or
|
|
"Generic Programming and the STL" by Matthew H. Austern for the \stl
|
|
and its notion of *concepts* and *models*.
|
|
|
|
Other resources for \cgal are the tutorials at
|
|
http://www.cgal.org/Tutorials/ and the user support page at
|
|
http://www.cgal.org/.
|
|
|
|
*/
|
|
} /* namespace CGAL */
|
|
|
|
|