Merge branch 'Cone_spanners_2-new_package-UWS-old' into Cone_spanners_2-new_package-UWS
Conflicts: Documentation/doc/Documentation/Doxyfile.in Documentation/doc/Documentation/packages.txt
|
|
@ -0,0 +1,50 @@
|
|||
/*!
|
||||
\ingroup PkgConeBasedSpannersConcepts
|
||||
\cgalConcept
|
||||
|
||||
The concept `ComputeConeBoundaries_2` describes the set of requirements for the functor that
|
||||
computes the directions of cone boundaries with a given cone number and a given initial direction
|
||||
either exactly or inexactly.
|
||||
|
||||
\cgalHasModel `CGAL::Compute_cone_boundaries_2`
|
||||
|
||||
*/
|
||||
template <typename Kernel_>
|
||||
class ComputeConeBoundaries_2 {
|
||||
public:
|
||||
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*! The CGAL kernel type used by the functor. If this parameter is
|
||||
`CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt`,
|
||||
the cone boundaries will be computed exactly; otherwise, inexactly using an approximate PI=3.1415...
|
||||
This kernel type also decides other types such as Kernel_::Point_2, Kernel_::Direction_2, etc.
|
||||
*/
|
||||
typedef Kernel_ kernel_type;
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// \name Operator
|
||||
/// @{
|
||||
|
||||
/*! \brief The operator().
|
||||
*
|
||||
* Compute the directions of cone boundaries with a given
|
||||
* cone number and a given initial direction. The results are returned by the reference
|
||||
* argument: vector \p rays.
|
||||
*
|
||||
* \param[in] cone_number The number of cones
|
||||
* \param[in] initial_direction The direction of the first ray
|
||||
* \param[out] rays Storing the results, a vector of directions. It should contain no
|
||||
* elements when passed to this operator.
|
||||
*/
|
||||
void operator()(const unsigned int cone_number,
|
||||
Direction_2& initial_direction,
|
||||
std::vector<Direction_2>& rays);
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end ComputeConeBoundaries_2 */
|
||||
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
/*!
|
||||
\ingroup PkgConeBasedSpannersConcepts
|
||||
\cgalConcept
|
||||
|
||||
The functors provided in this package for constructing
|
||||
cone-based spanners are parameterized with a traits class `Traits`, which defines the
|
||||
primitives (predicates and construction objects) required by the functors.
|
||||
|
||||
\cgalHasModel any model of a \cgal %kernel.
|
||||
|
||||
*/
|
||||
|
||||
class ConeBasedSpannerTraits {
|
||||
public:
|
||||
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
The point type.
|
||||
*/
|
||||
typedef unspecified_type Point_2;
|
||||
|
||||
/*!
|
||||
The line type.
|
||||
*/
|
||||
typedef unspecified_type Line_2;
|
||||
|
||||
/*!
|
||||
The direction type.
|
||||
*/
|
||||
typedef unspecified_type Direction_2;
|
||||
|
||||
/*!
|
||||
The affine transformation type.
|
||||
*/
|
||||
typedef unspecified_type Aff_transformation_2;
|
||||
|
||||
/*!
|
||||
The polynomial type. When the cone angle \f$ \theta \f$ is in the form of
|
||||
\f$ 2\pi / n \f$, where \f$ n \f$ is a positive integer, \f$ \sin(\theta) \f$
|
||||
and \f$ \cos(\theta) \f$ can be represented exactly by roots of polynomials.
|
||||
*/
|
||||
typedef unspecified_type Polynomial;
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// \name Functions
|
||||
/// The following functions are needed to construct cone-based spanners.
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
This function should return the k-th real root of an univariate polynomial, which is defined
|
||||
by the iterator range. It is needed in calculating cone boundaries exactly.
|
||||
It is not needed if the cone bounaries are calculated inexactly, which uses
|
||||
sin() and cos() instead.
|
||||
*/
|
||||
NT CGAL::root_of(int k, InputIterator begin, InputIterator end);
|
||||
|
||||
/*!
|
||||
This function should return the square root of the argument `x`.
|
||||
It is defined if the argument type is a model of the `FieldWithSqrt` concept.
|
||||
It is needed in calculating cone boundaries exactly.
|
||||
*/
|
||||
NT CGAL::sqrt(const NT & x);
|
||||
|
||||
/*
|
||||
This function should compute the sine value of arg (measured in radians).
|
||||
It is needed in calculating cone boundaries inexactly.
|
||||
long double sin( long double arg );
|
||||
|
||||
This function should compute the cosine value of arg (measured in radians).
|
||||
It is needed in calculating cone boundaries inexactly.
|
||||
long double cos( long double arg );
|
||||
*/
|
||||
|
||||
/*!
|
||||
This function should return the bisector of the two lines l1 and l2.
|
||||
And the bisector should have the direction of the vector which is the sum of
|
||||
the normalized directions of the two lines.
|
||||
This function requires that Kernel::RT supports the sqrt() operation.
|
||||
It is needed in constructing Theta graphs, not in constructing Yao graphs.
|
||||
*/
|
||||
CGAL::Line_2<Kernel> CGAL::bisector(const CGAL::Line_2<Kernel> & l1,
|
||||
const CGAL::Line_2<Kernel> & l2);
|
||||
|
||||
/*!
|
||||
This function should return CGAL::LARGER iff the signed distance of p and l
|
||||
is larger than the signed distance of q and l, CGAL::SMALLER, iff it is smaller,
|
||||
and CGAL::EQUAL iff both are equal.
|
||||
It is needed in sorting the points on the plane based on a certain direction.
|
||||
*/
|
||||
Comparison_result CGAL::compare_signed_distance_to_line(
|
||||
const CGAL::Line_2<Kernel> &l,
|
||||
const CGAL::Point_2<Kernel> &p,
|
||||
const CGAL::Point_2<Kernel> &q);
|
||||
/// @}
|
||||
|
||||
}; /* end ConeBasedSpannerTraits */
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/*!
|
||||
\ingroup PkgConeBasedSpannersConcepts
|
||||
\cgalConcept
|
||||
|
||||
The concept `ConstructConeBasedSpanner_2` describes the set of requirements to be fulfilled by any functor class that
|
||||
constructs a cone based spanner, such as a Theta graph and a Yao graph, etc.
|
||||
|
||||
\cgalHasModel `CGAL::Construct_theta_graph_2`
|
||||
\cgalHasModel `CGAL::Construct_yao_graph_2`
|
||||
|
||||
*/
|
||||
template <typename Kernel_, typename Graph_>
|
||||
class ConstructConeBasedSpanner_2 {
|
||||
public:
|
||||
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*! The CGAL kernel type used by the functor. If this parameter is
|
||||
`CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt`,
|
||||
the graph will be constructed exactly; otherwise, inexactly using an approximate PI=3.1415...
|
||||
This kernel type also decides other types such as Kernel_::Point_2, Kernel_::Direction_2, etc.
|
||||
*/
|
||||
typedef Kernel_ kernel_type;
|
||||
|
||||
/*! The graph type to store the constructed cone based spanner. It should be a model of
|
||||
both concepts MutableGraph and VertexAndEdgeListGraph in BGL. Of the two graph classes provided
|
||||
in BGL: `adjacency_list` and `adjacency_matrix`, only `adjacency_list` is such a model.
|
||||
So please use `adjacency_list` to be your graph type. Note that there are seven template parameters for
|
||||
`boost::adjacency_list`: `OutEdgeList`, `VertexList`, `Directed`, `VertexProperties`, `EdgeProperties`,
|
||||
`GraphProperties`, `EdgeList`, of which we only require the `VertexProperties` be `CGAL::Point_2`,
|
||||
while other parameters can be chosen freely. Here `Point_2` is passed directly as bundled properties
|
||||
to `adjacency_list` because this makes our implementation much more straightforward than using property maps.
|
||||
For detailed information about bundled properties, please refer to
|
||||
http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/bundles.html.
|
||||
If more properties for vertices are needed, they can be added later as external properties using
|
||||
property maps.
|
||||
*/
|
||||
typedef Graph_ graph_type;
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// \name Creation
|
||||
/// @{
|
||||
|
||||
/*! \brief Constructor.
|
||||
|
||||
\param k Number of cones to divide the plane
|
||||
\param initial_direction A direction denoting one of the rays dividing the
|
||||
cones. This allows arbitary rotations of the rays that divide
|
||||
the plane. (default: positive x-axis)
|
||||
*/
|
||||
Construct_spanner_2(unsigned int k, Direction_2 initial_direction = Direction_2(1,0) );
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Operator
|
||||
/// @{
|
||||
|
||||
/*! \brief Operator () to construct a cone based spanner.
|
||||
*
|
||||
* This operator implements the algorithm to build the spanner.
|
||||
*
|
||||
* \tparam PointInputIterator This template parameter is to give the application developer freedom
|
||||
* in choosing whichever Iterator he/she will use to input the coordinates of the points.
|
||||
* If omitted, the type of the Iterator can be inferred from the arguments passed to the
|
||||
* operator().
|
||||
*
|
||||
* \param[in] start An iterator pointing to the first point (vertex).
|
||||
* \param[in] end An iterator pointing to the place that passes the last point.
|
||||
* \param[out] g The constructed graph object.
|
||||
*/
|
||||
template <typename PointInputIterator>
|
||||
Graph_& operator()(const PointInputIterator& start,
|
||||
const PointInputIterator& end,
|
||||
Graph_& g);
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Member Access Functions
|
||||
/// @{
|
||||
|
||||
/*! \brief returns the number of cones in this graph.
|
||||
*/
|
||||
const unsigned int number_of_cones() const;
|
||||
|
||||
/*! \brief returns the vector of the directions of the rays dividing the plane.
|
||||
*/
|
||||
const std::vector<Direction_2>& directions() const;
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end ConstructConeBasedSpanner_2 */
|
||||
|
||||
|
|
@ -0,0 +1,366 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\mainpage User Manual
|
||||
\anchor Chapter_ConeBasedSpanners
|
||||
|
||||
\cgalAutoToc
|
||||
\author Weisheng Si and Quincy Tse
|
||||
|
||||
\section sec_CBS_Introduction Introduction
|
||||
|
||||
This chapter describes the package for constructing two kinds of cone-based spanners:
|
||||
Yao graph and Theta graph, given a set of vertices on the plane.
|
||||
Both exact and inexact constructions are supported.
|
||||
In exact construction, the cone boundaries are calculated using roots of polynomials,
|
||||
which achieves the exactness by avoiding using \f$ \pi \f$ in the computation.
|
||||
In inexact construction, the cone boundaries are calculated with an approximate
|
||||
\f$ \pi \f$ value, which uses the constant `CGAL_PI` defined in \cgal and is still accurate
|
||||
enough for most applications.
|
||||
Moreover, for visualization purpose, this chapter describes a global function
|
||||
that, given a constructed graph as input, can generate the data and script files for Gnuplot
|
||||
to plot that graph.
|
||||
|
||||
\section sec_CBS_mydefinitions Definitions
|
||||
|
||||
This section gives detailed definitions of Yao graph and Theta graph, which are followed
|
||||
in our implementation. In particular, because this package supports constructing Yao graph
|
||||
and Theta graph exactly, we need to be clear on which cone a cone boundary belongs to.
|
||||
The definitions presented here clarify on this.
|
||||
|
||||
Given a set \f$V\f$ of vertices on the plane, the directed Yao Graph with an integer
|
||||
parameter \f$k (k > 1)\f$ on \f$V\f$ is obtained as follows. For each vertex \f$u \in V\f$,
|
||||
starting from a given direction (e.g., the direction of positive \f$x\f$-axis),
|
||||
draw \f$k\f$ equally-spaced rays \f$l_0\f$, \f$l_1\f$, ..., \f$l_{k-1}\f$ originating
|
||||
from \f$u\f$ in counterclockwise order (see \cgalFigureRef{f-y5} (a)).
|
||||
These rays divide the plane into \f$k\f$ cones of angle \f$2\pi/k\f$,
|
||||
denoted by \f$ c(u, 0), c(u, 1), ..., c(u, k-1)\f$ respectively in counterclockwise order.
|
||||
To avoid overlapping at boundaries, it is stipulated here that the area of \f$ c(u, i)\f$,
|
||||
where \f$ i=0, \ldots, k-1\f$, includes the ray \f$l_{i}\f$ but excludes the ray \f$l_{(i+1)\% k}\f$.
|
||||
In each cone of \f$u\f$, draw a directed edge from \f$u\f$ to its closest vertex by
|
||||
Euclidean distance in that cone. Ties are broken arbitrarily. These directed edges will form the
|
||||
edge set of the directed Yao graph on \f$V\f$. The undirected Yao Graph on \f$V\f$ is obtained by
|
||||
ignoring the directions of the edges. Note that if both edge \f$uv\f$ and \f$vu\f$ are in the
|
||||
directed Yao graph, only one edge \f$uv\f$ exists in the undirected Yao graph.
|
||||
\cgalFigureRef{f-y5} (b) gives an example of Yao graph with \f$k=5\f$.
|
||||
|
||||
\cgalFigureBegin{f-y5, Example-Y5.jpg}
|
||||
Cones and an example of Yao Graph with \f$k=5\f$.
|
||||
\cgalFigureEnd
|
||||
|
||||
Similar to Yao graph, the directed or undirected Theta Graph is also obtained by letting each
|
||||
vertex \f$u \in V\f$ select a 'closest' vertex in each of its cones to have an edge.
|
||||
The only difference is that 'closest' in Theta Graph means the smallest projection distance
|
||||
onto the bisector of that cone, not the direct Euclidean distance. For instance,
|
||||
in \cgalFigureRef{f-theta}, vertex \f$u\f$'s 'closest' vertex will be vertex \f$b\f$.
|
||||
|
||||
\cgalFigureBegin{f-theta, BisectorInThetaGraph.jpg}
|
||||
The bisector in a cone of a Theta Graph.
|
||||
\cgalFigureEnd
|
||||
|
||||
\section sec_CBS_design Software Design
|
||||
This package provides the following template functors:
|
||||
|
||||
- `CGAL::Compute_cone_boundaries_2`: The functor for computing the directions of cone boundaries
|
||||
given a cone number and an initial direction.
|
||||
- `CGAL::Construct_theta_graph_2`: The functor for constructing Theta graphs given a set of vertices
|
||||
on the plane.
|
||||
- `CGAL::Construct_yao_graph_2`: The functor for constructing Yao graphs given a set of vertices
|
||||
on the plane.
|
||||
|
||||
In addition to the these functors, for visualizing the constructed graphs, this package provides a global function
|
||||
called `CGAL::gnuplot_output_2()` to output a `boost::adjacency_list` data structure to Gnuplot data and script files.
|
||||
Below, we detail the design and the usage of the above functors and function.
|
||||
|
||||
\subsection subsec_CBS_cone Functor CGAL::Compute_cone_boundaries_2
|
||||
|
||||
This functor has the following definition and is a model of the `ComputeConeBoundaries_2` concept.
|
||||
|
||||
\code{.cpp}
|
||||
template <typename Kernel_>
|
||||
class Compute_cone_boundaries_2{}
|
||||
\endcode
|
||||
|
||||
The template parameter `Kernel_` determines whether the cone boundaries are computed
|
||||
exactly or inexactly. If this parameter is `Exact_predicates_exact_constructions_kernel_with_sqrt`,
|
||||
the computation will be done exactly; otherwise, inexactly.
|
||||
The exact computation is implemented based on the fact that
|
||||
when the cone angle \f$ \theta \f$ is in the form of \f$ 2\pi / n \f$,
|
||||
where \f$ n \f$ is a positive integer, \f$ \sin(\theta) \f$ and \f$ \cos(\theta) \f$
|
||||
can be represented exactly by roots of polynomials, thus avoiding using \f$ \pi \f$
|
||||
in the computation. The exact computation requires the number type of either `CORE::Expr`
|
||||
or `leda_real`.
|
||||
In inexact computation, the cone angle \f$ \theta \f$ is
|
||||
simply calculated as \f$ 2\pi/k \f$, where \f$ k \f$ is the number of cones and
|
||||
\f$ \pi \f$ takes the value of the constant `CGAL_PI=3.14159265358979323846`
|
||||
defined in <TT>CGAL/number_type_config.h</TT>.
|
||||
Then, the \f$ \sin(\theta) \f$ and \f$ \cos(\theta) \f$ are calculated.
|
||||
While the inexact computation is done by the general functor
|
||||
definition, the exact computation is done by a specialization of this functor.
|
||||
|
||||
<!--
|
||||
The operator() of this functor is defined as follows:
|
||||
\code{.cpp}
|
||||
void operator()(const unsigned int k,
|
||||
Direction_2& initial_direction,
|
||||
std::vector<Direction_2>& rays)
|
||||
\endcode
|
||||
The parameter `k` is used to give the number of cones, and the
|
||||
parameter `initial_direction` the direction of the ray \f$l_0\f$ as defined in
|
||||
the first section, which allows the cones have arbitrary orientation. The
|
||||
parameter `rays` is used to return the computation results, which stores a vector
|
||||
of directions for the rays from \f$l_0\f$ to \f$l_{k-1}\f$ respectively.
|
||||
-->
|
||||
|
||||
This functor is currently used by the functors
|
||||
`CGAL::Construct_theta_graph_2` and `CGAL::Construct_yao_graph_2`
|
||||
in constructing Theta and Yao graphs. This functor can also be used in other applications where the plane needs to be
|
||||
divided into equally-angled cones. For how to use this functor to compute cone boundaries in writing an application,
|
||||
please refer to Section \ref sec_CBS_examples.
|
||||
|
||||
\subsection subsec_CBS_theta Functor CGAL::Construct_theta_graph_2
|
||||
|
||||
This functor has the following definition and is a model of the `ConstructConeBasedSpanner_2` concept.
|
||||
|
||||
\code{.cpp}
|
||||
template <typename Kernel_, typename Graph_>
|
||||
class Construct_theta_graph_2{}
|
||||
\endcode
|
||||
|
||||
The template parameter `Kernel_` specifies the \cgal kernel to be used by this functor.
|
||||
If this parameter is `CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt`,
|
||||
this functor will call the corresponding specialization of
|
||||
`CGAL::Compute_cone_boundaries_2` to compute the cone boundaries exactly and then
|
||||
add edges in each cone. If not, this functor will call the general
|
||||
`CGAL::Compute_cone_boundaries_2` to compute the cone boundaries inexactly and then
|
||||
add edges. In the stage of adding edges, since all calculations use the predicates or construction
|
||||
functions provided by CGAL, the type given in `Kernel_` actually determines overall whether the
|
||||
Theta graph will be constructed exactly. The template parameter
|
||||
`Graph_` specifies the graph type used to store the constructed graph.
|
||||
Our package requires it to be
|
||||
<a href="http://www.boost.org/libs/graph/doc/adjacency_list.html">boost::adjacency_list</a>
|
||||
from the Boost Graph Library (BGL).
|
||||
The advantage of using `boost::adjacency_list` is that it provides convenience
|
||||
to the further processing of the constructed graphs, since BGL includes most common graph algorithms.
|
||||
Note that BGL altogether provides two template classes for representing graphs:
|
||||
`boost::adjacency_list` and `boost::adjacency_matrix`, with the former suitable for
|
||||
sparse graphs and the latter suitable for dense graphs. While cone-based spanners
|
||||
are sparse graphs and the interfaces provided by `adjacency_list` and `adjaceny_matrix`
|
||||
are different, our package only supports `boost::adjacency_list`.
|
||||
|
||||
Note that there are seven template parameters for `adjacency_list` in BGL: `OutEdgeList`, `VertexList`,
|
||||
`Directed`, `VertexProperties`, `EdgeProperties`, `GraphProperties`, `EdgeList`,
|
||||
of which we require `VertexProperties` to be `CGAL::Point_2`,
|
||||
and other parameters can be chosen freely. And the kernel type for the `CGAL::Point_2` is
|
||||
decided by the template parameter `Kernel_`.
|
||||
Also note that, here we make `Point_2` passed
|
||||
directly as bundled properties to `adjacency_list`, because this makes our implementation of this
|
||||
package more straightforward than using property maps from BGL. For detailed information about
|
||||
bundled properties, please refer to http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/bundles.html.
|
||||
If you want more properties other than `Point_2` for vertices, you can still
|
||||
construct external properties by using property maps.
|
||||
|
||||
In constructing Theta graphs, this functor uses the algorithm from
|
||||
Chapter 4 of the book by Narasimhan and Smid \cgalCite{cgal:ns-gsn-07}.
|
||||
Basically, it is a sweep line algorithm and uses a
|
||||
balanced search tree to store the vertices that have already been scanned.
|
||||
It has the complexity of \f$O(n \log n)\f$, where \f$n\f$ is the number of vertices in the plane.
|
||||
This complexity has been proved to be optimal.
|
||||
|
||||
For more details on how to use this `CGAL::Construct_theta_graph_2` functor to write an application to build Theta graphs,
|
||||
please refer to Section \ref sec_CBS_examples.
|
||||
|
||||
\subsection subsec_CBS_yao Functor CGAL::Construct_yao_graph_2
|
||||
|
||||
With a similar definition (see below) to `CGAL::Construct_theta_graph_2`, this functor
|
||||
is also a model of the `ConstructConeBasedSpanner_2` concept.
|
||||
|
||||
\code{.cpp}
|
||||
template <typename Kernel_, typename Graph_>
|
||||
class Construct_yao_graph_2{}
|
||||
\endcode
|
||||
|
||||
The way of using these two template parameters is the same as that of `CGAL::Construct_theta_graph_2`,
|
||||
so please refer to the previous subsection for the details. We note here that construction algorithm for Yao graph
|
||||
is a slight adaptation of the algorithm for constructing Theta graph, having a complexity of \f$O(n^2)\f$.
|
||||
The increase of complexity in this adaptation is because in constructing Theta graph,
|
||||
the searching of the 'closest' node by projection distance can be done by a balanced search tree,
|
||||
but in constructing Yao graph, the searching of the 'closest' node by Euclidean distance cannot be
|
||||
done by a balanced search tree.
|
||||
|
||||
Note that an optimal algorithm for constructing Yao graph with a complexity of \f$O(n \log n)\f$ is
|
||||
described in \cgalCite{cgal:cht-oacov-90}. However, this algorithm is much more complex to implement than
|
||||
the current algorithm implemented, and it can hardly reuse the codes for constructing Theta graphs,
|
||||
so it is not implemented in this package right now.
|
||||
|
||||
\subsection subsec_CBS_gnuplot Global function CGAL::gnuplot_output_2()
|
||||
|
||||
This package also implements a template function `CGAL::gnuplot_output_2()`, which will read a
|
||||
`boost::adjacency_list` object and generate two files used by Gnuplot to visualize the graph stored
|
||||
in the `boost::adjacency_list` object. This template function has the following definition:
|
||||
|
||||
\code{.cpp}
|
||||
template <typename Graph_>
|
||||
void gnuplot_output_2(const Graph_& g, const std::string& prefix);
|
||||
\endcode
|
||||
|
||||
The template parameter `Graph_` specifies the type of the graph to be plotted. For this function to work,
|
||||
the graph type must be `boost::adjacency_list` with `CGAL::Point_2` as the `VertexProperties`.
|
||||
As for the two arguments to the function, `g` gives the graph to be plotted, and `prefix` gives the
|
||||
prefix for the names of the files generated by the function. Specifically, this function will
|
||||
generate the following two files:
|
||||
- A data file named `prefix.v` that contains the \f$(x, y)\f$-coordinates
|
||||
of each vertex. To be read by Gnuplot,
|
||||
the \f$(x, y)\f$-coordinates are written into the data file with decimal format,
|
||||
no matter which number type is used in the \cgal kernel.
|
||||
This is achieved by calling `CGAL::to_double()` on \f$x\f$ or \f$y\f$ coordinate before outputing them.
|
||||
- A Gnuplot script file named `prefix.plt` to be loaded by Gnuplot to plot the set of vertices and the set of edges.
|
||||
The set of vertices is read from the above data file and the set of edges are included in the script file
|
||||
with the syntax `set arrow from x1, y1 to x2, y2`.
|
||||
|
||||
For details on how to use this function to generate Gnuplot files, please refer to Section \ref sec_CBS_examples.
|
||||
|
||||
\section sec_CBS_examples Examples
|
||||
|
||||
\subsection CBS_coneboundaries Computing cone boundaries exactly or inexactly
|
||||
|
||||
The following example, 'compute_cones.cpp', shows how to compute the directions of the cone boundaries
|
||||
exactly given the cone number and the initial direction. This example basically consists of the following steps:
|
||||
|
||||
1. Define `CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt` as the kernel type
|
||||
to compute the cone boundaries exactly.
|
||||
2. Construct a `CGAL::Compute_cone_boundaries_2` object named `cones` with the above kernel
|
||||
as the template parameter. Note that since the functor `CGAL::Compute_cone_boundaries_2` has no
|
||||
member variables but member types and functions, its constructor needs no arguments.
|
||||
3. Initialize a vector of `CGAL::Direction_2` named `rays` to store the computed results.
|
||||
4. Use `cones` to compute the cone boundaries by passing the cone number, the initial direction
|
||||
and the beginning iterator of `rays` to it.
|
||||
5. Output the computed results.
|
||||
|
||||
\cgalExample{Cone_spanners_2/compute_cones.cpp}
|
||||
|
||||
Note that, in this example, for any k<=28, the computation can be done successfully; for any k>28, the computation
|
||||
cannot be completed because `CORE::Expr`, which we use as the number type for the exact kernel,
|
||||
exceeds its limit. It seems that k<=28 will suffice for most applications. Also, if inexact computation
|
||||
is used, the computation will be successful for any k>1, and much quicker than exact computation.
|
||||
We also note here that we don't experiment with `leda_real`.
|
||||
|
||||
As a final note, to compute the cone boundaries inexactly, just define the `Kernel` to be
|
||||
`CGAL::Exact_predicates_inexact_constructions_kernel` in the above example.
|
||||
|
||||
\subsection CBS_construction Constructing graphs exactly or inexactly and generating Gnuplot files
|
||||
|
||||
The following example, 'theta_io.cpp', shows how to construct Theta graphs exactly and generate Gnuplot files.
|
||||
This example basically consists of the following steps:
|
||||
1. Define `CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt` as the kernel type
|
||||
to construct the graph exactly.
|
||||
2. Define the graph type to store the constructed graph.
|
||||
3. Construct a `CGAL::Construct_theta_graph_2` object named `theta` with the number of cones and the initial direction
|
||||
as constructor arguments.
|
||||
4. Construct a graph object `g` to store the constructed graph.
|
||||
5. Use `theta` to construct the Theta graph by passing the input vertices and `g` to it.
|
||||
6. Generate Gnuplot files for plotting the construct graph.
|
||||
|
||||
\cgalExample{Cone_spanners_2/theta_io.cpp}
|
||||
|
||||
To construct Theta graphs inexactly, just define the `Kernel` to be
|
||||
`CGAL::Exact_predicates_inexact_constructions_kernel` in the above example. And the way of
|
||||
constructing Yao graphs exactly or inexactly is the same as that of constructing
|
||||
Theta graphs, just replacing the functor `CGAL::Construct_theta_graph_2` by the functor
|
||||
`CGAL::Construct_yao_graph_2`.
|
||||
|
||||
Note that, for Theta graph, the `Kernel` defined must support the `CGAL::sqrt()` operation.
|
||||
This is required by the `CGAL::bisector()` function, which is used to calculate the angle
|
||||
bisector of a cone. For instance, the compiler will complain if
|
||||
`CGAL::Exact_predicates_exact_constructions_kernel` (not supporting `CGAL::sqrt()`)
|
||||
is defined as the kernel, but `CGAL::Exact_predicates_inexact_constructions_kernel` will be fine
|
||||
since it supports `CGAL::sqrt()`. For Yao graph, there is no such restriction, since its construction
|
||||
does not need `CGAL::sqrt()`.
|
||||
|
||||
After compiling 'theta_io.cpp', execute the executable `theta_io` to construct a Theta graph with 4 cones
|
||||
on a set of 20 vertices (which is given in the file `data/n20.cin`):
|
||||
|
||||
\code{.txt}
|
||||
$ ./theta_io 4 data/n20.cin
|
||||
\endcode
|
||||
|
||||
The following two files will be generated for Gnuplot:
|
||||
- `t4n20.v`: This file contains the \f$(x, y)\f$-coordinates of the 20 vertices.
|
||||
- `t4n20.plt`: This is the script to be loaded by Gnuplot. It will read
|
||||
`t4n20.v` to plot the vertices. It will also plot all the edges,
|
||||
which are included in this script itself.
|
||||
|
||||
\cgalFigureRef{f-t4} shows the Theta graph plotted when the above `t4n20.plt` is loaded by Gnuplot.
|
||||
|
||||
\cgalFigureBegin{f-t4, t4n20.jpg}
|
||||
A directed Theta graph of 20 vertices with \f$k=4\f$.
|
||||
\cgalFigureEnd
|
||||
|
||||
\subsection CBS_diff_exact Exact construction can make a difference
|
||||
|
||||
This subsection gives an example vertex set on which the exact construction provided
|
||||
in this package can produce the correct Theta graph while the inexact construction cannot.
|
||||
|
||||
This vertex set, given in the file `examples/data/n9.cin`, consists of 9 vertices
|
||||
with the following \f$(x, y)\f$-coordinates:
|
||||
\code{.txt}
|
||||
0.000000 0.000000
|
||||
0.000000 1.000000
|
||||
0.000000 2.000000
|
||||
1.000000 0.000000
|
||||
1.000000 1.000000
|
||||
1.000000 2.000000
|
||||
2.000000 0.000000
|
||||
2.000000 1.000000
|
||||
2.000000 2.000000
|
||||
\endcode
|
||||
|
||||
If we construct the directed Theta graph on this vertex set with \f$k=4\f$ and its cone boundaries
|
||||
on the \f$x\f$ and \f$y\f$ axis, the exact construction will produce the Theta graph shown in
|
||||
\cgalFigureRef{f-t4n9exact}. Based on our definition on Theta graph presented in the
|
||||
Section \ref sec_CBS_mydefinitions, we can verify that the Theta graph in \cgalFigureRef{f-t4n9exact}
|
||||
is correctly constructed.
|
||||
|
||||
\cgalFigureBegin{f-t4n9exact, t4n9exact.jpg}
|
||||
The correct Theta graph produced by the exact construction.
|
||||
\cgalFigureEnd
|
||||
|
||||
On the other hand, the inexact construction will produce the Theta graph
|
||||
depicted in \cgalFigureRef{f-t4n9inexact}. We can see that this Theta graph is not constructed
|
||||
correctly, since the inexact construction will make wrong decisions on whether
|
||||
those vetices on the cone boundaries belong to a certain cone.
|
||||
|
||||
\cgalFigureBegin{f-t4n9inexact, t4n9inexact.jpg}
|
||||
The incorrect Theta graph produced by the inexact construction.
|
||||
\cgalFigureEnd
|
||||
|
||||
This example demonstrates that the exact construction capability
|
||||
provided by this package can be very
|
||||
valuable if it is a strict requirement that graphs be constructed correctly.
|
||||
|
||||
\subsection CBS_using_BGL Using algorithms from BGL
|
||||
|
||||
The following example, 'dijkstra_theta.cpp', shows how to call algorithms from BGL to do further processing
|
||||
after the graphs are constructed. Since the constructed Theta or Yao graphs are stored in the class
|
||||
`boost::adjacency_list`, it is convenient to apply BGL algorithms into the constructed graphs.
|
||||
Specifically, this example constructs a Theta graph first and then calculates
|
||||
the shortest paths on this graph by calling the Dijkstra's algorithm from BGL.
|
||||
It mainly consists of the following steps:
|
||||
|
||||
1. Define `CGAL::Exact_predicates_inexact_constructions_kernel_with_sqrt` as the kernel type
|
||||
to construct the graph inexactly.
|
||||
2. Define a structure named `Edge_property` for storing the Euclidean length of each edge,
|
||||
which is needed by the Dijkstra's algorithm.
|
||||
3. Define the graph type to store the constructed graph, passing `Edge_property` as a template
|
||||
parameter to the graph type `boost::adjacency_list`.
|
||||
4. Construct a `CGAL::Construct_theta_graph_2` object named `theta`.
|
||||
5. Construct a graph object `g` to store the constructed graph.
|
||||
6. Use `theta` to construct the Theta graph by passing the input vertices and `g` to it.
|
||||
7. After `g` is constructed, calculate the Euclidean length of each edge in `g`.
|
||||
8. Calculate the shortest distances from `v0` to other vertices by calling the function
|
||||
`dijkstra_shortest_paths()` from BGL.
|
||||
|
||||
\cgalExample{Cone_spanners_2/dijkstra_theta.cpp}
|
||||
|
||||
*/
|
||||
} /* namespace CGAL */
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
@INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS}
|
||||
PROJECT_NAME = "CGAL ${CGAL_CREATED_VERSION_NUM} - Cone-Based Spanners"
|
||||
INPUT = ${CMAKE_SOURCE_DIR}/Cone_spanners_2/doc/Cone_spanners_2/ \
|
||||
${CMAKE_SOURCE_DIR}/Cone_spanners_2/include
|
||||
EXCLUDE = ${CMAKE_SOURCE_DIR}/Cone_spanners_2/include/CGAL/Cone_spanners_2
|
||||
EXTRACT_ALL = NO
|
||||
HIDE_UNDOC_CLASSES = YES
|
||||
HIDE_UNDOC_MEMBERS = YES
|
||||
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
// PRETTY PACKAGE NAME should equal the project title in Doxyfile.in
|
||||
|
||||
/// \defgroup PkgConeBasedSpanners Cone-Based Spanners Reference
|
||||
/// \defgroup PkgConeBasedSpannersConcepts Concepts
|
||||
/// \ingroup PkgConeBasedSpanners
|
||||
|
||||
/// \defgroup PkgConeBasedSpannersTraitsClasses Traits Classes
|
||||
/// \ingroup PkgConeBasedSpanners
|
||||
|
||||
/// \defgroup PkgConeBasedSpannersMiscellaneous Miscellaneous
|
||||
/// \ingroup PkgConeBasedSpanners
|
||||
|
||||
/*!
|
||||
\addtogroup PkgConeBasedSpanners
|
||||
\todo check generated documentation
|
||||
|
||||
\cgalPkgDescriptionBegin{Cone-Based Spanners,PkgConeBasedSpannersSummary}
|
||||
\cgalPkgPicture{Logo-ConeSpanners.png}
|
||||
|
||||
\cgalPkgSummaryBegin
|
||||
\cgalPkgAuthors{Weisheng Si and Quincy Tse}
|
||||
\cgalPkgDesc{This package provides functors for constructing two kinds of cone-based spanners:
|
||||
Yao graph and Theta graph, given a set of vertices on the plane. Both exact and inexact constructions are
|
||||
supported. In exact construction, the cone boundaries are calculated using the roots of polynomials,
|
||||
thus avoiding the use of \f$ \pi \f$, which cannot be represented exactly.
|
||||
In inexact construction, the cone boundaries are calculated using the approximate \f$ \pi \f$
|
||||
value defined in \cgal, which is still accurate enough for most applications.
|
||||
Moreover, for visualization purpose, this package provides a global function to
|
||||
generate the data and script files used by Gnuplot to plot the constructed graphs. }
|
||||
\cgalPkgManuals{Chapter_ConeBasedSpanners,PkgConeBasedSpanners}
|
||||
\cgalPkgSummaryEnd
|
||||
|
||||
\cgalPkgShortInfoBegin
|
||||
\cgalPkgSince{X.X}
|
||||
\cgalPkgDependsOn{\ref PkgDEPENDENCY}
|
||||
\cgalPkgBib{cgal:st-cbs}
|
||||
\cgalPkgLicense{\ref licensesGPL "GPL"}
|
||||
\cgalPkgDemo{DEMO 1,demo1.zip}
|
||||
\cgalPkgShortInfoEnd
|
||||
|
||||
\cgalPkgDescriptionEnd
|
||||
|
||||
\cgalClassifedRefPages
|
||||
|
||||
## Concepts ##
|
||||
- `ConeBasedSpannerTraits`
|
||||
- `ComputeConeBoundaries_2`
|
||||
- `ConstructConeBasedSpanner_2`
|
||||
|
||||
## Functors ##
|
||||
- `CGAL::Compute_cone_boundaries_2`
|
||||
- `CGAL::Construct_yao_graph_2`
|
||||
- `CGAL::Construct_theta_graph_2`
|
||||
|
||||
## Functions to generate Gnuplot files ##
|
||||
|
||||
- `CGAL::gnuplot_output_2()`
|
||||
|
||||
*/
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
Manual
|
||||
Kernel_23
|
||||
STL_Extension
|
||||
Algebraic_foundations
|
||||
Circulator
|
||||
Stream_support
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
/*!
|
||||
\example Cone_spanners_2/compute_cones.cpp
|
||||
\example Cone_spanners_2/theta_io.cpp
|
||||
\example Cone_spanners_2/dijkstra_theta.cpp
|
||||
*/
|
||||
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 9.2 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
|
@ -0,0 +1,7 @@
|
|||
In the example cpp files, the function std::to_string() is used. Because this function is
|
||||
available since c++0x, please turn on '-std=gnu++0x' or '-std=c++0x' to compile. A recommended way
|
||||
is to add the following codes into your 'CMakeLists.txt' file.
|
||||
|
||||
if(UNIX)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
|
||||
endif()
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/** @file compute_cones.cpp
|
||||
* An example application that computes the cone boundariess given the number of cones
|
||||
* and the initial direction.
|
||||
*
|
||||
* Authors: Weisheng Si and Quincy Tse, University of Western Sydney
|
||||
*/
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel_with_sqrt.h>
|
||||
#include <CGAL/Compute_cone_boundaries_2.h>
|
||||
|
||||
// select the kernel type
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt Kernel;
|
||||
typedef Kernel::Point_2 Point_2;
|
||||
typedef Kernel::Direction_2 Direction_2;
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
|
||||
if (argc < 2) {
|
||||
std::cout << "Usage: " << argv[0] << " <no. of cones> [<direction-x> <direction-y>]" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned long k = atol(argv[1]);
|
||||
if (k<2) {
|
||||
std::cout << "The number of cones should be larger than 1!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Direction_2 initial_direction;
|
||||
if (argc == 2)
|
||||
initial_direction = Direction_2(1, 0); // default initial_direction
|
||||
else if (argc == 4)
|
||||
initial_direction = Direction_2(atof(argv[2]), atof(argv[3]));
|
||||
else {
|
||||
std::cout << "Usage: " << argv[0] << " <no. of cones> [<direction-x> <direction-y>]" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// construct the functor
|
||||
CGAL::Compute_cone_boundaries_2<Kernel> cones;
|
||||
// create the vector rays to store the results
|
||||
std::vector<Direction_2> rays(k);
|
||||
// compute the cone boundaries and store them in rays
|
||||
cones(k, initial_direction, rays.begin());
|
||||
|
||||
// display the computed rays, starting from the initial direction, ccw order
|
||||
for (int i=0; i<k; i++)
|
||||
std::cout << "Ray " << i << ": " << rays[i] << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
97.6188 489.679
|
||||
673.018 672.436
|
||||
67.6374 539.91
|
||||
40.0488 138.312
|
||||
110.286 659.128
|
||||
399.326 677.844
|
||||
585.28 614.301
|
||||
880.102 831.773
|
||||
752.166 840.363
|
||||
437.925 993.181
|
||||
120.746 215.884
|
||||
32.6144 584.674
|
||||
845.06 328.004
|
||||
656.569 774.867
|
||||
843.833 334.36
|
||||
368.169 941.452
|
||||
824.039 41.1866
|
||||
613.888 891.676
|
||||
581.096 653.936
|
||||
29.9877 691.382
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
0.000000 0.000000
|
||||
0.000000 1.000000
|
||||
0.000000 2.000000
|
||||
1.000000 0.000000
|
||||
1.000000 1.000000
|
||||
1.000000 2.000000
|
||||
2.000000 0.000000
|
||||
2.000000 1.000000
|
||||
2.000000 2.000000
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/** @file dijkstra_theta.cpp
|
||||
* An example application that constructs Theta graph first and then calculates
|
||||
* the shortest paths on this graph by calling the Dijkstra's algorithm from BGL.
|
||||
*
|
||||
* Authors: Weisheng Si and Quincy Tse, University of Western Sydney
|
||||
*/
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost/property_map/property_map.hpp>
|
||||
#include <boost/graph/dijkstra_shortest_paths.hpp>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Construct_theta_graph_2.h>
|
||||
|
||||
using namespace boost;
|
||||
|
||||
// select the kernel type
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
typedef Kernel::Point_2 Point_2;
|
||||
typedef Kernel::Direction_2 Direction_2;
|
||||
|
||||
/* define the struct for edge property */
|
||||
struct Edge_property {
|
||||
/* record the Euclidean length of the edge */
|
||||
double euclidean_length;
|
||||
};
|
||||
|
||||
// define the Graph (e.g., to be undirected,
|
||||
// and to use Edge_property as the edge property, etc.)
|
||||
typedef adjacency_list<listS, vecS, undirectedS, Point_2, Edge_property> Graph;
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
|
||||
if (argc != 3) {
|
||||
std::cout << "Usage: " << argv[0] << " <no. of cones> <input filename>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
unsigned long k = atol(argv[1]);
|
||||
if (k<2) {
|
||||
std::cout << "The number of cones should be larger than 1!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
// open the file containing the vertex list
|
||||
std::ifstream inf(argv[2]);
|
||||
if (!inf) {
|
||||
std::cout << "Cannot open file " << argv[1] << "!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// iterators for reading the vertex list file
|
||||
std::istream_iterator< Point_2 > input_begin( inf );
|
||||
std::istream_iterator< Point_2 > input_end;
|
||||
|
||||
// initialize the functor
|
||||
// If the initial direction is omitted, the x-axis will be used
|
||||
CGAL::Construct_theta_graph_2<Kernel, Graph> theta(k);
|
||||
// create an adjacency_list object
|
||||
Graph g;
|
||||
// construct the theta graph on the vertex list
|
||||
theta(input_begin, input_end, g);
|
||||
|
||||
// select a source vertex for dijkstra's algorithm
|
||||
graph_traits<Graph>::vertex_descriptor v0;
|
||||
v0 = vertex(0, g);
|
||||
std::cout << "The source vertex is: " << g[v0] << std::endl;
|
||||
|
||||
// get the vertex index map
|
||||
property_map<Graph, vertex_index_t>::type indexmap = get(vertex_index, g);
|
||||
std::cout << "The index of source vertex is: " << get(indexmap, v0) << std::endl;
|
||||
|
||||
// calculating edge length in Euclidean distance and store them in the edge property
|
||||
graph_traits<Graph>::edge_iterator ei, ei_end;
|
||||
for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
|
||||
graph_traits<Graph>::edge_descriptor e = *ei;
|
||||
graph_traits<Graph>::vertex_descriptor u = source(e, g);
|
||||
graph_traits<Graph>::vertex_descriptor v = target(e, g);
|
||||
const Point_2& pu = g[u];
|
||||
const Point_2& pv = g[v];
|
||||
|
||||
double dist = CGAL::sqrt( CGAL::to_double((pu.x()-pv.x())*(pu.x()-pv.x()) + (pu.y()-pv.y())*(pu.y()-pv.y())) );
|
||||
g[e].euclidean_length = dist;
|
||||
std::cout << "Edge (" << g[u] << ", " << g[v] << "): " << dist << std::endl;
|
||||
}
|
||||
|
||||
// calculating the distances from v0 to other vertices
|
||||
unsigned int n = num_vertices(g);
|
||||
// vector for storing the results
|
||||
std::vector<double> distances(n);
|
||||
// Calling the Dijkstra's algorithm implementation from boost.
|
||||
// For details, pls read the documentation from BGL
|
||||
dijkstra_shortest_paths(g,
|
||||
v0,
|
||||
weight_map(get(&Edge_property::euclidean_length, g)).
|
||||
distance_map(make_iterator_property_map(distances.begin(), indexmap))
|
||||
);
|
||||
|
||||
std::cout << "distances are:" << std::endl;
|
||||
for (unsigned int i=0; i < n; ++i) {
|
||||
std::cout << "distances[" << i << "] = " << distances[i] << ", (x,y)=" << g[vertex(i, g)];
|
||||
std::cout << " at Vertex " << i << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/** @file theta_io.cpp
|
||||
* An example application that constructs a Theta graph exactly with an input vertex list,
|
||||
* and then generates the Gnuplot files for plotting the Theta graph.
|
||||
*
|
||||
* Authors: Weisheng Si and Quincy Tse, University of Western Sydney
|
||||
*/
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel_with_sqrt.h>
|
||||
#include <CGAL/Construct_theta_graph_2.h>
|
||||
#include <CGAL/gnuplot_output_2.h>
|
||||
|
||||
// select the kernel type
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt Kernel;
|
||||
typedef Kernel::Point_2 Point_2;
|
||||
typedef Kernel::Direction_2 Direction_2;
|
||||
// define the graph type
|
||||
typedef boost::adjacency_list<boost::listS,
|
||||
boost::vecS,
|
||||
boost::directedS,
|
||||
Point_2
|
||||
> Graph;
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
|
||||
if (argc < 3) {
|
||||
std::cout << "Usage: " << argv[0] << " <no. of cones> <input filename> [<direction-x> <direction-y>]" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned long k = atol(argv[1]);
|
||||
if (k<2) {
|
||||
std::cout << "The number of cones should be larger than 1!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// open the file containing the vertex list
|
||||
std::ifstream inf(argv[2]);
|
||||
if (!inf) {
|
||||
std::cout << "Cannot open file " << argv[2] << "!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Direction_2 initial_direction;
|
||||
if (argc == 3)
|
||||
initial_direction = Direction_2(1, 0); // default initial_direction
|
||||
else if (argc == 5)
|
||||
initial_direction = Direction_2(atof(argv[3]), atof(argv[4]));
|
||||
else {
|
||||
std::cout << "Usage: " << argv[0] << " <no. of cones> <input filename> [<direction-x> <direction-y>]" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// iterators for reading the vertex list file
|
||||
std::istream_iterator<Point_2> input_begin( inf );
|
||||
std::istream_iterator<Point_2> input_end;
|
||||
|
||||
// initialize the functor
|
||||
CGAL::Construct_theta_graph_2<Kernel, Graph> theta(k, initial_direction);
|
||||
// create an adjacency_list object
|
||||
Graph g;
|
||||
// construct the theta graph on the vertex list
|
||||
theta(input_begin, input_end, g);
|
||||
|
||||
// obtain the number of vertices in the constructed graph
|
||||
unsigned int n = boost::num_vertices(g);
|
||||
// generate gnuplot files for plotting this graph
|
||||
std::string file_prefix = "t" + std::to_string(k) + "n" + std::to_string(n);
|
||||
CGAL::gnuplot_output_2(g, file_prefix);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
// Copyright (c) 2013-2015 The University of Western Sydney, Australia.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Authors: Weisheng Si, Quincy Tse
|
||||
|
||||
/*! \file Compute_cone_boundaries_2.h
|
||||
*
|
||||
* This header implements the functor for computing the directions of cone boundaries with a given
|
||||
* cone number and a given initial direction either exactly or inexactly.
|
||||
*/
|
||||
|
||||
#ifndef CGAL_COMPUTE_CONE_BOUNDARIES_2_H
|
||||
#define CGAL_COMPUTE_CONE_BOUNDARIES_2_H
|
||||
|
||||
// if leda::real is used, pls modify the following definition
|
||||
#define CGAL_USE_CORE 1
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <CGAL/Polynomial.h>
|
||||
#include <CGAL/number_type_config.h> // CGAL_PI is defined there
|
||||
#include <CGAL/enum.h>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel_with_sqrt.h>
|
||||
#include <CGAL/Aff_transformation_2.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
/*! \ingroup PkgConeBasedSpanners
|
||||
*
|
||||
* \brief The functor for computing the directions of cone boundaries with a given
|
||||
* cone number and a given initial direction.
|
||||
*
|
||||
* This computation can be either inexact by simply dividing an approximate Pi by the cone number
|
||||
* (which is quick), or exact by using roots of polynomials (requiring number types such as `CORE::Expr` or `LEDA::Real`,
|
||||
* which are slow). The inexact computation is done by the general functor definition,
|
||||
* while the exact computation is done by a specialization of this functor.
|
||||
*
|
||||
* \tparam Kernel_ If this parameter is `Exact_predicates_exact_constructions_kernel_with_sqrt`,
|
||||
* the specialization functor will be called; otherwise, the general functor will
|
||||
* be called.
|
||||
*
|
||||
* In the construction of Yao graph and Theta graph implemented by this package,
|
||||
* all predicates and construction functions are from \cgal.
|
||||
* Therefore, if the kernel `Exact_predicates_exact_constructions_kernel_with_sqrt` is used,
|
||||
* the Yao or Theta graph will be constructed exactly, otherwise inexactly.
|
||||
*
|
||||
* Of course, this functor can also be used in other applications where the plane needs to be divided
|
||||
* into equally-angled cones.
|
||||
*
|
||||
* \cgalModels `ComputeConeBoundaries_2`
|
||||
*
|
||||
*/
|
||||
template <typename Kernel_>
|
||||
class Compute_cone_boundaries_2 {
|
||||
|
||||
public:
|
||||
/*! Indicate the type of the \cgal kernel. */
|
||||
typedef Kernel_ Kernel_type;
|
||||
|
||||
private:
|
||||
typedef typename Kernel_::Direction_2 Direction_2;
|
||||
typedef typename Kernel_::Aff_transformation_2 Transformation;
|
||||
|
||||
public:
|
||||
/* No member variables in this class, so a custom constructor is not needed. */
|
||||
// Compute_cone_boundaries_2() {};
|
||||
|
||||
/*! \brief The operator().
|
||||
*
|
||||
* \details The direction of the first ray can be specified by the parameter `initial_direction`,
|
||||
* which allows the first ray to start at any direction.
|
||||
* This operator first places the `initial_direction` at the
|
||||
* position pointed by `result`. Then, it calculates the remaining directions (cone boundaries)
|
||||
* and output them to `result` in the counterclockwise order.
|
||||
* Finally, the past-the-end iterator for the resulting directions is returned.
|
||||
*
|
||||
* \param cone_number The number of cones
|
||||
* \param initial_direction The direction of the first ray
|
||||
* \param result The output iterator
|
||||
*/
|
||||
template<class DirectionOutputIterator>
|
||||
DirectionOutputIterator operator()(const unsigned int cone_number,
|
||||
const Direction_2& initial_direction,
|
||||
DirectionOutputIterator result) {
|
||||
if (cone_number<2) {
|
||||
std::cout << "The number of cones must be larger than 1!" << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
*result++ = initial_direction;
|
||||
|
||||
const double cone_angle = 2*CGAL_PI/cone_number;
|
||||
double sin_value, cos_value;
|
||||
for (unsigned int i = 1; i < cone_number; i++) {
|
||||
sin_value = std::sin(i*cone_angle);
|
||||
cos_value = std::cos(i*cone_angle);
|
||||
Direction_2 ray = Transformation(cos_value, -sin_value, sin_value, cos_value)(initial_direction);
|
||||
*result++ = ray;
|
||||
}
|
||||
|
||||
return result;
|
||||
} // end of operator
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
The specialised functor for computing the directions of cone boundaries exactly
|
||||
with a given cone number and a given initial direction.
|
||||
*/
|
||||
template <>
|
||||
class Compute_cone_boundaries_2<Exact_predicates_exact_constructions_kernel_with_sqrt> {
|
||||
|
||||
public:
|
||||
/* Indicate the type of the cgal kernel. */
|
||||
typedef Exact_predicates_exact_constructions_kernel_with_sqrt Kernel_type;
|
||||
|
||||
private:
|
||||
typedef typename Kernel_type::FT FT;
|
||||
typedef typename Kernel_type::Direction_2 Direction_2;
|
||||
typedef typename Kernel_type::Aff_transformation_2 Transformation;
|
||||
|
||||
public:
|
||||
/* No member variables in this class, so a Constructor is not needed. */
|
||||
// Compute_cone_boundaries_2() {};
|
||||
|
||||
/* The operator().
|
||||
|
||||
The direction of the first ray can be specified by the parameter
|
||||
initial_direction, which allows the first ray to start at any direction.
|
||||
The remaining directions are calculated in counter-clockwise order.
|
||||
|
||||
\param cone_number The number of cones
|
||||
\param initial_direction The direction of the first ray
|
||||
\param result The output iterator
|
||||
*/
|
||||
template<typename DirectionOutputIterator>
|
||||
DirectionOutputIterator operator()(const unsigned int cone_number,
|
||||
const Direction_2& initial_direction,
|
||||
DirectionOutputIterator result) {
|
||||
|
||||
if (cone_number<2) {
|
||||
std::cout << "The number of cones must be larger than 1!" << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
//std::cout << "Specialization is called!" << std::endl;
|
||||
|
||||
// Since CGAL::root_of() gives the k-th smallest root,
|
||||
// here -x is actually used instead of x.
|
||||
// But we want the second largest one with no need to count.
|
||||
Polynomial<FT> x(CGAL::shift(Polynomial<FT>(-1), 1));
|
||||
Polynomial<FT> double_x(2*x);
|
||||
Polynomial<FT> a(1), b(x);
|
||||
for (unsigned int i = 2; i <= cone_number; ++i) {
|
||||
Polynomial<FT> c = double_x*b - a;
|
||||
a = b;
|
||||
b = c;
|
||||
}
|
||||
a = b - 1;
|
||||
|
||||
unsigned int m, i;
|
||||
bool is_even;
|
||||
if (cone_number % 2 == 0) {
|
||||
is_even = true;
|
||||
m = cone_number/2; // for even number of cones
|
||||
}
|
||||
else {
|
||||
m= cone_number/2 + 1; // for odd number of cones
|
||||
is_even = false;
|
||||
}
|
||||
|
||||
FT cos_value, sin_value;
|
||||
// for storing the intermediate result
|
||||
Direction_2 ray;
|
||||
// For saving the first half number of rays when cone_number is even
|
||||
std::vector<Direction_2> ray_store;
|
||||
|
||||
// add the first half number of rays in counter clockwise order
|
||||
for (i = 1; i <= m; i++) {
|
||||
cos_value = - root_of(i, a.begin(), a.end());
|
||||
sin_value = sqrt(FT(1) - cos_value*cos_value);
|
||||
ray = Transformation(cos_value, -sin_value, sin_value, cos_value)(initial_direction);
|
||||
*result++ = ray;
|
||||
if (is_even)
|
||||
ray_store.push_back(ray);
|
||||
}
|
||||
|
||||
// add the remaining half number of rays in ccw order
|
||||
if (is_even) {
|
||||
for (i = 0; i < m; i++) {
|
||||
*result++ = -ray_store[i];
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < m-1; i++) {
|
||||
cos_value = - root_of(m-i, a.begin(), a.end());
|
||||
sin_value = - sqrt(FT(1) - cos_value*cos_value);
|
||||
ray = Transformation(cos_value, -sin_value, sin_value, cos_value)(initial_direction);
|
||||
*result++ = ray;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}; // end of operator()
|
||||
}; // end of functor specialization: Compute_cone_..._2
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
// Copyright (c) 2013-2015 The University of Western Sydney, Australia.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Authors: Weisheng Si, Quincy Tse
|
||||
|
||||
#ifndef CGAL_LESS_BY_DIRECTION_2_H
|
||||
#define CGAL_LESS_BY_DIRECTION_2_H
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <utility>
|
||||
#include <CGAL/Polynomial.h>
|
||||
#include <CGAL/number_utils.h>
|
||||
#include <CGAL/enum.h>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel_with_sqrt.h>
|
||||
#include <CGAL/Aff_transformation_2.h>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
/* Function object that orders 2D graph vertex_descriptors based on the order
|
||||
* induced by the direction D described in the book:
|
||||
*
|
||||
* Giri Narasimhan and Michiel Smid, Chapter 4: Spanners based on the Theta graph, Geometric Spanner Networks,
|
||||
* Cambridge University Press, 2007.
|
||||
*
|
||||
* The ties are broken according to the direction of ccw90(D).
|
||||
* The way of breaking ties in this functor is intended to prevent the overlapping of cone boundaries.
|
||||
* As a result, a vertex on the cw boundary will be considered to be inside this cone,
|
||||
* while a vertex on the ccw boundary will not.
|
||||
*
|
||||
* This function object is implemented using the function `CGAL::compare_signed_distance_to_line_2()`,
|
||||
* which orders two points according to their signed distance to a base line.
|
||||
*
|
||||
*/
|
||||
template <typename Kernel_, typename Graph_>
|
||||
class Less_by_direction_2 : public std::binary_function <typename Graph_::vertex_descriptor,
|
||||
typename Graph_::vertex_descriptor, bool> {
|
||||
|
||||
public:
|
||||
// typedef for C++11 - doesn't hurt to also have for C++98
|
||||
typedef typename Graph_::vertex_descriptor first_argument_type;
|
||||
typedef typename Graph_::vertex_descriptor second_argument_type;
|
||||
typedef bool result_type;
|
||||
|
||||
// typedef for Direction_2 and Line_2
|
||||
typedef typename Kernel_::Direction_2 Direction_2;
|
||||
typedef typename Kernel_::Line_2 Line_2;
|
||||
typedef typename Kernel_::Point_2 Point_2;
|
||||
typedef typename Kernel_::Aff_transformation_2 Transformation;
|
||||
|
||||
// constructor
|
||||
Less_by_direction_2(const Graph_& g, const Direction_2& d)
|
||||
: graph(g), base_line(Point_2(0,0), d) {};
|
||||
|
||||
bool operator() (const typename Graph_::vertex_descriptor& p,
|
||||
const typename Graph_::vertex_descriptor& q) const {
|
||||
Comparison_result outcome;
|
||||
outcome = compare_signed_distance_to_line(base_line, graph[p], graph[q]);
|
||||
if (outcome == SMALLER)
|
||||
return true;
|
||||
else {
|
||||
if (outcome == LARGER)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* otherwise, outcome == CGAL::EQUAL, ties will be broken by a second order
|
||||
* according to the ccw90(base_line) direction.
|
||||
*/
|
||||
// define a rotation of counter clockwise 90
|
||||
Transformation ccw90(0, -1, 1, 0);
|
||||
// rotate
|
||||
Line_2 ccw90_line = ccw90(base_line);
|
||||
outcome = compare_signed_distance_to_line(ccw90_line, graph[p], graph[q]);
|
||||
if (outcome == SMALLER)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
const Graph_& graph;
|
||||
const Line_2 base_line;
|
||||
|
||||
}; // class Less_by_direction_2
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
// Copyright (c) 2013 The University of Western Sydney, Australia.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s) : Quincy Tse, Weisheng Si
|
||||
|
||||
/* Plane_Scan_Tree.h
|
||||
*
|
||||
* This header defines the class Plane_Scan_Tree, the data structure for the balanced search tree used in
|
||||
* the Narasimhan and Smid's algorithm for constructing Theta graph.
|
||||
* Implementations of members in this class can be found in _Plane_Scan_Tree.h.
|
||||
*/
|
||||
|
||||
#ifndef CGAL_PLANE_SCAN_TREE_2_H
|
||||
#define CGAL_PLANE_SCAN_TREE_2_H
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <cstring>
|
||||
|
||||
#include <CGAL/Cone_spanners_2/_Plane_Scan_Tree.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
/* This namespace contains the internal implementation of the tree for builiding Theta graph.
|
||||
* This is not meant to be imported by other code.
|
||||
*/
|
||||
namespace ThetaDetail {
|
||||
|
||||
/*
|
||||
* This is the balanced tree structure needed in Narasimhan and Smid's book,
|
||||
* but implemented using a partial ternary B+ tree instead of red-black tree.
|
||||
*
|
||||
* This tree supports insert and search only, and, similar to a treap, is able
|
||||
* to determine not only the ordering according to a primary order specified
|
||||
* in the key_compare, but is also able to determine minimum weighted value
|
||||
* according to value_compare. Any single operation on this tree is guaranteed
|
||||
* to be at worst O(log n), and builds the tree from a list at O(nlogn).
|
||||
*
|
||||
* !!! Note: No two keys in the tree may have equal ordering
|
||||
* according to key_compare. Results are undefined if key_compare does not give
|
||||
* unique ordering of the inserted keys. The `Less_by_direction_2` functor implemented
|
||||
* by us guarantees the unique ordering, and is passed to Comp and VComp.
|
||||
*
|
||||
* see G. Narasimhan and M. Smid, Geometric Spanner Networks: Cambridge
|
||||
* University Press, 2007, p. 71
|
||||
*/
|
||||
template <typename Key,
|
||||
typename T,
|
||||
typename Comp=std::less<Key>,
|
||||
typename VComp=std::less<const T>
|
||||
>
|
||||
class Plane_Scan_Tree {
|
||||
private:
|
||||
typedef _Node<Key, T, Comp, VComp> _node_type;
|
||||
typedef typename _node_type::_leaf_type _leaf_type;
|
||||
typedef typename _node_type::_internal_type _internal_type;
|
||||
|
||||
public:
|
||||
typedef typename _node_type::key_type key_type;
|
||||
typedef typename _node_type::mapped_type mapped_type;
|
||||
typedef typename _node_type::value_type value_type;
|
||||
typedef typename _node_type::key_compare key_compare;
|
||||
typedef typename _node_type::value_compare value_compare;
|
||||
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
typedef value_type* pointer;
|
||||
typedef const value_type* const_pointer;
|
||||
|
||||
typedef _Iterator<key_type, mapped_type, key_compare, value_compare>
|
||||
iterator;
|
||||
typedef _RIterator<key_type, mapped_type, key_compare, value_compare>
|
||||
reverse_iterator;
|
||||
typedef iterator const_iterator;
|
||||
typedef reverse_iterator const_reverse_iterator;
|
||||
typedef size_t size_type;
|
||||
|
||||
/* Explicit Constructor. */
|
||||
explicit Plane_Scan_Tree (const key_compare& comp = key_compare(),
|
||||
const value_compare& vcomp = value_compare())
|
||||
: less (comp), vless (vcomp), root (NULL), min (NULL),
|
||||
max (NULL), _size (0) {}
|
||||
|
||||
/* Constructor */
|
||||
template <typename InputIterator>
|
||||
Plane_Scan_Tree (InputIterator first, InputIterator last,
|
||||
const key_compare& comp = key_compare(),
|
||||
const value_compare& vcomp = value_compare())
|
||||
: less (comp), vless (vcomp), root (NULL), min (NULL),
|
||||
max (NULL), _size (0)
|
||||
{
|
||||
// TODO - Inplement a more efficient algorithm that builds the tree bottom up
|
||||
for (;first != last; ++first)
|
||||
add (first->first, first->second);
|
||||
}
|
||||
|
||||
/* Destructor. This will recursively destroy all nodes in the tree, making
|
||||
* all iterators and pointers to values stored in this tree invalid.
|
||||
*/
|
||||
~Plane_Scan_Tree () {
|
||||
delete root;
|
||||
root = NULL;
|
||||
min = NULL;
|
||||
max = NULL;
|
||||
_size = 0;;
|
||||
}
|
||||
|
||||
/*
|
||||
#ifdef GXX11
|
||||
/// Move constructor.
|
||||
Plane_Scan_Tree (Plane_Scan_Tree<Key, T, Comp>&& x) : less (x.less), _size(x._size) {
|
||||
root = x.root;
|
||||
x.root = NULL;
|
||||
|
||||
min = x.min;
|
||||
x.min = NULL;
|
||||
|
||||
max = x.max;
|
||||
x.max = NULL;
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
/* Returns the number of key-value pairs in the tree
|
||||
*
|
||||
* @return The number of key-value pairs in the tree.
|
||||
*/
|
||||
size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
/* Inserts a key-value pair into the tree.
|
||||
* @param k The key
|
||||
* @param v The value
|
||||
*/
|
||||
void add (const key_type& k, const mapped_type& v) {
|
||||
if (NULL == root) {
|
||||
min = new _leaf_type (less, vless, this);
|
||||
max = min;
|
||||
root = min;
|
||||
}
|
||||
_leaf_type* l = root->leafNode(k);
|
||||
l->add(k, v);
|
||||
_size++;
|
||||
}
|
||||
|
||||
/* find a key */
|
||||
iterator find(const key_type& k) {
|
||||
_leaf_type* l = root->leafNode(k);
|
||||
return iterator (l, k);
|
||||
}
|
||||
|
||||
/* find a constant key */
|
||||
const_iterator find(const key_type& k) const {
|
||||
_leaf_type* l = root->leafNode(k);
|
||||
return const_iterator (l, k);
|
||||
}
|
||||
|
||||
/* Returns the the minimum value that has a key strictly greater than
|
||||
* the specified key.
|
||||
*
|
||||
* @param x The threshold key
|
||||
* @return The minimum value whose key is strictly greater than x.
|
||||
*/
|
||||
const mapped_type* minAbove (const key_type& x) const {
|
||||
if (NULL == root) return NULL;
|
||||
return root->minAbove(x);
|
||||
}
|
||||
|
||||
/* Begin Iterator */
|
||||
inline iterator begin() {
|
||||
return iterator (this->min);
|
||||
}
|
||||
|
||||
/* Const Begin Iterator */
|
||||
inline const_iterator begin() const {
|
||||
return const_iterator (this->min);
|
||||
}
|
||||
|
||||
/* End Iterator */
|
||||
inline iterator end() {
|
||||
static iterator res;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Constant End Iterator */
|
||||
inline const_iterator end() const {
|
||||
static const_iterator res;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Reverse order Begin Iterator */
|
||||
inline reverse_iterator rbegin() {
|
||||
return reverse_iterator (this->max);
|
||||
}
|
||||
|
||||
/* Constant Reverse order Begin Iterator */
|
||||
const_reverse_iterator rbegin() const {
|
||||
return const_reverse_iterator (this->max);
|
||||
}
|
||||
|
||||
/* Reverse order End Iterator */
|
||||
reverse_iterator rend() {
|
||||
static reverse_iterator res;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Constant Reverse order End Iterator */
|
||||
const_reverse_iterator rend() const {
|
||||
static const_reverse_iterator res;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
friend class _Leaf<Key, T, Comp, VComp>;
|
||||
friend class _Internal<Key, T, Comp, VComp>;
|
||||
|
||||
friend std::ostream& operator<< (std::ostream& os, const Plane_Scan_Tree<Key, T, Comp, VComp>& pst) {
|
||||
os << *pst.root << std::endl;
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
/* key_compare funtor */
|
||||
const key_compare less;
|
||||
|
||||
/* value_compare funtor */
|
||||
const value_compare vless;
|
||||
|
||||
/* pointer to root */
|
||||
_node_type* root;
|
||||
|
||||
/* pointer to min */
|
||||
_leaf_type* min;
|
||||
|
||||
/* pointer to max */
|
||||
_leaf_type* max;
|
||||
|
||||
/* size of the tree */
|
||||
size_t _size;
|
||||
};
|
||||
|
||||
} // namespace ThetaDetail
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,633 @@
|
|||
// Copyright (c) 2013 The University of Western Sydney, Australia.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s) : Quincy Tse, Weisheng Si
|
||||
|
||||
/* _Plane_Scan_Tree.h
|
||||
*
|
||||
* This header implements the details of the class Plane_Scan_Tree.
|
||||
*/
|
||||
|
||||
#ifndef CGAL__PLANE_SCAN_TREE_2_H
|
||||
#define CGAL__PLANE_SCAN_TREE_2_H
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
/* This namespace contains the internal implementation of the tree for building Theta graph.
|
||||
* This is not meant to be imported by other codes.
|
||||
*/
|
||||
namespace ThetaDetail {
|
||||
|
||||
/* Contains the internal data structure for the Plane_Scan_Tree.
|
||||
*
|
||||
* Plane_Scan_Tree is a ternary B+ tree using linked structures.
|
||||
*/
|
||||
template < typename Key, typename T, typename Comp, typename VComp >
|
||||
class Plane_Scan_Tree;
|
||||
|
||||
template < typename Key, typename T, typename Comp=std::less<Key>, typename VComp=std::less<const T> >
|
||||
class _Node;
|
||||
template < typename Key, typename T, typename Comp=std::less<Key>, typename VComp=std::less<const T> >
|
||||
class _Leaf;
|
||||
template < typename Key, typename T, typename Comp=std::less<Key>, typename VComp=std::less<const T> >
|
||||
class _Internal;
|
||||
|
||||
template < typename Key, typename T, typename Comp=std::less<Key>, typename VComp=std::less<const T> >
|
||||
class _Iterator;
|
||||
|
||||
template < typename Key, typename T, typename Comp=std::less<Key>, typename VComp=std::less<const T> >
|
||||
class _RIterator;
|
||||
|
||||
/* Abstract superclass */
|
||||
template < typename Key, typename T, typename Comp, typename VComp >
|
||||
class _Node {
|
||||
public:
|
||||
typedef Key key_type;
|
||||
typedef T mapped_type;
|
||||
typedef std::pair<const Key, T> value_type;
|
||||
typedef Comp key_compare;
|
||||
typedef VComp value_compare;
|
||||
|
||||
typedef _Node<Key, T, Comp, VComp> _node_type;
|
||||
typedef _Leaf<Key, T, Comp, VComp> _leaf_type;
|
||||
typedef _Internal<Key, T, Comp, VComp> _internal_type;
|
||||
typedef Plane_Scan_Tree<Key, T, Comp, VComp> tree_type;
|
||||
|
||||
/* Constructor */
|
||||
_Node(const key_compare& less, const value_compare& vless, tree_type *const t)
|
||||
: parent(NULL), less(less), vless(vless), tree(t) {}
|
||||
|
||||
/* Destructor */
|
||||
virtual ~_Node() {}
|
||||
|
||||
/* @return true if the node is a leaf node, false otherwise. */
|
||||
virtual bool isLeaf() const = 0;
|
||||
|
||||
/* Retrieves the leaf node that handles the specified key.
|
||||
*
|
||||
* @param k The key being queried
|
||||
* @return The leaf node that handles the key.
|
||||
*/
|
||||
virtual _leaf_type* leafNode(const key_type& k) = 0;
|
||||
|
||||
/* Returns the minimum value whose key is greater than x.
|
||||
*
|
||||
* @param x The threshold key
|
||||
* @return the minimum value whose key is greater than x.
|
||||
*/
|
||||
virtual const mapped_type* minAbove(const key_type& x) const = 0;
|
||||
|
||||
friend std::ostream& operator<< (std::ostream& os, const _node_type& n) {
|
||||
n.print(os, 0);
|
||||
return os;
|
||||
}
|
||||
|
||||
protected:
|
||||
/* Prints a string representation of the node in the ostream. */
|
||||
virtual void print(std::ostream&, const size_t) const = 0;
|
||||
|
||||
/* Sets the parent internal node for the node */
|
||||
void setParent(_internal_type *const p) {
|
||||
parent = p;
|
||||
}
|
||||
|
||||
/* Returns the minimum value in the subtree rooted at the current node. */
|
||||
virtual const mapped_type* minV() const = 0;
|
||||
|
||||
_internal_type* parent;
|
||||
const key_compare& less;
|
||||
const value_compare& vless;
|
||||
tree_type* tree;
|
||||
|
||||
friend class _Leaf<key_type, mapped_type, key_compare, value_compare>;
|
||||
friend class _Internal<key_type, mapped_type, key_compare, value_compare>;
|
||||
};
|
||||
|
||||
/* Leaf node of the B+ tree. */
|
||||
template < typename Key, typename T, typename Comp, typename VComp >
|
||||
class _Leaf : public _Node<Key, T, Comp, VComp> {
|
||||
public:
|
||||
typedef _Node<Key, T, Comp, VComp> _node_type;
|
||||
|
||||
typedef typename _node_type::key_type key_type;
|
||||
typedef typename _node_type::mapped_type mapped_type;
|
||||
typedef typename _node_type::value_type value_type;
|
||||
typedef typename _node_type::key_compare key_compare;
|
||||
typedef typename _node_type::value_compare value_compare;
|
||||
|
||||
typedef typename _node_type::_leaf_type _leaf_type;
|
||||
typedef typename _node_type::_internal_type _internal_type;
|
||||
typedef typename _node_type::tree_type tree_type;
|
||||
|
||||
_Leaf (const key_compare& less, const value_compare& vless, tree_type *const t,
|
||||
_leaf_type *const prev = NULL,
|
||||
_leaf_type *const next = NULL)
|
||||
: _node_type (less, vless, t), prev (prev), next (next) {
|
||||
std::memset (values, 0, 2*sizeof(value_type*));
|
||||
}
|
||||
|
||||
/* Destructor.
|
||||
* Frees memory used for storing key-value pair, thus invalidating any
|
||||
* exisitng pointers to any keys and/or values in the tree. During and
|
||||
* after destruction, neighbour nodes are not guarenteed to be consistent.
|
||||
* Specifically, the linked list along the leaves of the B+ tree is
|
||||
* invalidated. */
|
||||
virtual ~_Leaf() {
|
||||
delete values[0];
|
||||
delete values[1];
|
||||
values[0] = NULL;
|
||||
values[1] = NULL;
|
||||
prev = NULL;
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
virtual bool isLeaf() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual _leaf_type* leafNode(const key_type&) {
|
||||
return this;
|
||||
}
|
||||
|
||||
void add(const key_type& k, const mapped_type& v) {
|
||||
if (NULL == values[0]) {
|
||||
// empty
|
||||
values[0] = new value_type(k, v);
|
||||
} else if (NULL == values[1]) {
|
||||
// Not full;
|
||||
if (this->less(k, values[0]->first)) {
|
||||
values[1] = values[0];
|
||||
values[0] = new value_type(k, v);
|
||||
if (this->parent && this->vless(v, values[1]->second))
|
||||
this->parent->updateMin(this);
|
||||
} else {
|
||||
values[1] = new value_type(k, v);
|
||||
if (this->parent && this->vless(v, values[0]->second))
|
||||
this->parent->updateMin(this);
|
||||
}
|
||||
} else {
|
||||
_leaf_type* split
|
||||
= new _leaf_type(this->less, this->vless, this->tree, this, next);
|
||||
if (NULL != next) next->prev = split;
|
||||
next = split;
|
||||
if (this->less(k, values[0]->first)) {
|
||||
// k, [0], [1]
|
||||
split->values[0] = values[0];
|
||||
split->values[1] = values[1];
|
||||
values[0] = new value_type(k, v);
|
||||
values[1] = NULL;
|
||||
} else if (this->less(k, values[1]->first)) {
|
||||
// [0], k, [1]
|
||||
split->values[0] = new value_type(k, v);
|
||||
split->values[1] = values[1];
|
||||
values[1] = NULL;
|
||||
} else {
|
||||
split->values[0] = values[1];
|
||||
split->values[1] = new value_type(k, v);
|
||||
values[1] = NULL;
|
||||
}
|
||||
|
||||
// Update pointer to max leaf (for reverse iterator)
|
||||
if (this->tree->max == this) this->tree->max = split;
|
||||
|
||||
// Create new parent node current node is not root
|
||||
if (NULL == this->parent) {
|
||||
this->setParent(new _internal_type(this->less, this->vless, this->tree));
|
||||
this->tree->root = this->parent;
|
||||
}
|
||||
// Promote middle key and get parent to readjust pointers
|
||||
this->parent->splitMe (&(split->values[0]->first), this, split);
|
||||
}
|
||||
}
|
||||
|
||||
virtual const mapped_type* minAbove(const key_type& x) const {
|
||||
if ( !this->less(x, values[0]->first) && !this->less(values[0]->first, x) // equals
|
||||
&& NULL != values[1]) {
|
||||
return &values[1]->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual const mapped_type* minV() const {
|
||||
return (NULL == values[1]) ? &values[0]->second : &std::min(values[0]->second, values[1]->second, this->vless);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void print(std::ostream& os, const size_t level) const {
|
||||
os << "\t\"" << this << "\"--\"" << &(values[0]->first) << "\" [style=bold];" << std::endl;
|
||||
os << "\t" << "{rank=same; \"" << &(values[0]->first) << "\"--\"" << &(values[0]->second) << "\" [style=dotted];}" << std::endl;
|
||||
os << "\t\"" << &(values[0]->first) << "\"--\"" << values[0]->first << "\";" << std::endl;
|
||||
os << "\t\"" << &(values[0]->second) << "\"--\"" << values[0]->second << "\";" << std::endl;
|
||||
if (NULL != values[1]) {
|
||||
os << "\t\"" << this << "\"--\"" << &(values[1]->first) << "\" [style=bold];" << std::endl;
|
||||
os << "\t" << "{rank=same; \"" << &(values[1]->first) << "\"--\"" << &(values[1]->second) << "\" [style=dotted];}" << std::endl;
|
||||
os << "\t" << "{rank=same; \"" << &(values[0]->second) << "\"--\"" << &(values[1]->first) << "\" [color=white]; rankdir=LR;}" << std::endl;
|
||||
os << "\t\"" << &(values[1]->first) << "\"--\"" << values[1]->first << "\";" << std::endl;
|
||||
os << "\t\"" << &(values[1]->second) << "\"--\"" << values[1]->second << "\";" << std::endl;
|
||||
}
|
||||
os << "\t\"" << this << "\" [style=diagonals];" << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
/* Key-value pairs */
|
||||
value_type* values[2];
|
||||
|
||||
/* Linked list structure of the B+ tree */
|
||||
_leaf_type* prev;
|
||||
_leaf_type* next;
|
||||
|
||||
friend class _Iterator<key_type, mapped_type, key_compare, value_compare>;
|
||||
friend class _RIterator<key_type, mapped_type, key_compare, value_compare>;
|
||||
};
|
||||
|
||||
template < typename Key, typename T, typename Comp, typename VComp >
|
||||
class _Internal : public _Node<Key, T, Comp, VComp> {
|
||||
public:
|
||||
typedef _Node<Key, T, Comp, VComp> _node_type;
|
||||
|
||||
typedef typename _node_type::key_type key_type;
|
||||
typedef typename _node_type::mapped_type mapped_type;
|
||||
typedef typename _node_type::value_type value_type;
|
||||
typedef typename _node_type::key_compare key_compare;
|
||||
typedef typename _node_type::value_compare value_compare;
|
||||
|
||||
typedef typename _node_type::_leaf_type _leaf_type;
|
||||
typedef typename _node_type::_internal_type _internal_type;
|
||||
typedef typename _node_type::tree_type tree_type;
|
||||
|
||||
_Internal (const Comp& less, const VComp& vless, tree_type *const t)
|
||||
: _node_type(less, vless, t) {
|
||||
std::memset (keys, 0, 2*sizeof(key_type*));
|
||||
std::memset (children, 0, 3*sizeof(_node_type*));
|
||||
std::memset (vMin, 0, 3*sizeof(mapped_type*));
|
||||
}
|
||||
|
||||
virtual ~_Internal() {
|
||||
keys[0] = NULL;
|
||||
keys[1] = NULL;
|
||||
|
||||
delete children[0]; children[0] = NULL;
|
||||
delete children[1]; children[1] = NULL;
|
||||
delete children[2]; children[2] = NULL;
|
||||
|
||||
vMin[0] = NULL;
|
||||
vMin[1] = NULL;
|
||||
vMin[2] = NULL;
|
||||
}
|
||||
|
||||
virtual bool isLeaf() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual _leaf_type* leafNode(const key_type& k) {
|
||||
int i = 0;
|
||||
for (i = 0; (i < 2) && (NULL != keys[i]); i++) {
|
||||
if (this->less(k, *(keys[i]))) return children[i]->leafNode(k);
|
||||
}
|
||||
return children[i]->leafNode(k);
|
||||
}
|
||||
|
||||
/* Update references to min values.
|
||||
*
|
||||
* @param ch The child node involved.
|
||||
*/
|
||||
void updateMin(const _node_type *const ch) {
|
||||
int i = 0;
|
||||
while (i < 3) {
|
||||
if (children[i] == ch) break;
|
||||
++i;
|
||||
}
|
||||
if (i >= 3)
|
||||
throw std::runtime_error("Cannot find child");
|
||||
|
||||
vMin[i] = ch->minV();
|
||||
if (this->parent && minV() == vMin[i])
|
||||
this->parent->updateMin(this);
|
||||
}
|
||||
|
||||
/* Process the splitting of children. This is called by the affected
|
||||
* child AFTER splitting had occurred. This function updates relevant
|
||||
* pointers, and splits current internal node as necessary.
|
||||
*
|
||||
* @param k The key the child was split on.
|
||||
* @param left The (existing) child that lies to the left of k.
|
||||
* @param right The (new) child that lies to the right of k.
|
||||
*/
|
||||
void splitMe(const key_type *const k,
|
||||
_node_type *const left,
|
||||
_node_type *const right) {
|
||||
if (keys[0] == NULL) {
|
||||
// New root
|
||||
keys[0] = k;
|
||||
children[0] = left;
|
||||
left->setParent(this);
|
||||
vMin[0] = left->minV();
|
||||
children[1] = right;
|
||||
right->setParent(this);
|
||||
vMin[1] = right->minV();
|
||||
} else if (keys[1] == NULL) {
|
||||
// not full
|
||||
if (left == children[0]) {
|
||||
// split 0th
|
||||
keys[1] = keys[0];
|
||||
keys[0] = k;
|
||||
children[2] = children[1];
|
||||
children[1] = right;
|
||||
right->setParent(this);
|
||||
|
||||
vMin[0] = children[0]->minV();
|
||||
vMin[1] = children[1]->minV();
|
||||
vMin[2] = children[2]->minV();
|
||||
} else {
|
||||
// split 1st
|
||||
keys[1] = k;
|
||||
children[2] = right;
|
||||
right->setParent(this);
|
||||
|
||||
// did not touch children[0]
|
||||
vMin[1] = children[1]->minV();
|
||||
vMin[2] = children[2]->minV();
|
||||
}
|
||||
if (this->parent)
|
||||
this->parent->updateMin(this);
|
||||
} else {
|
||||
// full
|
||||
_internal_type* split
|
||||
= new _internal_type(this->less, this->vless, this->tree);
|
||||
const key_type * toPromote;
|
||||
if (left == children[0]) {
|
||||
// Split 0th
|
||||
split->keys[0] = keys[1];
|
||||
toPromote = keys[0];
|
||||
keys[1] = NULL;
|
||||
keys[0] = k;
|
||||
|
||||
split->children[1] = children[2];
|
||||
split->vMin[1] = split->children[1]->minV();
|
||||
split->children[1]->setParent(split);
|
||||
|
||||
split->children[0] = children[1];
|
||||
split->vMin[0] = split->children[0]->minV();
|
||||
split->children[0]->setParent(split);
|
||||
|
||||
children[1] = right;
|
||||
vMin[1] = children[1]->minV();
|
||||
children[1]->setParent(this);
|
||||
|
||||
vMin[0] = children[0]->minV();
|
||||
|
||||
children[2] = NULL;
|
||||
vMin[2] = NULL;
|
||||
} else if (left == children[1]) {
|
||||
// Split 1st
|
||||
split->keys[0] = keys[1];
|
||||
toPromote = k;
|
||||
keys[1] = NULL;
|
||||
|
||||
split->children[1] = children[2];
|
||||
split->vMin[1] = split->children[1]->minV();
|
||||
split->children[1]->setParent(split);
|
||||
|
||||
split->children[0] = right;
|
||||
split->vMin[0] = split->children[0]->minV();
|
||||
split->children[0]->setParent(split);
|
||||
|
||||
vMin[1] = children[1]->minV();
|
||||
|
||||
children[2] = NULL;
|
||||
vMin[2] = NULL;
|
||||
} else {
|
||||
// Split last
|
||||
split->keys[0] = k;
|
||||
toPromote = keys[1];
|
||||
keys[1] = NULL;
|
||||
|
||||
split->children[1] = right;
|
||||
split->vMin[1] = split->children[1]->minV();
|
||||
split->children[1]->setParent(split);
|
||||
|
||||
split->children[0] = left;
|
||||
split->vMin[0] = split->children[0]->minV();
|
||||
split->children[0]->setParent(split);
|
||||
|
||||
children[2] = NULL;
|
||||
vMin[2] = NULL;
|
||||
}
|
||||
|
||||
if (NULL == this->parent) {
|
||||
this->setParent(new _internal_type(this->less, this->vless, this->tree));
|
||||
this->tree->root = this->parent;
|
||||
}
|
||||
|
||||
this->parent->splitMe (toPromote, this, split);
|
||||
}
|
||||
}
|
||||
|
||||
virtual const mapped_type* minAbove(const key_type& x) const {
|
||||
if (this->less(x, *keys[0])) {
|
||||
// x in left tree
|
||||
const mapped_type* minFromCh = children[0]->minAbove(x);
|
||||
const mapped_type* res =
|
||||
(NULL == minFromCh) ?
|
||||
vMin[1] :
|
||||
&std::min (*children[0]->minAbove(x), *vMin[1], this->vless);
|
||||
if (vMin[2] != NULL)
|
||||
res = &std::min (*res, *vMin[2], this->vless);
|
||||
return res;
|
||||
} else if (NULL == keys[1] || this->less(x, *keys[1])) {
|
||||
// x in middle
|
||||
const mapped_type* res = children[1]->minAbove(x);
|
||||
if (NULL == res) return vMin[2];
|
||||
|
||||
if (vMin[2] != NULL)
|
||||
res = &std::min (*res, *vMin[2], this->vless);
|
||||
return res;
|
||||
} else {
|
||||
return children[2]->minAbove(x);
|
||||
}
|
||||
}
|
||||
|
||||
virtual const mapped_type* minV() const {
|
||||
const mapped_type* res = &std::min(*vMin[0], *vMin[1], this->vless);
|
||||
if (NULL != children[2])
|
||||
res = &std::min(*res, *vMin[2], this->vless);
|
||||
return res;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void print(std::ostream& os, const size_t level) const {
|
||||
os << "\t\"" << this << "\"--\"" << children[0] << "\";" << std::endl;
|
||||
os << "\t\"" << this << "\"--\"" << children[1] << "\";" << std::endl;
|
||||
if (NULL != children[2])
|
||||
os << "\t\"" << this << "\"--\"" << children[2] << "\";" << std::endl;
|
||||
|
||||
children[0]->print(os, level+1);
|
||||
children[1]->print(os, level+1);
|
||||
if (NULL != children[2])
|
||||
children[2]->print(os, level+1);
|
||||
|
||||
os << "\t\"" << this << "\"--\"" << vMin[0] << "\" [style=dashed,label=vMin0];" << std::endl;
|
||||
os << "\t\"" << this << "\"--\"" << vMin[1] << "\" [style=dashed,label=vMin1];" << std::endl;
|
||||
if (NULL != vMin[2])
|
||||
os << "\t\"" << this << "\"--\"" << vMin[2] << "\" [style=dashed,label=vMin2];" << std::endl;
|
||||
|
||||
os << "\t\"" << this << "\"--\"" << keys[0] << "\" [style=dotted,label=keys0];" << std::endl;
|
||||
if (NULL != keys[1])
|
||||
os << "\t\"" << this << "\"--\"" << keys[1] << "\" [style=dotted,label=keys1];" << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
const key_type* keys[2];
|
||||
_node_type* children[3];
|
||||
const mapped_type* vMin[3];
|
||||
};
|
||||
|
||||
template <typename Key, typename T, typename Comp, typename VComp >
|
||||
class _Iterator {
|
||||
public:
|
||||
typedef _Leaf<Key, T, Comp, VComp> leaf_type;
|
||||
|
||||
typedef typename leaf_type::value_type value_type;
|
||||
typedef _Iterator<Key, T, Comp, VComp> iterator_type;
|
||||
|
||||
_Iterator(leaf_type* start = NULL) : cell (0), leaf(start) {}
|
||||
_Iterator(leaf_type* start, const Key& key) : cell(0), leaf(start) {
|
||||
if (start->values[0]->first != key) {
|
||||
if (!start->values[1] || start->values[1]->first != key)
|
||||
leaf = NULL;
|
||||
else
|
||||
cell = 1;
|
||||
}
|
||||
}
|
||||
~_Iterator() {
|
||||
cell = 0;
|
||||
leaf = NULL;
|
||||
}
|
||||
|
||||
value_type& operator*() const {
|
||||
return *(leaf->values[cell]);
|
||||
}
|
||||
|
||||
value_type* operator->() const {
|
||||
return leaf->values[cell];
|
||||
}
|
||||
|
||||
iterator_type& operator++() {
|
||||
cell++;
|
||||
if (NULL == leaf) return *this;
|
||||
|
||||
if (cell > 1 || NULL == leaf->values[cell]) {
|
||||
cell = 0;
|
||||
leaf = leaf->next;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator_type operator++(int) {
|
||||
iterator_type res (*this);
|
||||
++(*this);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool operator==(const iterator_type& x) const {
|
||||
return (leaf == x.leaf) && (cell == x.cell);
|
||||
}
|
||||
|
||||
bool operator!=(const iterator_type& x) const {
|
||||
return (leaf != x.leaf) || (cell != x.cell);
|
||||
}
|
||||
|
||||
private:
|
||||
size_t cell;
|
||||
leaf_type* leaf;
|
||||
|
||||
friend class _Node<Key, T, Comp, VComp>;
|
||||
};
|
||||
|
||||
template <typename Key, typename T, typename Comp, typename VComp >
|
||||
class _RIterator {
|
||||
public:
|
||||
typedef _Leaf<Key, T, Comp, VComp> leaf_type;
|
||||
|
||||
typedef typename leaf_type::value_type value_type;
|
||||
typedef _RIterator<Key, T, Comp, VComp> iterator_type;
|
||||
|
||||
_RIterator(_Leaf<Key, T, Comp, VComp>* start = NULL) : cell (1), leaf(start) {
|
||||
if (NULL == start) return;
|
||||
|
||||
if (NULL == leaf->values[cell]) {
|
||||
cell--;
|
||||
if (NULL == leaf->values[cell]) leaf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
~_RIterator() {
|
||||
cell = 0;
|
||||
leaf = NULL;
|
||||
}
|
||||
|
||||
value_type& operator*() const {
|
||||
return *(leaf->values[cell]);
|
||||
}
|
||||
|
||||
value_type* operator->() const {
|
||||
return leaf->values[cell];
|
||||
}
|
||||
|
||||
iterator_type& operator++() {
|
||||
if (NULL == leaf) return *this;
|
||||
if (cell == 1) {
|
||||
cell--;
|
||||
} else if (cell == 0) {
|
||||
cell = 1;
|
||||
leaf = leaf->prev;
|
||||
if (NULL == leaf) return *this;
|
||||
|
||||
if (NULL == leaf->values[cell]) cell--;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator_type operator++(int) {
|
||||
iterator_type res (*this);
|
||||
++(*this);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool operator==(const iterator_type& x) const {
|
||||
return (leaf == x.leaf) && (cell == x.cell);
|
||||
}
|
||||
|
||||
bool operator!=(const iterator_type& x) const {
|
||||
return (leaf != x.leaf) || (cell != x.cell);
|
||||
}
|
||||
|
||||
private:
|
||||
size_t cell;
|
||||
leaf_type* leaf;
|
||||
|
||||
friend class _Node<Key, T, Comp, VComp>;
|
||||
};
|
||||
|
||||
} // namespace ThetaDetail
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,275 @@
|
|||
// Copyright (c) 2013-2015 The University of Western Sydney, Australia.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Authors: Weisheng Si, Quincy Tse
|
||||
|
||||
/*! \file Construct_theta_graph_2.h
|
||||
*
|
||||
* This header implements the functor for constructing Theta graphs.
|
||||
*/
|
||||
|
||||
#ifndef CGAL_CONSTRUCT_THETA_GRAPH_2_H
|
||||
#define CGAL_CONSTRUCT_THETA_GRAPH_2_H
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <utility>
|
||||
#include <CGAL/Aff_transformation_2.h>
|
||||
#include <CGAL/Compute_cone_boundaries_2.h>
|
||||
#include <CGAL/Cone_spanners_2/Less_by_direction_2.h>
|
||||
#include <CGAL/Cone_spanners_2/Plane_Scan_Tree.h>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
/*! \ingroup PkgConeBasedSpanners
|
||||
|
||||
\brief A template functor for constructing Theta graphs with a given set of 2D points and
|
||||
a given initial direction for the cone boundaries.
|
||||
|
||||
For the meaning and use of its template parameters, please refer to the concept
|
||||
`ConstructConeBasedSpanner_2`.
|
||||
|
||||
\cgalModels `ConstructConeBasedSpanner_2`
|
||||
*/
|
||||
template <typename Traits, typename Graph_>
|
||||
class Construct_theta_graph_2 {
|
||||
|
||||
public:
|
||||
/*! is the geometric traits which must be a model of the concept `ConeBasedSpannerTraits` */
|
||||
typedef Traits Geom_traits;
|
||||
/*! Indicate the specific type of `boost::adjacency_list`. */
|
||||
typedef Graph_ Graph_type;
|
||||
|
||||
private:
|
||||
typedef typename Geom_traits::Direction_2 Direction_2;
|
||||
typedef typename Geom_traits::Point_2 Point_2;
|
||||
typedef typename Geom_traits::Line_2 Line_2;
|
||||
typedef typename Geom_traits::Aff_transformation_2 Transformation;
|
||||
typedef Less_by_direction_2<Geom_traits, Graph_> Less_by_direction;
|
||||
|
||||
/* Store the number of cones. */
|
||||
unsigned int cone_number;
|
||||
|
||||
/* Store the directions of the rays dividing the plane. The initial direction will be
|
||||
* stored in rays[0].
|
||||
*/
|
||||
std::vector<Direction_2> rays;
|
||||
|
||||
public:
|
||||
/*! \brief Constructor.
|
||||
\details Constructs a `Construct_theta_graph_2` object.
|
||||
|
||||
\param k Number of cones to divide space into
|
||||
\param initial_direction A direction denoting one of the rays deviding the
|
||||
cones. This allows arbitary rotations of the rays that divide
|
||||
the plane. (default: positive x-axis)
|
||||
*/
|
||||
Construct_theta_graph_2 (unsigned int k,
|
||||
Direction_2 initial_direction = Direction_2(1,0)
|
||||
): cone_number(k), rays(std::vector<Direction_2>(k))
|
||||
|
||||
{
|
||||
if (k<2) {
|
||||
std::cout << "The number of cones must be larger than 1!" << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
/* Initialize a functor, specialization will happen here depending on the kernel type to
|
||||
compute the cone boundaries either exactly or inexactly */
|
||||
Compute_cone_boundaries_2<Geom_traits> compute_cones;
|
||||
// compute the rays using the functor
|
||||
compute_cones(k, initial_direction, rays.begin());
|
||||
}
|
||||
|
||||
/* \brief Copy constructor. As commented by Michael Hemmer, copy constructor is not needed for
|
||||
a funtor.
|
||||
\param x another Construct_theta_graph_2 object to copy from.
|
||||
|
||||
Construct_theta_graph_2 (const Construct_theta_graph_2& x) : cone_number(x.cone_number), rays(x.rays) {}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\brief Operator to construct a Theta graph.
|
||||
|
||||
\details This operator implements the algorithm for constructing the Theta graph.
|
||||
For the details of this algorithm, please refer to the user manual.
|
||||
|
||||
\param[in] start An iterator pointing to the first vertex of the input.
|
||||
\param[in] end An iterator pointing to the past-the-end location of the input.
|
||||
\param[out] g The constructed graph object.
|
||||
*/
|
||||
template <typename PointInputIterator>
|
||||
Graph_& operator()(const PointInputIterator& start,
|
||||
const PointInputIterator& end,
|
||||
Graph_& g) {
|
||||
|
||||
// add vertices into the graph
|
||||
for (PointInputIterator curr = start; curr != end; ++curr) {
|
||||
g[boost::add_vertex(g)] = *curr;
|
||||
}
|
||||
|
||||
unsigned int i; // ray index of the cw ray
|
||||
unsigned int j; // index of the ccw ray
|
||||
|
||||
// add edges into the graph for every cone
|
||||
for (i = 0; i < cone_number; i++) {
|
||||
j = (i+1) % cone_number;
|
||||
add_edges_in_cone(rays[i], rays[j], g);
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
/*! \brief returns the number of cones.
|
||||
*/
|
||||
const unsigned int number_of_cones() const {
|
||||
return cone_number;
|
||||
}
|
||||
|
||||
/*! \brief outputs the directions in the vector rays to the iterator `result`.
|
||||
|
||||
\return the past-the-end iterator of the vector `rays`.
|
||||
*/
|
||||
template<class DirectionOutputIterator>
|
||||
DirectionOutputIterator directions(DirectionOutputIterator result) {
|
||||
typename std::vector<Direction_2>::iterator it;
|
||||
for (it=rays.begin(); it!=rays.end(); it++) {
|
||||
*result++ = *it;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/* Construct edges in one cone bounded by two directions.
|
||||
|
||||
\param cwBound The direction of the clockwise boundary of the cone.
|
||||
\param ccwBound The direction of the counter-clockwise boundary.
|
||||
\param g The Theta graph to be built.
|
||||
*/
|
||||
void add_edges_in_cone(const Direction_2& cwBound, const Direction_2& ccwBound, Graph_& g) {
|
||||
if (ccwBound == cwBound) {
|
||||
// Degenerate case, not allowed.
|
||||
throw std::out_of_range("The cw boundary and the ccw boundary shouldn't be same!");
|
||||
}
|
||||
|
||||
// Find angle bisector (requiring sqrt(), not exact)
|
||||
Line_2 cwLine(ORIGIN, cwBound);
|
||||
Line_2 ccwLine(ORIGIN, ccwBound);
|
||||
Direction_2 bisector_direction = bisector(cwLine, ccwLine).direction();
|
||||
|
||||
// Rotational transformation of cw 90 degree
|
||||
static const Transformation cw90( 0, 1, -1, 0);
|
||||
|
||||
// Ordering
|
||||
// here D1 is the reverse of D1 in the book, we find this is easier to implement
|
||||
const Less_by_direction orderD1 (g, ccwBound);
|
||||
const Less_by_direction orderD2 (g, cwBound);
|
||||
const Less_by_direction orderMid(g, cw90(bisector_direction));
|
||||
|
||||
typename Graph_::vertex_iterator vit, ve;
|
||||
boost::tie(vit, ve) = boost::vertices(g);
|
||||
|
||||
// Step 1: Sort S according to order induced by D1
|
||||
std::vector<typename Graph_::vertex_descriptor> S(vit, ve);
|
||||
std::sort(S.begin (), S.end (), orderD1);
|
||||
|
||||
// Step 2: Initialise an empty set to store vertices sorted by orderD2
|
||||
typedef CGAL::ThetaDetail::Plane_Scan_Tree<typename Graph_::vertex_descriptor,
|
||||
typename Graph_::vertex_descriptor,
|
||||
Less_by_direction,
|
||||
Less_by_direction > PSTree;
|
||||
PSTree pst(orderD2, orderMid);
|
||||
#ifndef NDEBUG
|
||||
#ifdef REALLY_VERBOSE_TREE_STATE_AFTER_EVERY_TREE_UPDATE__SAFE_TO_REMOVE_FOR_PRODUCTION
|
||||
int i = 0;
|
||||
#endif
|
||||
#endif
|
||||
// Step 3: visit S in orderD1
|
||||
// * insert pi into T
|
||||
// * ri = T.minAbove(pi)
|
||||
for (typename std::vector<typename Graph_::vertex_descriptor>::const_iterator
|
||||
it = S.begin(); it != S.end(); ++it) {
|
||||
pst.add(*it, *it);
|
||||
const typename Graph_::vertex_descriptor *const ri = pst.minAbove(*it);
|
||||
if ( ri != NULL ) {
|
||||
typename Graph_::edge_descriptor existing_e;
|
||||
bool existing;
|
||||
// check whether the edge already exists
|
||||
boost::tie(existing_e, existing)=boost::edge(*it, *ri, g);
|
||||
if (!existing)
|
||||
boost::add_edge(*it, *ri, g);
|
||||
//else
|
||||
// std::cout << "Edge " << *it << ", " << *ri << " already exists!" << std::endl;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
#ifdef REALLY_VERBOSE_TREE_STATE_AFTER_EVERY_TREE_UPDATE__SAFE_TO_REMOVE_FOR_PRODUCTION
|
||||
// Prints the current tree
|
||||
// To see the tree, pipe output to dot. eg
|
||||
// ./a.out <whatever arguments...> | dot -Tpng -O
|
||||
// You'll get a sequence of png files:
|
||||
// noname.dot.png
|
||||
// noname.dot.2.png
|
||||
// noname.dot.3.png
|
||||
// ...etc...
|
||||
//
|
||||
// The tree output shades the new value added, and states what action was taken.
|
||||
std::cout << "graph Plane_Scan_Tree {" << std::endl <<
|
||||
pst << std::endl << std::endl;
|
||||
int j = 1;
|
||||
for (auto rit = S.rbegin(); rit <= it; ++rit) {
|
||||
auto p = g[*rit];
|
||||
std::cout << "\t\"" << *rit << "\"[label=\"" << j++ << "\"";
|
||||
if (rit == it)
|
||||
std::cout << ",style=filled";
|
||||
std::cout << "];" << std::endl;
|
||||
}
|
||||
|
||||
if (pst.size() > 1) {
|
||||
std::cout << "\t{rank=same;" << std::endl;
|
||||
std::cout << "\"" << pst.begin()->first << "\"";
|
||||
for (auto pit = ++(pst.begin()); pit != pst.end(); ++pit) {
|
||||
std::cout << "--\"" << pit->first << "\"";
|
||||
}
|
||||
std::cout << "[color=white];" << std::endl;
|
||||
std::cout << "rankdir=LR;" << std::endl;
|
||||
std::cout << "}" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "\tlabel=\"" << ++i << ": Added (" << g[*it].x().to_double() << "," << g[*it].y().to_double() << ").";
|
||||
if (NULL != ri)
|
||||
std::cout << " -- (" << g[*ri].x().to_double() << "," << g[*ri].y().to_double() << ").";
|
||||
std::cout << "\";" << std::endl;
|
||||
std::cout << "\ttableloc=\"b\";" << std:: endl;
|
||||
std::cout << "}" << std::endl << std::endl;
|
||||
#endif
|
||||
#endif
|
||||
} // end of for
|
||||
}; // end of add edges in cone
|
||||
|
||||
}; // class Construct_theta_graph_2
|
||||
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
// Copyright (c) 2013-2015 The University of Western Sydney, Australia.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Authors: Weisheng Si, Quincy Tse
|
||||
|
||||
/*! \file Construct_yao_graph_2.h
|
||||
*
|
||||
* This header implements the functor for constructing Yao graphs.
|
||||
*/
|
||||
|
||||
#ifndef CGAL_CONSTRUCT_YAO_GRAPH_2_H
|
||||
#define CGAL_CONSTRUCT_YAO_GRAPH_2_H
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <utility>
|
||||
#include <CGAL/Compute_cone_boundaries_2.h>
|
||||
#include <CGAL/Cone_spanners_2/Less_by_direction_2.h>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
/*! \ingroup PkgConeBasedSpanners
|
||||
|
||||
\brief A template functor for constructing Yao graphs with a given set of 2D points and
|
||||
a given initial direction for the cone boundaries.
|
||||
|
||||
For the meaning and use of its template parameters, please refer to the concept
|
||||
`ConstructConeBasedSpanner_2`.
|
||||
|
||||
\cgalModels `ConstructConeBasedSpanner_2`
|
||||
*/
|
||||
template <typename Traits, typename Graph_>
|
||||
class Construct_yao_graph_2 {
|
||||
|
||||
public:
|
||||
/*! is the geometric traits which must be a model of the concept `ConeBasedSpannerTraits` */
|
||||
typedef Traits Geom_traits;
|
||||
/*! Indicate the specific type of `boost::adjacency_list`. */
|
||||
typedef Graph_ Graph_type;
|
||||
|
||||
private:
|
||||
typedef typename Geom_traits::Direction_2 Direction_2;
|
||||
typedef typename Geom_traits::Point_2 Point_2;
|
||||
typedef typename Geom_traits::Line_2 Line_2;
|
||||
typedef Less_by_direction_2<Geom_traits, Graph_> Less_by_direction;
|
||||
// a type for the set to store vertices sorted by a direction
|
||||
typedef std::set<typename Graph_::vertex_descriptor, Less_by_direction> Point_set;
|
||||
|
||||
/* Store the number of cones. */
|
||||
unsigned int cone_number;
|
||||
|
||||
/* Store the directions of the rays dividing the plane. The initial direction will be
|
||||
stored in rays[0]. */
|
||||
std::vector<Direction_2> rays;
|
||||
|
||||
public:
|
||||
/*!
|
||||
\brief Constructor.
|
||||
\details Constructs a `Construct_yao_graph_2` object.
|
||||
|
||||
\param k Number of cones to divide space into
|
||||
\param initial_direction A direction denoting one of the rays dividing the
|
||||
cones. This allows arbitary rotations of the rays that divide
|
||||
the plane. (default: positive x-axis)
|
||||
*/
|
||||
Construct_yao_graph_2 (unsigned int k,
|
||||
Direction_2 initial_direction = Direction_2(1,0)
|
||||
): cone_number(k), rays(std::vector<Direction_2>(k))
|
||||
|
||||
{
|
||||
if (k<2) {
|
||||
std::cout << "The number of cones must be larger than 1!" << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
/* Initialize a functor, specialization will happen here depending on the kernel type to
|
||||
compute the cone boundaries either exactly or inexactly */
|
||||
Compute_cone_boundaries_2<Geom_traits> compute_cones;
|
||||
// compute the rays using the functor
|
||||
compute_cones(k, initial_direction, rays.begin());
|
||||
}
|
||||
|
||||
/* \brief Copy constructor. Not needed.
|
||||
\param x another Construct_yao_graph_2 object to copy from.
|
||||
|
||||
Construct_yao_graph_2 (const Construct_yao_graph_2& x) : cone_number(x.cone_number), rays(x.rays) {}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\brief Operator to construct a Yao graph.
|
||||
|
||||
\details This operator implements the algorithm for constructing the Yao graph.
|
||||
The algorithm implemented is an adaptation from the algorithm for constructing Theta graph.
|
||||
For more details, please refer to the user manual.
|
||||
|
||||
\param[in] start An iterator pointing to the first vertex of the input.
|
||||
\param[in] end An iterator pointing to the past-the-end location of the input.
|
||||
\param[out] g The constructed graph object.
|
||||
*/
|
||||
template <typename PointInputIterator>
|
||||
Graph_& operator()(const PointInputIterator& start,
|
||||
const PointInputIterator& end,
|
||||
Graph_& g) {
|
||||
|
||||
// add vertices into the graph
|
||||
for (PointInputIterator curr = start; curr != end; ++curr) {
|
||||
g[boost::add_vertex(g)] = *curr;
|
||||
}
|
||||
|
||||
unsigned int i; // ray index of the cw ray
|
||||
unsigned int j; // index of the ccw ray
|
||||
|
||||
// add edges into the graph for every cone
|
||||
for (i = 0; i < cone_number; i++) {
|
||||
j = (i+1) % cone_number;
|
||||
add_edges_in_cone(rays[i], rays[j], g);
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
/*! \brief returns the number of cones.
|
||||
*/
|
||||
const unsigned int number_of_cones() const {
|
||||
return cone_number;
|
||||
}
|
||||
|
||||
/*! \brief outputs the directions in the vector rays to the iterator `result`.
|
||||
|
||||
\return the past-the-end iterator of the vector `rays`.
|
||||
*/
|
||||
template<class DirectionOutputIterator>
|
||||
DirectionOutputIterator directions(DirectionOutputIterator result) {
|
||||
typename std::vector<Direction_2>::iterator it;
|
||||
for (it=rays.begin(); it!=rays.end(); it++) {
|
||||
*result++ = *it;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/* Construct edges in one cone bounded by two directions.
|
||||
|
||||
\param cwBound The direction of the clockwise boundary of the cone.
|
||||
\param ccwBound The direction of the counter-clockwise boundary.
|
||||
\param g The Yao graph to be built.
|
||||
*/
|
||||
void add_edges_in_cone(const Direction_2& cwBound, const Direction_2& ccwBound, Graph_& g) {
|
||||
if (ccwBound == cwBound) {
|
||||
// Degenerate case, not allowed.
|
||||
throw std::out_of_range("The cw boundary and the ccw boundary shouldn't be same!");
|
||||
}
|
||||
|
||||
// Ordering
|
||||
// here D1 is the reverse of D1 in the book, we find this is easier to implement
|
||||
const Less_by_direction orderD1 (g, ccwBound);
|
||||
const Less_by_direction orderD2 (g, cwBound);
|
||||
|
||||
typename Graph_::vertex_iterator vit, ve;
|
||||
boost::tie(vit, ve) = boost::vertices(g);
|
||||
|
||||
// Step 1: Sort S according to order induced by D1
|
||||
std::vector<typename Graph_::vertex_descriptor> S(vit, ve);
|
||||
std::sort(S.begin (), S.end (), orderD1);
|
||||
|
||||
// Step 2: Initialise an empty set to store vertices sorted by orderD2
|
||||
Point_set pst(orderD2);
|
||||
|
||||
// Step 3: visit S in orderD1
|
||||
// insert 'it' into pst
|
||||
// search the min in pst
|
||||
for (typename std::vector<typename Graph_::vertex_descriptor>::const_iterator
|
||||
it = S.begin(); it != S.end(); ++it) {
|
||||
Less_euclidean_distance comp(g[*it], g);
|
||||
|
||||
pst.insert(*it);
|
||||
// Find the last added node - O(logn)
|
||||
typename Point_set::iterator it2 = pst.find(*it);
|
||||
// Find minimum in pst from last ended node - O(n)
|
||||
typename Point_set::iterator min = std::min_element(++it2, pst.end(), comp);
|
||||
// add an edge
|
||||
if (min != pst.end()) {
|
||||
typename Graph_::edge_descriptor existing_e;
|
||||
bool existing;
|
||||
// check whether the edge already exists
|
||||
boost::tie(existing_e, existing)=boost::edge(*it, *min, g);
|
||||
if (!existing)
|
||||
boost::add_edge(*it, *min, g);
|
||||
//else
|
||||
// std::cout << "Edge " << *it << ", " << *min << " already exists!" << std::endl;
|
||||
}
|
||||
|
||||
} // end of for
|
||||
|
||||
}; // end of add edges in cone
|
||||
|
||||
|
||||
/* Functor for comparing Euclidean distances of two vertices in a graph g to a given vertex.
|
||||
It is implemented by encapsulating the CGAL::has_smaller_distance_to_point() function.
|
||||
*/
|
||||
struct Less_euclidean_distance {
|
||||
const Point_2& p;
|
||||
const Graph_& g;
|
||||
|
||||
// constructor
|
||||
Less_euclidean_distance(const Point_2&p, const Graph_& g) : p(p), g(g) {}
|
||||
|
||||
// operator
|
||||
bool operator() (const typename Point_set::iterator::value_type& i, const typename Point_set::iterator::value_type& j) {
|
||||
const Point_2& p1 = g[i];
|
||||
const Point_2& p2 = g[j];
|
||||
return has_smaller_distance_to_point(p, p1, p2);
|
||||
}
|
||||
};
|
||||
|
||||
}; // class Construct_yao_graph_2
|
||||
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,245 @@
|
|||
// Copyright (c) 2013-2015 The University of Western Sydney, Australia.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s): Quincy Tse, Weisheng Si
|
||||
|
||||
/*! \file gnuplot_output_2.h
|
||||
*
|
||||
* This header implements the function that can generate data and script files for plotting
|
||||
* graphs by Gnuplot. This function requires that graphs be represented by boost::adjacency_list
|
||||
* with its template parameter VertexProperties set to CGAL::Point_2.
|
||||
*/
|
||||
|
||||
#ifndef GNUPLOT_OUTPUT_2_H
|
||||
#define GNUPLOT_OUTPUT_2_H
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
/* ------ Declarations go first, then implementations follow. ------ */
|
||||
|
||||
/*!
|
||||
* \brief Output a set of files used by Gnuplot to plot `g`.
|
||||
*
|
||||
* The files that are generated for Gnuplot are:
|
||||
* (1) prefix.v (vertex list)
|
||||
* (2) prefix.plt (Gnuplot script), This script will read
|
||||
* prefix.v as input to plot the vertex list. The edge list is also
|
||||
* included in this script.
|
||||
*
|
||||
* Notes:
|
||||
* (1) If these files already exists, this function will overwrite these
|
||||
* files.
|
||||
* (2) Parallel and self-edges cannot be plotted.
|
||||
*
|
||||
* \tparam Graph The type of the graph to be plotted. For this function to work,
|
||||
* the graph type must be `boost::adjacency_list` with `CGAL::Point_2`
|
||||
* as the `VertexProperties`.
|
||||
*
|
||||
* \param g A `boost::adjacency_list` graph with `CGAL::Point_2` as the VertexProperties to be plotted
|
||||
* \param prefix The prefix of the output files names
|
||||
*/
|
||||
template <typename Graph>
|
||||
void gnuplot_output_2 (const Graph& g, const std::string& prefix);
|
||||
|
||||
/*
|
||||
* \brief Compiles a multi-lined %string to draw the edges in \p g by Gnuplot.
|
||||
* Compiles an edge list in the following format:
|
||||
*
|
||||
* set arrow from (start x, start y) to (end x, end y)
|
||||
* ...
|
||||
*
|
||||
* NOTE: For undirected graphs, use "set style arrow nohead"; for directed graphs,
|
||||
* use "set style arrow head"
|
||||
*
|
||||
* \param g A boost::adjacency_list graph with CGAL::Point_2 as the VertexProperties to be plotted
|
||||
* \return The edge list string.
|
||||
*/
|
||||
template <typename Graph>
|
||||
std::string gnuplot_edge_list (const Graph& g);
|
||||
|
||||
/*
|
||||
* \brief Compiles a multi-lined %string representing the vertices in \p g.
|
||||
*
|
||||
* Compiles a vertex list in the following format:
|
||||
* x y
|
||||
* x y
|
||||
* ...
|
||||
*
|
||||
* \param g A boost::adjacency_list graph with CGAL::Point_2 as the VertexProperties to be plotted
|
||||
* \return The vertex list string.
|
||||
*/
|
||||
template <typename Graph>
|
||||
std::string gnuplot_vertex_list (const Graph& g);
|
||||
|
||||
/* This struct is defined to use partial specialization to generate arrow styles differently for
|
||||
* directed and undirected graphs.
|
||||
* Note: Need to use structs because C++ before 11 doesn't allow partial specialisation
|
||||
* for functions
|
||||
*/
|
||||
template <typename Graph, typename Directedness=typename Graph::directed_selector>
|
||||
struct Gnuplot_edges_2;
|
||||
|
||||
/* ------- IMPLEMENTATIONS ------- */
|
||||
|
||||
template <typename Graph>
|
||||
std::string gnuplot_edge_list (const Graph& g)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss.precision(3);
|
||||
ss << std::fixed; // Use fixed floating-point notation
|
||||
|
||||
typename Graph::edge_iterator eit, ee;
|
||||
for (boost::tie(eit, ee) = boost::edges(g); eit != ee; ++eit) {
|
||||
typename Graph::vertex_descriptor src = boost::source(*eit, g);
|
||||
typename Graph::vertex_descriptor end = boost::target(*eit, g);
|
||||
ss << "set arrow from ";
|
||||
ss << to_double(g[src].x()) << "," << to_double(g[src].y());
|
||||
ss << " to ";
|
||||
ss << to_double(g[end].x()) << "," << to_double(g[end].y());
|
||||
ss << " as 1" << std::endl;
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// Common regardless of whether g is directed.
|
||||
template <typename Graph>
|
||||
std::string gnuplot_vertex_list(const Graph& g) {
|
||||
std::stringstream ss;
|
||||
ss.precision(3);
|
||||
ss << std::fixed;
|
||||
|
||||
typename Graph::vertex_iterator vit, ve;
|
||||
for (boost::tie(vit, ve) = boost::vertices(g); vit != ve; ++vit) {
|
||||
ss << to_double(g[*vit].x()) << " " << to_double(g[*vit].y()) << std::endl;
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
void gnuplot_output_2 (const Graph& g, const std::string& prefix)
|
||||
{
|
||||
// Generate the vertex list to the .v file
|
||||
std::ofstream fs((prefix + ".v").c_str(),
|
||||
std::ofstream::out | std::ofstream::trunc);
|
||||
fs << gnuplot_vertex_list(g);
|
||||
fs.close();
|
||||
std::cout << prefix << ".v" << " is generated. " << std::endl;
|
||||
|
||||
// Generate the Gnuplot Script to the .plt file
|
||||
fs.open((prefix + ".plt").c_str(),
|
||||
std::ofstream::out | std::ofstream::trunc);
|
||||
fs << "set term ";
|
||||
// Choose one:
|
||||
fs << "wxt ";
|
||||
// fs << "postscript eps ";
|
||||
|
||||
fs << "font \", 9\" enhanced" << std::endl;
|
||||
|
||||
// Uncomment if eps:
|
||||
// fs << "set output \"" << prefix << ".eps\"" << std::endl;
|
||||
|
||||
fs << "set title" << std::endl;
|
||||
fs << "set xlabel # when no options, clear the xlabel" << std::endl;
|
||||
fs << "set ylabel" << std::endl;
|
||||
fs << "unset key" << std::endl;
|
||||
fs << "set size square" << std::endl;
|
||||
fs << "unset xtics" << std::endl;
|
||||
fs << "unset ytics" << std::endl;
|
||||
fs << "unset border" << std::endl;
|
||||
|
||||
/*
|
||||
ss << "set xtics" << std::endl;
|
||||
ss << "set ytics" << std::endl;
|
||||
ss << "set border" << std::endl;
|
||||
ss << "set grid xtics ytics" << std::endl;
|
||||
*/
|
||||
|
||||
fs << std::endl;
|
||||
// Specific part that depends on whether g is directed
|
||||
fs << Gnuplot_edges_2<Graph>::gnuplot_edge_script(g);
|
||||
fs << std::endl;
|
||||
|
||||
// plot the vertices
|
||||
fs << "plot \"" << prefix << ".v\" with points pt 7 ps 0.8 lt rgb \"blue\"" << std::endl;
|
||||
|
||||
// Uncomment if wxt and also want eps output:
|
||||
// fs << "set term postscript eps " << std::endl;
|
||||
// fs << "set output \"" << prefix << ".eps\"" << std::endl;
|
||||
// fs << "replot" << std::endl;
|
||||
|
||||
fs.close();
|
||||
std::cout << prefix << ".plt" << " is generated. " << std::endl;
|
||||
}
|
||||
|
||||
// directed graphs
|
||||
/* Writing edge list to the gnuplot script for directed graphs */
|
||||
template <typename Graph>
|
||||
struct Gnuplot_edges_2<Graph, boost::directedS> {
|
||||
|
||||
// Uses "set style arrow 1 head" to draw directed edges
|
||||
// Edges are written directly into the script file.
|
||||
static std::string gnuplot_edge_script(const Graph& g)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "set style arrow 1 head filled lc rgb \"black\"" << std::endl;
|
||||
ss << std::endl;
|
||||
ss << "# edges" << std::endl;
|
||||
ss << gnuplot_edge_list(g);
|
||||
ss << "# end of edges" << std::endl;
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
// Bidirectional graph, the same as the directed graph.
|
||||
/* Writing edge list to the gnuplot script for bidirectional graphs */
|
||||
template <typename Graph>
|
||||
struct Gnuplot_edges_2<Graph, boost::bidirectionalS> : public Gnuplot_edges_2<Graph, boost::directedS> {};
|
||||
|
||||
// Undirected graphs
|
||||
/* Writing edge list to the gnuplot script for undirected graphs */
|
||||
template <typename Graph>
|
||||
struct Gnuplot_edges_2<Graph, boost::undirectedS> {
|
||||
|
||||
static std::string gnuplot_edge_script(const Graph& g)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "set style arrow 1 nohead lc rgb \"black\"" << std::endl;
|
||||
ss << std::endl;
|
||||
ss << "# edges" << std::endl;
|
||||
ss << gnuplot_edge_list(g);
|
||||
ss << "# end of edges" << std::endl;
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1 @@
|
|||
University of Western Sydney (Australia)
|
||||
|
|
@ -0,0 +1 @@
|
|||
This package provides classes for constructing two kinds of cone-based spanners (Yao graph and Theta graph) given a set of vertices on the plane.
|
||||
|
|
@ -0,0 +1 @@
|
|||
GPL (v3 or later)
|
||||
|
|
@ -0,0 +1 @@
|
|||
This package provides classes for constructing two kinds of cone-based spanners (Yao graph and Theta graph) given a set of vertices on the plane. Both exact and inexact constructions are implemented. In exact construction, the cone boundaries are calculated using roots of polynomials (requiring `CORE::Expr` or `LEDA::real`). In inexact construction, the cone boundaries are calculated using an approximate Pi (3.14159265358979323846), which is still accurate enough for most applications. Moreover, for visualization purpose, this package provides functions to generate the data and script files used by Gnuplot to plot the constructed graphs.
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
Weisheng Si <w.si@uws.edu.au>
|
||||
Quincy Tse <quincy.tse@gmail.com>
|
||||
|
|
@ -358,6 +358,16 @@ Boissonnat}
|
|||
,update = "97.08 kettner"
|
||||
}
|
||||
|
||||
@article{ cgal:cht-oacov-90
|
||||
,author = {M. Chang and N. Huang and C. Tang}
|
||||
,title = {An optimal algorithm for constructing oriented Voronoi diagrams
|
||||
and geographic neighborhood graphs}
|
||||
,journal = "Information Processing Letters"
|
||||
,volume = 35
|
||||
,year = 1990
|
||||
,pages = {255--260}
|
||||
}
|
||||
|
||||
@article{ cgal:cp-edqpf-05,
|
||||
author="F. Cazals and M. Pouget",
|
||||
title="Estimating Differential Quantities using Polynomial fitting of Osculating Jets",
|
||||
|
|
@ -1466,6 +1476,13 @@ ABSTRACT = {We present the first complete, exact and efficient C++ implementatio
|
|||
,update = "97.04 kettner"
|
||||
}
|
||||
|
||||
@book{ cgal:ns-gsn-07
|
||||
,author = {G. Narasimhan and M. Smid}
|
||||
,title = {Geometric Spanner Networks}
|
||||
,publisher = {Cambridge University Press}
|
||||
,year = 2007
|
||||
}
|
||||
|
||||
@inproceedings{ cgal:o-dcgal-96
|
||||
,author = {Mark H. Overmars}
|
||||
,title = {Designing the Computational Geometry Algorithms
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ Matrix_search
|
|||
Box_intersection_d
|
||||
CGAL_ipelets
|
||||
Circulator
|
||||
Cone_spanners_2
|
||||
Convex_decomposition_3
|
||||
Convex_hull_2
|
||||
Convex_hull_3
|
||||
|
|
|
|||
|
|
@ -152,6 +152,8 @@ h1 {
|
|||
\package_listing{BGL}
|
||||
\package_listing{Solver_interface}
|
||||
\package_listing{Property_map}
|
||||
\package_listing{Cone_spanners_2}
|
||||
\package_listing{Point_set_processing_3/Property_map}
|
||||
\package_listing{Circulator}
|
||||
\package_listing{Generator}
|
||||
\package_listing{Miscellany}
|
||||
|
|
|
|||