Algorithm Library Design:
Course Home Page --
Lecture Notes --
Source Code --
References
6. CGAL, the Computational Geometry Algorithms Library
Introduction
Computational geometry is the sub-area of algorithm design that deals
with the design and analysis of algorithms for geometric problems
involving objects like points, lines, polygons, and polyhedra.
Over the past two decades, the field has developed a rich body of
solutions to a huge variety of geometric problems including
intersection problems, visibility problems, and proximity problems. A
number of fundamental techniques have been designed, and key problems
and problem classes have emerged.
Geometric algorithms arise in various areas of computer science.
Computer graphics and virtual reality, computer aided design and
manufacturing, solid modeling, robotics, geographical information
systems, computer vision, shape reconstruction, molecular modeling,
and circuit design are well-known examples.
To a large extent the theory has been developed with asymptotic
worst-case complexity analysis and under the assumption of the real
RAM model. Computations with real numbers are assumed to be in
constant time. For many (perhaps most) algorithms and problems this is
a justified assumption that can be perfectly simulated with finite
precision numbers if the input has limited precision.
In 1996 the Computational Geometry Impact Task Force published a task
force report, Application Challenges to Computational
Geometry. Although crediting the remarkable success of the field
in theory, the report now demanded to address also the applicability
in practice. Recommendation number one on the list of four was
``production and distribution of usable (and useful) geometric
codes''. Where are the difficulties in doing so?
There are four major reasons why implementing geometric algorithms in
particular is seen to be more difficult than in other fields:
-
Algorithms in geometry are among the most advanced algorithms in
algorithm design and they make frequent use of complicated data
structures.
Furthermore, software engineering has ignored the difficulties in
algorithm engineering for quite a while. For example, the main
focus in object-oriented design is on data abstraction, data
encapsulation, relationships among data, its reuse and the design
of large-scale systems. Only recently have implementations of
algorithms been rediscovered as an active topic in software
engineering, for example with the generic programming
paradigm [Musser89].
-
The asymptotic worst-case complexity analysis does not match
the practical need for two reasons. In practice, the constant
hidden in the asymptotic analysis can easily outweigh asymptotic
factors, such as log-factors, and the worst-case usually
depends on a general input model that may be unrealistic.
More realistic input models, such as fatness, can help
understanding the practicability of algorithms.
-
Theoretical papers assume exact arithmetic with real numbers. The
correctness proofs of the algorithms rely on exact computation,
and replacing exact arithmetic by imprecise built-in
floating-point arithmetic does not work in general. Geometric
algorithms in particular are sensitive to rounding errors since
numerical data and control flow decisions have usually a strong
interrelation. The numerical problems may destroy the geometric
consistency that an algorithm may rely on. As a result the program
may crash, may run into an infinite loop, or -- perhaps worst of
all -- may produce unpredictable erroneous output.
The requirements on the arithmetic vary with the algorithm. Some
algorithms require only sign computations of polynomial
expressions of bounded degree in the input variables. Others
require unbounded degree or algebraic roots. Various packages for
exact arithmetic are available for different needs. Another
approach is to redesign the algorithm to cope with inexact
arithmetic. Usually the output is only an approximation of the
exact solution. As a common prerequisite for exact arithmetic the
input is rounded, either to convert the input into the format
required for the arithmetic (rounding floating point to integer),
or to lessen the precision requirements on the arithmetic.
-
Often, theoretical papers exclude degenerate configurations in the
input. Typically, these degeneracies are specific to the
algorithm and the problem, and would involve the treatment of
special cases in the algorithm. Simple examples of configurations
considered as degenerate are duplicate points in a point set or
three lines intersecting in one point. For some problems, it is
not difficult to handle the degeneracies, but for other problems
the special case treatment distracts from the solution of the
general problem and it can amount to a considerable fraction of
the coding effort.
In theory, this approach of excluding degeneracies from
consideration is justified by the argument that degenerate cases
are very rare in the set of all possible input over the real
numbers, i.e., they have zero probability if the input set is
randomly chosen over the real numbers. Another argument is that it
is first of all important to understand the general case before
treating special cases.
In practice, however, degenerate input occurs frequently. For
instance, the coordinates of the geometric objects may not be
randomly chosen over the real numbers, but lie on a grid. They may
be created by clicking in a window in a graphical user interface.
In some applications, what are called degeneracies are even
high-valued design criteria. In architecture features of buildings
do align on purpose. As a consequence, practical implementations
usually must address the handling of degeneracies.
General approaches in handling degeneracies are symbolic
perturbation or randomized perturbation with performance and
correctness guarantee.
The community has addressed these topics from time to time and with
increasing intensity (several references are given above), but many
useful geometric algorithms have not found their way into the
application domains of computational geometry yet. This situation is
also a severe hindrance for researchers if they wish to implement and
evaluate their algorithms. Thus, the constants hidden in the analysis
of the otherwise theoretically efficient algorithms often is not
known.
To remedy this situation the Computational Geometry Algorithms
Library, CGAL (http://www.cgal.org/),
has been started five years ago in Europe in order to provide correct,
efficient, and reusable implementations [Fabri99]. The library is being developed
by several universities and research institutes in Europe and
Israel.
The major design goals for CGAL include correctness, robustness,
flexibility, efficiency, and ease-of-use. One aspect of flexibility
is that CGAL algorithms can be easily adapted to work on data types in
applications that already exist. The design goals, especially
flexibility and efficient robust computation, led us to opt for the
generic programming paradigm using templates in C++, and to reject the
object-oriented paradigm in C++ (as well as in Java). In several
appropriate places, however, we make use of object-oriented solutions
and design patterns. Generic programming with templates in C++ also
provides us with the help of strong type checking at compile time.
Moreover, the C++ abstractions used by us do not cause any runtime
overhead.
The birth of the CGAL-library dates back to a meeting in Utrecht in
January 1995. Shortly afterwards, the five authors of [Fabri99] started developing the kernel.
The CGAL-project has been funded officially since October 1996 and the
team of developers has grown considerably among professionals in the
field of computational geometry and related areas, in academia
especially research assistants, PhD students and postdocs. The CGAL
release 1.2 of January 1999 consists of approximately 110,000 lines of
C++ source code for the library, plus 50,000 lines for accompanying
sources, such as the test suite and example programs, not counting C++
comments or empty lines (the release 2.4 of May 2002 consists of
approximately 290,000 lines of code, comments and empty lines included
this time, plus test suite and example programs).
In terms of the elder Constructive Cost Model
(COCOMO) the line counts, the people involved, and the time schedule
indicate a large project comparable to operating systems or database
management systems. The WWW home-page of CGAL (http://www.cgal.org/)
provides a list of publications about CGAL and related research.
Related Work
Three approaches of disseminating geometric software can be
distinguished: collections of isolated implementations, integrated
applications or workbenches, and software libraries. An overview on
the state of the art of computational geometry software before CGAL
including many references is given in [Amenta97].
Collecting isolated implementations, also called the
Gems approach according to the successful Graphics Gems series,
usually requires some adaption effort to make things work together.
Compared to the graphics gems, computational geometry implementations
usually use more involved data structures and more advanced
algorithms. This makes adaption harder. A good collection provides the
Directory of Computational Geometry Software (http://www.geom.umn.edu/software/cglist/).
Integrated applications and workbenches provide a homogeneous
environment, for example with animation and interaction capabilities,
and all parts work smoothly together. However, they tend to be
monolithic, hard to extend, and hard to reuse in other projects.
Examples date back to the end of the Eighties, specifically XYZ
GeoBench (http://wwwjn.inf.ethz.ch/geobench/XYZGeoBench.html)
developed at ETH Zurich, Switzerland, is one of the precursors of
CGAL.
Software libraries promise that the components work seamlessly
together, that the library is extensible and that the components can
be reused in other projects. Examples are the precursors of CGAL
developed by members of the CGAL consortium. These precursors are
PlaGeo developed at Utrecht University, C++Gal developed at Inria
Sophia-Antipolis, and the geometric part of LEDA (http://www.mpi-sb.mpg.de/LEDA/),
a library for combinatorial and geometric computing, which has been
developed at Max-Planck-Institut für Informatik,
Saarbrücken. Another example is
GeomLib, a computational
geometry library implemented in Java at the Center for Geometric
Computing, located at Brown University, Duke University, and Johns
Hopkins University in the United States. They state their goal as
an effective technology transfer from Computational Geometry to
relevant applied fields.
Overview of the Library Structure
CGAL is structured into three layers and a support library, which
stands apart. The three layers are the core library with basic
non-geometric functionality, the geometric kernel with basic geometric
objects and operations, and the basic library with algorithms and data
structures.

The library layers and the support library are further subdivided into
smaller modular units. The modular approach has several benefits: The
library is easier to learn, the implementation work is more easily
spread among the project partners, and the reduction of dependencies
facilitates testing and maintenance.
The geometric kernel contains simple geometric objects of constant
size such as points, lines, segments, triangles, tetrahedra, circle
and more. It provides geometric predicates on those objects,
operations to compute intersections of and distances between objects,
and affine transformations. The kernel objects are closed under affine
transformations, e.g., the existence of circles implies that there are
also ellipses in the kernel.
The geometric kernel is split in three parts, one for two-dimensional
objects, one for three-dimensional objects, and one for
general-dimensional objects. Geometry in two and three dimensions is
well studied and has lots of applications which explains their special
status. For all dimensions there are Cartesian and homogeneous
representations available for the coordinates.
To solve robustness problems, CGAL advocates the use of exact
arithmetic instead of floating point arithmetic. An arithmetic is
associated with a number type in CGAL and the classes in the geometric
kernel are parameterized by number types. CGAL provides own number
types and supports number types from other sources, e.g., from LEDA or
the Gnu Multiple Precision library. Since the arithmetic operations
needed in CGAL are quite basic, every library supplying number types
can be adapted easily to work with CGAL.
The basic library contains more complex geometric objects and data
structures: polygons, triangulations, planar maps, polyhedra and so
on. It also contains algorithms, such as for computing the convex
hull of a set of points, the union of two polygons, smallest enclosing
ellipse and so on. The figure above indicates the major parts in the
basic library. These parts are mostly independent from each other and
even independent from the kernel. This independence has been achieved
with geometric traits classes, to be discussed later. Default
implementations of the traits classes use the CGAL kernel for the
types and primitive operations. Other implementations of the traits
classes provided in CGAL use the LEDA geometric part. The traits
class requirements are simple enough for a user to be able to write a
traits class for own geometric data types and operations.
The core library offers basic non-geometric functionality that is
needed in the geometric kernel or the basic library, for example
support for coping with different C++ compilers which all have their
own limitations. The core library contains the support for assertions,
preconditions and postconditions. Circulators and random number
generators belong here as well.
The support library also contains functionality with non-geometric
aspects. In contrast to the core library, this functionality is not
needed by the geometric kernel nor the basic library. The support
library interfaces the geometric objects with external
representations, like visualizations or external file formats. Among
the list of supported formats are VRML and PostScript as well as the
GeomView program and LEDA windows for 2D and 3D visualization. The
support library also contains generators for synthetic test data sets,
for example random points uniformly distributed in a certain domain.
The adaptation of number types from other libraries is contained in
the support library as well. The separation from the kernel and the
basic library makes the functionality in the support library
orthogonal and therefore open for future extensions.
Geometric Kernel
The geometric kernel contains types for objects of constant size, such
as point, vector, direction, line, ray, segment, triangle,
iso-oriented rectangle and tetrahedron. Each type provides a set of
member functions, for example access to the defining objects, the
bounding box of the object if existing, and affine transformation.
Global functions are available for the detection and computation of
intersections as well as for distance computations.
The current geometric kernel provides two families of geometric
objects: One family is based on the representation of points using
Cartesian coordinates. The other family is based on the representation
of points using homogeneous coordinates. The homogeneous
representation extends the representation with Cartesian coordinates
by an additional coordinate which is used as a common denominator.
More formally, in d-dimensional space, a point with homogeneous
coordinates , where , has
Cartesian coordinates