update the doxygen doc of the Arrangement package from the doc_tex

using the following commits:
f669df07
a1fb4c48
0d9f5aa1
40fac7ad
15e766a5
3f021c72
178e7a89
4a20a898
b8817aa6
5a7309f6
b05d1870
03fbdf61
e25e73a5
26cb83f9
9a491625
c9e72151
5651842b
97ed2499
dc2f174b
fea29a85
This commit is contained in:
Sébastien Loriot 2013-05-22 17:31:23 +02:00
parent ee776291e7
commit 18b9ec1c4f
11 changed files with 424 additions and 294 deletions

View File

@ -756,197 +756,207 @@ arrangement operations - see more details in the Reference Manual.
\section arr_secqueries Issuing Queries on an Arrangement \section arr_secqueries Issuing Queries on an Arrangement
One of the most important query types defined on arrangements is One of the most important query types defined on arrangements is
the <I>point-location</I> query: Given a point, find the the <I>point-location</I> query: Given a point, find the arrangement
arrangement cell that contains it. Typically, the result of a cell that contains it. Typically, the result of a point-location
point-location query is one of the arrangement faces, but in query is one of the arrangement faces, but in degenerate situations
degenerate situations the query point can be located on an edge or the query point can be located on an edge or it may coincide with a
coincide with a vertex. vertex.
Point-location queries are not only common in many applications, Point-location queries are common in many applications, and also
they also play an important role in the free insertion-functions play an important role in the incremental construction of arrangements
(see Section \ref arr_secgl_funcs). Therefore, it is crucial to (and more specifically in the free insertion-functions described in
have the ability to answer such queries effectively for any Section \ref arr_secgl_funcs). Therefore, it is crucial to have the
arrangement instance. ability to answer such queries effectively.
\subsection arr_ssecpl Point-Location Queries \subsection arr_ssecpl Point-Location Queries
The arrangement package includes several classes (more precisely, The `Arrangement_2` class template does not support point-location
class templates parameterized by an arrangement class) that model queries directly, as the arrangement representation is decoupled from
the `ArrangementPointLocation_2` concept. Namely, they all the geometric algorithms that operate on it. The <I>2D Arrangements</I>
have a member function called `locate(q)` that accepts a query package includes a set of classe templates that are capable of
point \f$ q\f$ and result with a \cgal `Object` that wraps a handle answering such queries; all are models of the concept
to the arrangement cell containing the query point. This object can `ArrangementPointLocation_2`. Each model employs a different
be assigned to either a `Face_const_handle`, algorithm or <I>strategy</I> for answering queries. A model of this
`Halfedge_const_handle` or a `Vertex_const_handle`, depending concept must define the `locate()` member function, which accepts
on whether the query point is located inside a face, on an edge or an input query-point and returns an object that represents the
on a vertex. arrangement cell that contains this point. This object is is type
`Arr_point_location_result<Arrangement_2>::%Type`---a discriminated
union container of the bounded types `Vertex_const_handle`,
`Halfedge_const_handle`, or `Face_const_handle`. Depending on
whether the query point is located inside a face, on an edge, or on a
vertex, the appropriate handle can be obtained with <I>value retrieval</I>
by `boost::get` as demonstrated in the example below.
Note that the handles returned by the `locate()` functions are Note that the handles returned by the `locate()` functions are
`const` (non-mutable) handles. If necessary, such handles may non-mutable (`const`). If necessary, such handles may
be casted to mutable handles using the static functions be cast to mutable handles using the `non_const_handle()` methods
`Arrangement_on_surface_2::non_const_handle()` provided by the `Arrangement_2::non_const_handle()` provided by the
arrangement class. `Arrangement_2` class.
An instance of any point-location class must be attached to an An object `pl` of any point-location class must be attached to an
`Arrangement_on_surface_2` instance so we can use it to issue point-location `Arrangement_2` object `arr` before it is used to answer
queries. This attachment can be performed when the point-location point-location queries on `arr`. This attachment can be performed
instance is constructed, or at a later time, using the `init(arr)` when `pl` is constructed or at a later time using the
method, where `arr` is the attached `Arrangement_on_surface_2` instance. `pl.init(arr)` call.
In this chapter we always use the first option.
The following function template, which can be found in the example The function template listed below accepts a point-location object,
file `point_location_utils.h`, accepts a point-location object the type of which is a model of the `ArrangementPointLocation_2`
(whose type can be any of the models to the concept, and a query point. The function template issues a
`ArrangementPointLocation_2` concept) and a query point, and point-location query for the given point, and prints out the result.
prints out the result of the point-location query for the given It is defined in the header file `point_location_utils.h`.
point. Observe how we use the function `assign()` is order
to cast the resulting `Object` into a handle to an arrangement
feature. The point-location object `pl` is assumed to be already
associated with an arrangement:
\anchor lst_pl
\code \code
template <class PointLocation> template <typename PointLocation>
void point_location_query void locate_point(const PointLocation& pl,
(const PointLocation& pl, const typename PointLocation::Arrangement_2::Point_2& q)
const typename PointLocation::Arrangement_on_surface_2::Point_2& q)
{ {
// Perform the point-location query. typedef PointLocation Point_location;
CGAL::Object obj = pl.locate (q); typedef typename Point_location::Arrangement_2 Arrangement_2;
typename CGAL::Arr_point_location_result<Arrangement_2>::Type obj =
pl.locate(q);
// Print the result. // Print the result.
typedef typename PointLocation::Arrangement_on_surface_2 Arrangement_on_surface_2; print_point_location<Arrangement_2>(q, obj);
}
\endcode
typename Arrangement_on_surface_2::Vertex_const_handle v; The function template `locate_point()` calls an instance of the
typename Arrangement_on_surface_2::Halfedge_const_handle e; function template `print_point_location()`, which inserts the
typename Arrangement_on_surface_2::Face_const_handle f; result of the query into the standard output-stream. It is listed
below, and defined in the header file `point_location_utils.h`.
Observe how the function `boost::get()` is used to cast the
resulting object into a handle to an arrangement feature. The
point-location object `pl` is assumed to be already attached
to an arrangement.
std::cout << "The point " << q << " is located "; \code
if (CGAL::assign (f, obj)) { template <typename Arrangement_>
// q is located inside a face: void
if (f->is_unbounded()) print_point_location
std::cout << "inside the unbounded face." << std::endl; (const typename PointLocation::Arrangement_2::Point_2& q
else typename CGAL::Arr_point_location_result<Arrangement_>::Type obj)
std::cout << "inside a bounded face." << std::endl; {
} else if (CGAL::assign (e, obj)) { typedef Arrangement_ Arrangement_2;
// q is located on an edge:
std::cout << "on an edge: " << e->curve() << std::endl; typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
} else if (CGAL::assign (v, obj)) { typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
// q is located on a vertex: typedef typename Arrangement_2::Face_const_handle Face_const_handle;
if (v->is_isolated())
std::cout << "on an isolated vertex: " << v->point() << std::endl; const Vertex_const_handle* v;
else const Halfedge_const_handle* e;
std::cout << "on a vertex: " << v->point() << std::endl; const Face_const_handle* f;
} else {
CGAL_assertion_msg (false, "Invalid object."); std::cout << "The point (" << q << ") is located ";
} if (f = boost::get<Face_const_handle>(&obj)) // located inside a face
std::cout << "inside "
<< (((*f)->is_unbounded()) ? "the unbounded" : "a bounded")
<< " face." << std::endl;
else if (e = boost::get<Halfedge_const_handle>(&obj)) // located on an edge
std::cout << "on an edge: " << (*e)->curve() << std::endl;
else if (v = boost::get<Vertex_const_handle>(&obj)) // located on a vertex
std::cout << "on " << (((*v)->is_isolated()) ? "an isolated" : "a")
<< " vertex: " << (*v)->point() << std::endl;
else CGAL_error_msg("Invalid object.");
} }
\endcode \endcode
\subsection arr_sssecpl_strat Choosing a Point-Location Strategy \subsection arr_sssecpl_strat Choosing a Point-Location Strategy
Each of the various point-location classes employs a different Each of the various point-location class templates employs a different
algorithm or <I>strategy</I>\cgalFootnote{We use the term <I>strategy</I> following the design pattern taxonomy \cite cgal:ghjv-dpero-95.} algorithm or <I>strategy</I>\cgalFootnote{We use the term <I>strategy</I>
is borrowed from the design-pattern taxonomy \cite cgal:ghjv-dpero-95, Chapter 5.}
for answering queries: for answering queries:
<UL> <UL>
<LI>`Arr_naive_point_location<Arrangement>` locates the query <LI> `Arr_naive_point_location<Arrangement>` employes the
point naively, by exhaustively scanning all arrangement cells. <I>naive</I> strategy. It locates the query point naively,
<LI>`Arr_walk_along_a_line_point_location<Arrangement>` exhaustively scanning all arrangement cells.
simulates a traversal, in reverse order, along an imaginary vertical %
ray emanating <LI> `Arr_walk_along_a_line_point_location<Arrangement>`} employs
from the query point: It starts from the unbounded face of the the <I>walk-along-a-line</I> (or <I>walk</I> for short) strategy.
arrangement and moves downward toward the query point until It simulates a traversal, in reverse order, along an imaginary
locating the arrangement cell containing it. vertical ray emanating from the query point. It starts from the
unbounded face of the arrangement and moves downward toward the
query point until locating the arrangement cell containing it.
<LI>`Arr_landmarks_point_location<Arrangement,Generator>` <LI>`Arr_landmarks_point_location<Arrangement,Generator>`
uses a set of "landmark" points whose location in the uses a set of <I>landmark</I> points the location of which in the
arrangement is known. Given a query point, it uses a <span class="textsc">Kd</span>-tree to arrangement is known. It employs the
find the nearest landmark and then traverses the straight line <I>landmark</I> strategy. Given a query point, it uses a
segment connecting this landmark to the query point.<BR> nearest-neighbor search-structure (a <span class="textsc">Kd</span>-tree is used by default)
There are various ways to select the landmark set in the to find the nearest landmark and then traverses the straight-line
arrangement, determined by the `Generator` template parameter. segment connecting this landmark to the query point.
By default, the generator
class `Arr_landmarks_vertices_generator` is used and the There are various ways to select the landmark set in the
arrangement vertices are the selected landmarks, but other arrangement. The selection is governed by the `Generator`
landmark generators, such as sampling random points or template parameter. The default generator class, namely
choosing points on a grid, are also available; see the `Arr_landmarks_vertices_generator`, selects all the vertices of
Reference Manual for more details. the attached arrangement as landmarks. Additional generators that
select the set in other ways, such as by sampling random
points or choosing points on a grid, are also available; see the
Reference Manual for more details.
The landmark strategy requires that the type of the attached
arrangement be an instance of the `Arrangement_2<Traits,Dcel>`
class template, where the `Traits` parameter is substituted with
a geometry-traits class that models the
`ArrangementLandmarkTraits_2` concept, which refines the basic
`ArrangementBasicTraits_2` concept; see
Section \ref arr_sssectr_lanmarks_concept for details. Most traits
classes included in the <I>2D Arrangement</I> package are models of
this refined concept.
<LI>`Arr_trapezoid_ric_point_location<Arrangement>` implements <LI>`Arr_trapezoid_ric_point_location<Arrangement>` implements
a point location algorithm presented by Seidel \cite s-sfira-91, which uses the Mulmuley's point-location algorithm \cite m-fppa-90; see
randomized incremental construction described by Mulmuley \cite m-fppa-90 (see also \cite bkos-cgaa-00, Chapter 6. The arrangement faces are
also [\cite bkos-cgaa-00 Chapter 6). The decomposed into simpler cells each of constant complexity, known as
arrangement faces are decomposed into simpler cells of constant <I>pseudo-trapezoids</I>, and a search structure (a directed acyclic
complexity known as <I>pseudo-trapezoids</I> and a search-structure graph) is constructed on top of these cells, facilitating the search
(a directed acyclic graph) is constructed on top of these cells, of the pseudo trapezoid (hence the arrangement cell) containing a
allowing to locate the pseudo-trapezoid (hence the arrangement query point in expected logarithmic time. The trapezoidal map and
cell) containing a query point in logarithmic time. the search structure are built by a algorithm (RIC).
</UL> </UL>
The main advantage of the first two strategies is that they do not The first two strategies do not require any extra data. The class
require any extra data, so the respective classes just store a templates that implement them store a pointer to an arrangement object
pointer to an arrangement object and operate directly on it. and operate directly on it. Attaching such point-location objects to
Attaching such point-location objects to an existing arrangement an existing arrangement has virtually no running-time cost at all, but
has virtually no running-time cost at all, but the query time is the query time is linear in the size of the arrangement (the
linear in the size of the arrangement (the performance of the performance of the walk strategy is much better in practice, but
"walk" strategy is much better in practice, but its worst-case its worst-case performance is linear). Using these strategies is
performance is linear). Using these strategies is therefore therefore recommended only when a relatively small number of
recommended only when a relatively small number of point-location point-location queries are issued by the application, or when the
queries are issued by the application, or when the arrangement is arrangement is constantly changing (That is, changes in the arrangement
constantly changing (i.e., changes in the arrangement structure structure are more frequent than point-location queries).
are more frequent than point-location queries).
On the other hand, the landmarks and the trapezoid RIC strategies On the other hand, the landmarks and the trapezoid RIC strategies
require auxiliary data structures on top of the arrangement, which require auxiliary data structures on top of the arrangement, which
they need to construct once they are attached to an arrangement they need to construct once they are attached to an arrangement
object and need to keep up-to-date as this arrangement changes. object and need to keep up-to-date as this arrangement changes.
The data structure needed by the landmarks strategy can be constructed The data structure needed by the landmarks strategy can be constructed
in \f$ O(N \log N)\f$ time (where \f$ N\f$ is the overall number of edges in in \f$ O(N \log N) \f$ time, where \f$ N \f$ is the overall number of edges in
the arrangement), whereas the construction of the data structure needed the arrangement, but the constant hidden in the \f$ O() \f$ notation for the
by the trapezoid RIC strategy takes expected \f$ O(N \log N)\f$, but trapezoidal map RIC strategy is much larger. Thus, construction needed
may require several rebuilds. As shown in \cite hkh-iiplgtds-12, one can by the landmark algorithm is in practice significantly faster than the
expect only a small number of rebuilds. construction needed by the trapezoidal map RIC strategy. In addition,
In practice, the construction needed by the landmark algorithm is although both resulting data structures are asymptotically linear in
significantly faster. size, using a <span class="textsc">Kd</span>-tree as the nearest-neighbor search-structure that
In addition, although both the landmark algorithm stores significantly reduces memory consumption.
resulting data structures are asymptotically linear in size, the The trapezoidal map RIC algorithm has expected logarithmic query time,
<span class="textsc">Kd</span>-tree that the landmark algorithm stores needs significantly while the query time for the landmark strategy may be as large as
less memory. linear. In practice however, the query times of both strategies are
competitive. For a detailed experimental comparison
see \cite hh-eplca-05
We note that the trapezoid RIC algorithm guarantees a Updating the auxiliary data structures of the trapezoidal map RIC
logarithmic query time for any scenario algorithm is done very efficiently. On the other hand, updating the
making it advantageous comparing to other strategies. nearest-neighbor search-structure of the landmark algorithm may consume
The query time of the landmarks strategy, on the other hand, more time when the arrangement changes frequently, especially when
is only logarithmic on average - and we may have a <span class="textsc">Kd</span>-tree is used, as it must be rebuilt each time the arrangement
scenarios where the query time can be linear. changes. It is therefore recommended that the
In practice, in many scenarios `Arr_landmarks_point_location` class template be used when the
the query times of both strategies are competitive. For a detailed application frequently issues point-location queries on an arrangement
experimental comparison, see \cite hh-esplp-08. that only seldom changes. If the arrangement is more dynamic and is
frequently going through changes, the `Arr_trapezoid_ric_point_location`
Another advantageous feature of the trapezoid RIC strategy class template should be the selected point-location strategy.
when compared with other methods
is the unbounded curves support.
Currently, this is the most efficient strategy
suitable for general unbounded subdivisions.
The main drawback in the current implementation of the landmark
strategy, compared to the trapezoidal RIC strategy, is that while
the updating the auxiliary data structures
related to the trapezoidal decomposition is done very efficiently,
the <span class="textsc">Kd</span>-tree maintained by the landmark algorithm needs to be
frequently rebuilt as the arrangement changes. In addition, using
the landmark point-location class adds some extra requirement
from the traits class (that is, the traits class should be a model
of a refined concept `ArrangementLandmarkTraits_2`; see
Section \ref arr_sectraits for the details). However, most
built-in traits classes that come with the \cgal public release
support these extra operations.
It is therefore recommended to use the
`Arr_landmarks_point_location` class when the application
frequently issues point-location queries on a bounded
arrangement that only seldom changes. If the arrangement
consists of unbounded curves or is more
dynamic and is frequently going through changes, the
`Arr_trapezoid_ric_point_location` class should be the
selected point-location strategy.
\subsection arr_sssecpl_ex An Example \subsection arr_sssecpl_ex An Example
@ -954,135 +964,136 @@ selected point-location strategy.
The arrangement of line segments, as constructed in `point_location_example.cpp`, `vertical_ray_shooting.cpp`, and `batched_point_location.cpp`. The arrangement vertices are drawn as small discs, while the query points \f$ q_1, \ldots, q_6\f$ are marked with crosses. The arrangement of line segments, as constructed in `point_location_example.cpp`, `vertical_ray_shooting.cpp`, and `batched_point_location.cpp`. The arrangement vertices are drawn as small discs, while the query points \f$ q_1, \ldots, q_6\f$ are marked with crosses.
\cgalFigureEnd \cgalFigureEnd
The following program constructs a simple arrangement of five line The program listed below constructs a simple arrangement of five line
segments that form a pentagonal face, with a single isolated segments that form a pentagonal face, with a single isolated
vertex in its interior, as depicted in \cgalFigureRef{arr_figex_5} vertex in its interior, as depicted in Figure \cgalFigureRef{arr_figex_5}.
(the arrangement construction is performed by the function Notice that we use the same arrangement structure in the next
`construct_segment_arr()` whose listing is omitted here and three example programs. The arrangement construction is performed by
can be found in `point_location_utils.h`). the function `construct_segment_arr()` defined in the heade file
It then employs the naive and the landmark strategies to issue `point_location_utils.h`. (Its listing is omitted here.) The
several point-location queries on this arrangement: program employs the naive and the landmark strategies to issue
several point-location queries on this arrangement.
\cgalExample{Arrangement_on_surface_2/point_location_example.cpp} \cgalExample{Arrangement_on_surface_2/point_location_example.cpp}
Note that the program uses the auxiliary Note that the program uses the `locate_point()` function template
`point_location_query()` function template to nicely print the to locate a point and nicely print the result of each query; see
result of each query. This function can be found in the header file \ref lst_pl "here".
`point_location_utils.h`.
\subsection arr_ssecray_shoot Vertical Ray Shooting \subsection arr_ssecray_shoot Vertical Ray Shooting
Another important query issued on arrangements is the vertical Another important query issued on arrangements is the vertical
ray-shooting query: Given a query point, which arrangement feature ray-shooting query: Given a query point, which arrangement feature
do we encounter if we shoot a vertical ray emanating upward (or do we encounter by a vertical ray shot upward (or downward) from this
downward) from this point? In the general case the ray hits an point? In the general case the ray hits an edge, but it is possible
edge, but it is possible that it hits a vertex, or that the that it hits a vertex, or that the arrangement does not have any
arrangement does not have any feature lying directly above (or vertex or edge lying directly above (or below) the query point.
below) the query point.
All point-location classes listed in the previous section are also models All point-location classes listed in the previous section are also
of the `ArrangementVerticalRayShoot_2` concept. That is, they all models of the `ArrangementVerticalRayShoot_2` concept. That is,
have member functions called `ray_shoot_up(q)` and they all have member functions called `ray_shoot_up(q)` and
`ray_shoot_down(q)` that accept a query point \f$ q\f$ and output a `ray_shoot_down(q)` that accept a query point `q`. These functions
\cgal `Object`. This can be assigned to either a output an object of type type
`Halfedge_const_handle` or to a `Vertex_const_handle`. `Arr_point_location_result<Arrangement_2>::%Type`---a discriminated
Alternatively, the returned value is a `Face_const_handle` union container of the bounded types `Vertex_const_handle`,
for the unbounded face of the arrangement, in case there is no edge `Halfedge_const_handle`, or `Face_const_handle`. The latter type
or vertex lying directly above (or below) \f$ q\f$. is used for the unbounded face of the arrangement, in case there is no
edge or vertex lying directly above (or below) `q`.
The following function template, `vertical_ray_shooting_query()`, The function template `vertical_ray_shooting_query()` listed
which also located in the header file `point_location_utils.h`, below accepts a vertical ray-shooting object, the type of which
accepts a vertical ray-shooting models the `ArrangementVerticalRayShoot_2` concept. It exports
object, whose type can be any of the models to the the result of the upward vertical ray-shooting operation from a
`ArrangementVerticalRayShoot_2` concept and prints out the given query point to the standard output-stream. The ray-shooting
result of the upward vertical ray-shooting operations from a given object `vrs` is assumed to be already attached to an arrangement.
query point. The ray-shooting object `vrs` is assumed to be The function template is defined in the header file
already associated with an arrangement: `point_location_utils.h.
\code \code
template <class VerticalRayShoot> template <typename RayShoot>
void vertical_ray_shooting_query void shoot_vertical_ray(const RayShoot& vrs,
(const VerticalRayShoot& vrs, const typename RayShoot::Arrangement_2::Point_2& q)
const typename VerticalRayShoot::Arrangement_on_surface_2::Point_2& q)
{ {
typedef RayShoot Vertical_ray_shooting;
// Perform the point-location query. // Perform the point-location query.
CGAL::Object obj = vrs.ray_shoot_up (q); typename Vertical_ray_shooting::result_type obj = vrs.ray_shoot_up(q);
// Print the result. // Print the result.
typedef typename VerticalRayShoot::Arrangement_on_surface_2 Arrangement_on_surface_2; typedef typename Vertical_ray_shooting::Arrangement_2 Arrangement_2;
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
typename Arrangement_on_surface_2::Vertex_const_handle v; typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
typename Arrangement_on_surface_2::Halfedge_const_handle e; typedef typename Arrangement_2::Face_const_handle Face_const_handle;
typename Arrangement_on_surface_2::Face_const_handle f;
std::cout << "Shooting up from " << q << " : ";
if (CGAL::assign (e, obj)) {
// We hit an edge:
std::cout << "hit an edge: " << e->curve() << std::endl;
} else if (CGAL::assign (v, obj)) {
// We hit a vertex:
if (v->is_isolated())
std::cout << "hit an isolated vertex: " << v->point() << std::endl;
else
std::cout << "hit a vertex: " << v->point() << std::endl;
} else if (CGAL::assign (f, obj)) {
// We did not hit anything:
CGAL_assertion (f->is_unbounded());
const Vertex_const_handle* v;
const Halfedge_const_handle* e;
const Face_const_handle* f;
std::cout << "Shooting up from (" << q << ") : ";
if (v = boost::get<Vertex_const_handle>(&obj)) // we hit a vertex
std::cout << "hit " << (((*v)->is_isolated()) ? "an isolated" : "a")
<< " vertex: " << (*v)->point() << std::endl;
else if (e = boost::get<Halfedge_const_handle>(&obj)) // we hit an edge
std::cout << "hit an edge: " << (*e)->curve() << std::endl;
else if (f = boost::get<Face_const_handle>(&obj)) \{ // we hit nothing
CGAL_assertion((*f)->is_unbounded());
std::cout << "hit nothing." << std::endl; std::cout << "hit nothing." << std::endl;
} else { else CGAL_error();
CGAL_assertion_msg (false, "Invalid object.");
}
} }
\endcode \endcode
The following program uses the auxiliary function listed above to The program below uses the function template listed above to
perform vertical ray-shooting queries on an arrangement. perform vertical ray-shooting queries on an arrangement. The
The arrangement and the query points are exactly the same as in arrangement and the query points are exactly the same as in
`point_location_example.cpp` (see \cgalFigureRef{arr_figex_5}): `point_location.cpp`; see \cgalFigureRef{arr_figex_5}.
\cgalExample{Arrangement_on_surface_2/vertical_ray_shooting.cpp} \cgalExample{Arrangement_on_surface_2/vertical_ray_shooting.cpp}
The number type we use in this example is \cgal's built-in The number type we use in this example is \cgal's built-in
`MP_Float` type which is a floating-point number with an `MP_Float` type, which is a floating-point number with an
unbounded mantissa and a 32-bit exponent. It supports construction from an unbounded mantissa and a 32-bit exponent. It supports construction
integer or from a machine `float` or `double` and performs additions, from an integer or from a machine `float` or `double` and
subtractions and multiplications in an exact number. performs additions, subtractions and multiplications in an exact
number.
\subsection arr_ssecbatched_pl Batched Point-Location \subsection arr_ssecbatched_pl Batched Point-Location
Suppose that at a given moment our application has to issue a Suppose that at a given moment our application has to issue a
relatively large number \f$ m\f$ of point-location queries on a relatively large number \f$ m\f$ of point-location queries on a
specific arrangement instance. It is possible of course to define specific arrangement object. Naturally, It is possible to define
a point-location object and to issue separate queries on the a point-location object and use it to issue separate queries on
arrangement. However, as explained in Section \ref arr_ssecpl, the arrangement. However, as explained in Section \ref arr_ssecpl
choosing a simple point-location strategy (either the naive or choosing a simple point-location strategy (either the naive or
the walk strategy) means inefficient queries, while the more the walk strategy) means inefficient queries, while the more
sophisticated strategies need to construct auxiliary structures sophisticated strategies need to construct auxiliary structures
that incur considerable overhead in running time. that incur considerable overhead in running time.
On the other hand, the arrangement package includes a free Alternatively, the <I>2D Arrangement</I> package includes a free
`locate()` function that accepts an arrangement a range of `locate()` function that accepts an arrangement and a range of
query points as its input and sweeps through the arrangement to query points as its input and sweeps through the arrangement to
locate all query points in one pass. The function outputs the query locate all query points in one pass. The function outputs the query
results as pairs, where each pair is comprised of a query point results as pairs, where each pair consists of a query point
and a \cgal `Object` that represents the cell containing the and a discriminated union container, which represents the
point (see Section \ref arr_ssecpl). The output pairs are cell containing the point; see Section \ref arr_ssecpl. The output
sorted in increasing \f$ xy\f$-lexicographical order of the query point. pairs are sorted in increasing $xy$-lexicographical order of the
query point.
The batched point-location operation can be performed in The batched point-location operation is carried out by sweeping the
\f$ O\left((m+N)\log{(m+N)}\right)\f$ time, where \f$ N\f$ is the number of arrangement. Thus, it takes \f$ O((m+N)\log{(m+N)}) \f$ time, where \f$ N \f$
edges in the arrangement. This means that when the number \f$ m\f$ of is the number of edges in the arrangement. Issuing separate queries
exploiting a point-location strategy with logarithmic query time
per query, such as the trapezoidal map RIC strategy (see
Section \ref arr_sssecpl_strat), is asymptotically more
efficient. However, experiments show that when the number \f$ m \f$ of
point-location queries is of the same order of magnitude as \f$ N\f$, point-location queries is of the same order of magnitude as \f$ N\f$,
this operation is more efficient than issuing separate queries. the batched point-location operation is more efficient in practice.
This suggestion is also backed up by experimental results. One of the reasons for the inferior performance of the alternative
Moreover, the batched point-location operation is also (asymptotically faster) procedures is the necessity to construct
advantageous as it does not have to construct and maintain and maintain complex additional data structures.
additional data structures.
The following program issues a batched point-location query, which The program below issues a batched point-location query, which
is essentially equivalent to the six separate queries performed in is essentially equivalent to the six separate queries performed in
`point_location_example.cpp` (see Section \ref arr_ssecpl): `point_location_example.cpp`; see Section \ref arr_ssecpl.
\cgalExample{Arrangement_on_surface_2/batched_point_location.cpp} \cgalExample{Arrangement_on_surface_2/batched_point_location.cpp}
@ -3266,8 +3277,8 @@ segments, as depicted in \cgalFigureRef{arr_figex_24}, while maintaining
the curve history. The example demonstrates the usage of the special the curve history. The example demonstrates the usage of the special
traversal functions. It also shows how to issue point-location queries traversal functions. It also shows how to issue point-location queries
on the resulting arrangement, using the auxiliary function on the resulting arrangement, using the auxiliary function
`point_location_query()` defined in the header file `locate_point()` defined in the header file
`point_location_utils.h` (see also Section \ref arr_ssecpl). `point_location_utils.h`; see also Section \ref arr_ssecpl.
\cgalExample{Arrangement_on_surface_2/curve_history.cpp} \cgalExample{Arrangement_on_surface_2/curve_history.cpp}

View File

@ -6,10 +6,10 @@ namespace CGAL {
The function `locate` performs a batched point-location operation on a The function `locate` performs a batched point-location operation on a
given arrangement. It accepts a range of query points, and locates each given arrangement. It accepts a range of query points, and locates each
point in the arrangement. The query results are returned through the output point in the arrangement. The query results are returned through the output
iterator. Each result is given as a pair of the query point and an object iterator. Each query result is given as a pair of the query point and an
representing the arrangement feature that contains it, namely an object representing the arrangement feature that contains it, namely a
`Object` that may be either `Face_const_handle`, discriminated union container of the bounded types`Face_const_handle`,
`Halfedge_const_handle`, or `Vertex_const_hanlde`. The resulting `Halfedge_const_handle`, and `Vertex_const_hanlde`. The resulting
pairs in the output sequence are sorted in increasing \f$ xy\f$-lexicographical pairs in the output sequence are sorted in increasing \f$ xy\f$-lexicographical
order of the query points. The function returns a past-the-end iterator of order of the query points. The function returns a past-the-end iterator of
the output sequence. the output sequence.
@ -17,17 +17,30 @@ the output sequence.
\cgalHeading{Requirements} \cgalHeading{Requirements}
<UL> <UL>
<LI>`InputIterator::value_type` must be `Traits::Point_2`. <LI>`InputIterator::value_type` must be `Arrangement_2::Point_2`.
<LI>`OutputIterator::value_type` must be <LI>`OutputIterator::value_type` must be convertible to
`std::pair<Traits::Point_2,Object>`. `std::pair<Arrangement_2::Point_2, Arr_point_location_result<Arrangement_2>::%Type>`.
</UL> </UL>
\cgalHeading{A Note on Backwards Compatibility}
This function used to return `CGAL::Object` up to
\cgal version 4.2. Starting with \cgal version 4.3 the return type
is determined by a metafunction. To preserve backwards compatibility
`CGAL::Object` can be constructed from the new return type
implicitly, but switching to the new style is recommended. To enable
the old style without any overhead, the macro
`CGAL_ARR_POINT_LOCATION_VERSION` can be defined to 1 before any
\cgal header is included.
\sa `CGAL::Arr_point_location_result<Arrangement>`
\sa `CGAL_ARR_POINT_LOCATION_VERSION`
*/ */
template<typename Traits, typename Dcel, template<typename Traits, typename Dcel,
typename PointsIterator, typename OutputIterator> typename InputIterator, typename OutputIterator>
OutputIterator locate (const Arrangement_2<Traits,Dcel>& arr, OutputIterator locate (const Arrangement_2<Traits,Dcel>& arr,
PointsIterator points_begin, InputIterator points_begin,
PointsIterator points_end, InputIterator points_end,
OutputIterator oi); OutputIterator oi);
} /* namespace CGAL */ } /* namespace CGAL */

View File

@ -22,12 +22,12 @@ and segments to have rational coordinates.
The nested `Point_2` type defined by the traits class is therefore The nested `Point_2` type defined by the traits class is therefore
<I>different</I> than the `Kernel::Point_2` type. Its coordinates are <I>different</I> than the `Kernel::Point_2` type. Its coordinates are
of type `CoordNT`, which an instantiation of of type `CoordNT`, which an instantiation of
`CGAL::Sqrt_extension<NT,ROOT>` where `NT = ROOT = Kernel::FT`. `Sqrt_extension<NT,ROOT>` where `NT = ROOT = Kernel::FT`.
Moreover, the third and fourth (hidden) template parameters of Moreover, the third and fourth (hidden) template parameters of
`CGAL::Sqrt_extension<NT,ROOT>` are set to `CGAL::Tag_true`, which `Sqrt_extension<NT,ROOT>` are set to `CGAL::Tag_true`, which
enables efficient comparison among different extensions. enables efficient comparison among different extensions.
For more details see the documentation of \ref ::CGAL::Sqrt_extension<NT,ROOT> For more details see the documentation of `Sqrt_extension<NT,ROOT>`.
While `Arr_circle_segment_traits_2` models the concept While `Arr_circle_segment_traits_2` models the concept
`ArrangementDirectionalXMonotoneTraits_2`, the implementation of `ArrangementDirectionalXMonotoneTraits_2`, the implementation of

View File

@ -50,6 +50,11 @@ insertions of curves and not deletions of them.
\cgalModels `ArrangementPointLocation_2` \cgalModels `ArrangementPointLocation_2`
\cgalModels `ArrangementVerticalRayShoot_2` \cgalModels `ArrangementVerticalRayShoot_2`
\sa `ArrangementPointLocation_2`
\sa `ArrangementVerticalRayShoot_2`
\sa `CGAL::Arr_point_location_result<Arrangement>`
\sa `CGAL_ARR_POINT_LOCATION_VERSION`
*/ */
template< typename Arrangement, typename Generator > template< typename Arrangement, typename Generator >
class Arr_landmarks_point_location { class Arr_landmarks_point_location {

View File

@ -16,6 +16,11 @@ time-consuming process when applied to dense arrangements.
\cgalModels `ArrangementPointLocation_2` \cgalModels `ArrangementPointLocation_2`
\cgalModels `ArrangementVerticalRayShoot_2` \cgalModels `ArrangementVerticalRayShoot_2`
\sa `ArrangementPointLocation_2`
\sa `ArrangementVerticalRayShoot_2`
\sa `CGAL::Arr_point_location_result<Arrangement>`
\sa `CGAL_ARR_POINT_LOCATION_VERSION`
*/ */
template< typename Arrangement > template< typename Arrangement >
class Arr_naive_point_location { class Arr_naive_point_location {

View File

@ -0,0 +1,49 @@
/*!
\ingroup PkgArrangement2PointLocation
The macro `CGAL_ARR_POINT_LOCATION_VERSION` can be used to configure
the point-location query API. In particular, it determines which version
of the result type of the point-location and vertical ray-shooting queries
should be used by models of the concepts `ArrangementPointLocation_2`
and `ArrangementVerticalRayShoot_2`, and by the free function
`locate`. The `CGAL_ARR_POINT_LOCATION_VERSION` should be defined before any \cgal header
is included.
`CGAL_ARR_POINT_LOCATION_VERSION` == 1, the result type is set to be `CGAL::Object`.
`CGAL_ARR_POINT_LOCATION_VERSION` == 2, the result type is set to be
`boost::variant<Vertex_const_handle,Halfedge_const_handle,Face_const_handle>`, where `Vertex_const_handle`, `Halfedge_const_handle`, and
`Face_const_handle` are the corresponding nested types in an `Arrangement_2` instance.
\sa `ArrangementPointLocation_2`
\sa `ArrangementVerticalRayShoot_2`
\sa `CGAL::Arr_point_location_result<Arrangement>`
*/
#define CGAL_ARR_POINT_LOCATION_VERSION
namespace CGAL {
/*!
\ingroup PkgArrangement2PointLocation
A binary metafunction to determine the return type of a point-location
or vertical ray-shoot query.
\tparam Arrangement must be an instance of the `Arrangement<Traits,Dcel>` class template.
\sa `ArrangementPointLocation_2`
\sa `ArrangementVerticalRayShoot_2`
\sa `CGAL::Arr_naive_point_location<Arrangement>`
\sa `CGAL::Arr_walk_along_line_point_location<Arrangement>`
\sa `CGAL::Arr_landmarks_point_location<Arrangement,Generator>`
\sa `CGAL::Arr_trapezoid_ric_point_location<Arrangement>`
\sa `CGAL_ARR_POINT_LOCATION_VERSION`
*/
template <class Arrangement>
class Arr_point_location_result
{
public:
/// The type of a point-location or vertical ray-shoot query return type.
typedef Hidden_type Type;
}; /* end Arr_walk_along_line_point_location */
} /* end namespace CGAL */

View File

@ -29,6 +29,11 @@ This strategy supports arbitrary subdivisions, including unbounded ones.
\cgalModels `ArrangementPointLocation_2` \cgalModels `ArrangementPointLocation_2`
\cgalModels `ArrangementVerticalRayShoot_2` \cgalModels `ArrangementVerticalRayShoot_2`
\sa `ArrangementPointLocation_2`
\sa `ArrangementVerticalRayShoot_2`
\sa `CGAL::Arr_point_location_result<Arrangement>`
\sa `CGAL_ARR_POINT_LOCATION_VERSION`
*/ */
template< typename Arrangement > template< typename Arrangement >
class Arr_trapezoid_ric_point_location { class Arr_trapezoid_ric_point_location {

View File

@ -26,6 +26,11 @@ of issued queries is not large.
\cgalModels `ArrangementPointLocation_2` \cgalModels `ArrangementPointLocation_2`
\cgalModels `ArrangementVerticalRayShoot_2` \cgalModels `ArrangementVerticalRayShoot_2`
\sa `ArrangementPointLocation_2`
\sa `ArrangementVerticalRayShoot_2`
\sa `CGAL::Arr_point_location_result<Arrangement>`
\sa `CGAL_ARR_POINT_LOCATION_VERSION`
*/ */
template< typename Arrangement > template< typename Arrangement >
class Arr_walk_along_line_point_location { class Arr_walk_along_line_point_location {

View File

@ -3,18 +3,35 @@
\ingroup PkgArrangement2Concepts \ingroup PkgArrangement2Concepts
\cgalConcept \cgalConcept
A model of the `ArrangementPointLocation_2` concept can be attached to an `Arrangement_2` A model of the `ArrangementPointLocation_2` concept can answer point-location queries on
instance and answer point-location queries on this arrangement. Namely, given an arrangement attached to it. Namely, given a `Arrangement_2::Point_2`
a `Arrangement_2::Point_2` object, representing a point in the plane, object, representing a point in the plane, it returns the arrangement cell
it returns the arrangement cell containing it. In the general case, the containing it. In the general case, the query point is contained inside an
query point is contained inside an arrangement face, but in degenerate arrangement face, but in degenerate situations it may lie on an edge or
situations it may lie on an edge or coincide with an arrangement vertex. coincide with an arrangement vertex.
\cgalHeading{A note on Backwards compatibility}
The `locate` member function used to return `CGAL::Object` up to
\cgal version 4.2. Starting with \cgal version 4.3 the return type
is determined by a metafunction. To preserve backwards compatibility
`CGAL::Object` can be constructed from the new return types
implicitly, but switching to the new style is recommended. To enable
the old style without any overhead, the macro
`CGAL_ARR_POINT_LOCATION_VERSION` can be defined to 1 before any
\cgal header is included.
\cgalHasModel `CGAL::Arr_naive_point_location<Arrangement>` \cgalHasModel `CGAL::Arr_naive_point_location<Arrangement>`
\cgalHasModel `CGAL::Arr_walk_along_line_point_location<Arrangement>` \cgalHasModel `CGAL::Arr_walk_along_line_point_location<Arrangement>`
\cgalHasModel `CGAL::Arr_trapezoid_ric_point_location<Arrangement>` \cgalHasModel `CGAL::Arr_trapezoid_ric_point_location<Arrangement>`
\cgalHasModel `CGAL::Arr_landmarks_point_location<Arrangement,Generator>` \cgalHasModel `CGAL::Arr_landmarks_point_location<Arrangement,Generator>`
\sa `CGAL::Arr_naive_point_location<Arrangement>`
\sa `CGAL::Arr_walk_along_line_point_location<Arrangement>`
\sa `CGAL::Arr_trapezoid_ric_point_location<Arrangement>`
\sa `CGAL::Arr_landmarks_point_location<Arrangement,Generator>`
\sa `CGAL::Arr_point_location_result<Arrangement>`
\sa `CGAL_ARR_POINT_LOCATION_VERSION`
*/ */
class ArrangementPointLocation_2 { class ArrangementPointLocation_2 {
@ -56,9 +73,9 @@ ArrangementPointLocation_2 (const Arrangement_2& arr);
/*! /*!
locates the arrangement cell that contains the query point `q` locates the arrangement cell that contains the query point `q`
and returns a handle for this cell. and returns a discriminated union container of the following bounded
The function returns an `Object` instance that wraps either of the types:
following types:
<UL> <UL>
<LI>`Arrangement_2::Face_const_handle`, in case `q` is <LI>`Arrangement_2::Face_const_handle`, in case `q` is
contained inside an arrangement face; contained inside an arrangement face;
@ -67,9 +84,9 @@ on an arrangement edge;
<LI>`Arrangement_2::Vertex_const_handle`, in case `q` coincides <LI>`Arrangement_2::Vertex_const_handle`, in case `q` coincides
with an arrangement vertex. with an arrangement vertex.
</UL> </UL>
\pre `pl` is attached to a valid arrangement instance. \pre `pl` is attached to a valid arrangement object.
*/ */
Object locate (const Point_2& q) const; Arr_point_location_result<Arrangement_2>::Type locate(const Point_2& q) const;
/// @} /// @}

View File

@ -3,25 +3,42 @@
\ingroup PkgArrangement2Concepts \ingroup PkgArrangement2Concepts
\cgalConcept \cgalConcept
A model of the `ArrangementVerticalRayShoot_2` concept can be attached to an `Arrangement_2` A model of the `ArrangementVerticalRayShoot_2` concept can answer vertical ray-shooting
instance and answer vertical ray-shooting queries on this arrangement. queries on an arrangement attached to it. Namely, given a
Namely, given a `Arrangement_2::Point_2` object, representing a point in `Arrangement_2::Point_2` object, representing a point in the plane,
the plane, it returns the arrangement feature (edge or vertex) that lies it returns the arrangement feature (edge or vertex) that lies
strictly above it (or below it). By "strictly" we mean that if the strictly above it (or below it). By "strictly" we mean that if the
query point lies on an arrangement edge (or on an arrangement vertex) this query point lies on an arrangement edge (or on an arrangement vertex)
edge will <I>not</I> be the query result, but the feature lying above or this edge will <I>not</I> be the query result, but the feature lying
below it. (An exception to this rule is the degenerate situation where the above or below it. (An exception to this rule is the degenerate case
query point lies in the interior of a vertical edge.) Note that it may happen where the query point lies in the interior of a vertical edge.) Note
that the query point lies above the upper envelope (or below the lower that it may happen that the query point lies above the upper envelope
envelope) of the arrangement, so that the vertical ray emanating from it (or below the lower envelope) of the arrangement, and the vertical ray
may go to infinity without hitting any arrangement feature on its way. In this emanating from the query point goes to infinity without hitting any
case the unbounded face is returned. arrangement feature on its way. In this case the unbounded face is
returned.
\cgalHeading{A Note on Backwards Compatibility}
The `ray_shoot_up` and `ray_shoot_down` member functions used
to return `CGAL::Object` up to \cgal version 4.2. Starting with
\cgal version 4.3 the return type is determined by a metafunction. To
preserve backwards compatibility `CGAL::Object` can be constructed
from the new return types implicitly, but switching to the new style
is recommended. To enable the old style without any overhead, the macro
`CGAL_ARR_POINT_LOCATION_VERSION` can be defined to 1 before any
\cgal header is included.
\cgalHasModel `CGAL::Arr_naive_point_location<Arrangement>` \cgalHasModel `CGAL::Arr_naive_point_location<Arrangement>`
\cgalHasModel `CGAL::Arr_walk_along_a_line_point_location<Arrangement>` \cgalHasModel `CGAL::Arr_walk_along_line_point_location<Arrangement>`
\cgalHasModel `CGAL::Arr_trapezoid_ric_point_location<Arrangement>` \cgalHasModel `CGAL::Arr_trapezoid_ric_point_location<Arrangement>`
\cgalHasModel `CGAL::Arr_landmarks_point_location<Arrangement,Generator>` \cgalHasModel `CGAL::Arr_landmarks_point_location<Arrangement,Generator>`
\sa `CGAL::Arr_naive_point_location<Arrangement>`
\sa `CGAL::Arr_walk_along_line_point_location<Arrangement>`
\sa `CGAL::Arr_trapezoid_ric_point_location<Arrangement>`
\sa `CGAL::Arr_landmarks_point_location<Arrangement,Generator>`
\sa `CGAL::Arr_point_location_result<Arrangement>`
\sa `CGAL_ARR_POINT_LOCATION_VERSION`
*/ */
class ArrangementVerticalRayShoot_2 { class ArrangementVerticalRayShoot_2 {
@ -64,9 +81,8 @@ ArrangementVerticalRayShoot_2 (const Arrangement_2& arr);
/*! /*!
locates the arrangement feature that is first hit by an upward-directed locates the arrangement feature that is first hit by an upward-directed
vertical ray emanating from the query point `q`, vertical ray emanating from the query point `q`,
and returns a handle for this feature. and returns a handle for this feature. The function returns a
The function returns an `Object` instance that is a wrapper for discriminated union container of the following bounded types:
one of the following types:
<UL> <UL>
<LI>`Arrangement_2::Halfedge_const_handle`, in case the vertical <LI>`Arrangement_2::Halfedge_const_handle`, in case the vertical
ray hits an arrangement edge; ray hits an arrangement edge;
@ -78,14 +94,13 @@ arrangement.
</UL> </UL>
\pre `rs` is attached to a valid arrangement instance. \pre `rs` is attached to a valid arrangement instance.
*/ */
Object ray_shoot_up (const Point_2& q) const; Arr_point_location_result<Arrangement_2>::Type ray_shoot_up(const Point_2& q) const;
/*! /*!
locates the arrangement feature that is first hit by a downward-directed locates the arrangement feature that is first hit by a downward-directed
vertical ray emanating from the query point `q`, vertical ray emanating from the query point `q`,
and returns a handle for this feature. and returns a handle for this feature. The function returns a
The function returns an `Object` instance that is a wrapper for discriminated union container of the following bounded types:
one of the following types:
<UL> <UL>
<LI>`Arrangement_2::Halfedge_const_handle`, in case the vertical <LI>`Arrangement_2::Halfedge_const_handle`, in case the vertical
ray hits an arrangement edge; ray hits an arrangement edge;
@ -97,7 +112,7 @@ arrangement.
</UL> </UL>
\pre `rs` is attached to a valid arrangement instance. \pre `rs` is attached to a valid arrangement instance.
*/ */
Object ray_shoot_down (const Point_2& q) const; Arr_point_location_result<Arrangement_2>::Type ray_shoot_down (const Point_2& q) const;
/// @} /// @}

View File

@ -180,12 +180,17 @@ implemented as peripheral classes or as free (global) functions.
- `CGAL::Arr_walk_along_line_point_location<Arrangement>` - `CGAL::Arr_walk_along_line_point_location<Arrangement>`
- `CGAL::Arr_trapezoid_ric_point_location<Arrangement>` - `CGAL::Arr_trapezoid_ric_point_location<Arrangement>`
- `CGAL::Arr_landmarks_point_location<Arrangement,Generator>` - `CGAL::Arr_landmarks_point_location<Arrangement,Generator>`
- `CGAL::Arr_vertex_index_map<Arrangement>`
- `CGAL::Arr_face_index_map<Arrangement>`
- `CGAL::Arr_point_location_result<Arrangement>`
## Tags ## ## Tags ##
- `CGAL::Arr_oblivious_side_tag` - `CGAL::Arr_oblivious_side_tag`
- `CGAL::Arr_open_side_tag` - `CGAL::Arr_open_side_tag`
## Macros ##
- \link CGAL_ARR_POINT_LOCATION_VERSION `CGAL_ARR_POINT_LOCATION_VERSION` \endlink
## Functions ## ## Functions ##
- `CGAL::is_valid()` - `CGAL::is_valid()`