mirror of https://github.com/CGAL/cgal
567 lines
23 KiB
Plaintext
567 lines
23 KiB
Plaintext
namespace CGAL {
|
|
/*!
|
|
|
|
\mainpage User Manual
|
|
\anchor Chapter_dD_Range_and_Segment_Trees
|
|
\anchor Trees
|
|
\cgalAutoToc
|
|
\author Gabriele Neyer
|
|
|
|
\section SearchStructuresIntroduction Introduction
|
|
|
|
This chapter presents the \cgal range tree and segment tree
|
|
data structures.
|
|
|
|
\section SearchStructuresDefinitions Definitions
|
|
|
|
This section presents ` d`-dimensional range and segment trees.
|
|
A one-dimensional range tree is a binary search tree on
|
|
<I>one-dimensional point data</I>.
|
|
Here we call all one-dimensional data types having a strict ordering
|
|
(like integer and double) <I>point data</I>.
|
|
<I>` d`-dimensional point data</I> are ` d`-tuples of one-dimensional
|
|
point data.
|
|
|
|
A one-dimensional segment tree is a binary search tree as well, but with
|
|
<I>one-dimensional interval data</I> as input data.
|
|
One-dimensional interval data is a pair (i.e., 2-tuple) ` (a,b)`, where ` a`
|
|
and ` b` are one-dimensional point data of the same type and ` a< b`.
|
|
The pair ` (a,b)` represents a half open interval ` [a,b)`.
|
|
Analogously, a ` d`-dimensional interval is represented by a ` d`-tuple of
|
|
one-dimensional intervals.
|
|
|
|
The <I>input data type</I> for a ` d`-dimensional tree is a container
|
|
class consisting of a ` d`-dimensional point data type, interval data type
|
|
or a mixture of both, and optionally a <I>value type</I>, which
|
|
can be used to store arbitrary data.
|
|
E.g., the ` d`-dimensional bounding box of a ` d`-dimensional polygon
|
|
may define the interval data of a ` d`-dimensional segment tree and
|
|
the polygon itself can be stored as its value.
|
|
An <I>input data item</I> is an instance of an input data type.
|
|
|
|
The range and segment tree classes are fully generic in the sense that they
|
|
can be used to define <I>multilayer trees</I>.
|
|
A multilayer tree of dimension (number of layers) ` d` is a simple tree in
|
|
the ` d`-th layer, whereas the ` k`-th layer, ` 1 <= k <= d-1`, of the tree
|
|
defines a tree where each (inner) vertex contains a multilayer tree of
|
|
dimension ` d-k+1`.
|
|
The ` k-1`-dimensional tree which is nested in the ` k`-dimensional tree
|
|
(` T`) is called the <I>sublayer tree</I> (of ` T`).
|
|
For example, a ` d`-dim tree can be a range tree on the first layer,
|
|
constructed with respect to the first dimension of ` d`-dimensional data
|
|
items.
|
|
On all the data items in each subtree, a ` (d-1)`-dimensional tree is built,
|
|
either a range or a segment tree, with respect to the second dimension of
|
|
the data items.
|
|
And so on.
|
|
|
|
The figures in Sections \ref secrange_trees and \ref secsegment_trees
|
|
illustrate the means of a sublayer tree graphically.
|
|
|
|
After creation of the tree, further insertions or deletions of data items
|
|
are disallowed.
|
|
The tree class does neither depend on the type of data nor on the concrete
|
|
physical representation of the data items.
|
|
E.g., let a multilayer tree be a segment tree for which each vertex
|
|
defines a range tree.
|
|
We can choose the data items to consist of intervals of type `double`
|
|
and the point data of type `integer`.
|
|
As value type we can choose `string`.
|
|
|
|
For this generality we have to
|
|
define what the tree of each dimension looks like and how the
|
|
input data is organized.
|
|
For dimension ` k`, ` 1 < k < 4`, \cgal provides ready-to-use
|
|
range and segment trees that can store k-dimensional keys
|
|
(intervals resp.).
|
|
Examples illustrating the use of these classes are given in
|
|
Sections \ref secrange_tree_ex
|
|
and \ref secsegment_tree_ex.
|
|
The description of the functionality of these classes as well as
|
|
the definition of higher dimensional trees and mixed multilayer
|
|
trees is given in the reference manual.
|
|
|
|
In the following two sections we give short definitions of the version of
|
|
the range tree and segment tree implemented here together with some
|
|
examples. The presentation closely follows \cgalCite{bkos-cgaa-97}.
|
|
|
|
\section SearchStructuresSoftware Software Design
|
|
|
|
In order to be able to define a multilayer tree we first
|
|
designed the range and segment tree to have a template argument
|
|
defining the type of the sublayer tree. With this sublayer tree
|
|
type information the sublayers could be created. This approach lead to nested
|
|
template arguments, since the sublayer tree can again have a template
|
|
argument defining the sublayer. Therefore, the internal class and function
|
|
identifiers got longer than a compiler-dependent limit.
|
|
This happend already for ` d=2`.
|
|
|
|
Therefore, we chose another, object oriented,
|
|
design. We defined a pure
|
|
virtual base class called `Tree_base` from which we derived
|
|
the classes `Range_tree_d` and `Segment_tree_d`.
|
|
The constructor of these classes expects an argument called
|
|
`sublayer_prototype` of type `Tree_base`.
|
|
Since class `Range_tree_d` and class
|
|
`Segment_tree_d` are derived from class `Tree_base`, one can
|
|
use an instantiation of class `Range_tree_d` or class
|
|
`Segment_tree_d` as constructor argument.
|
|
This argument defines the sublayer tree of the tree. E.g., you
|
|
can construct a `Range_tree_d` with an
|
|
instantiation of class `Segment_tree_d` as constructor
|
|
argument. You then have defined a range tree with a segment tree
|
|
as sublayer tree. Since both classes `Range_tree_d` and
|
|
`Segment_tree_d` expect a sublayer tree in their constructor
|
|
we had to derive a third class called `Tree_anchor` from
|
|
class `Tree_base` which
|
|
does not expect a constructor argument. An instantiation of this
|
|
class is used as constructor argument of class `Range_tree_d` or
|
|
`Segment_tree_d` in order to stop the recursion.
|
|
|
|
All classes provide a `clone()` function which returns an
|
|
instance (a copy) of the same tree type. The `clone()`
|
|
function of the `sublayer_prototype` is called in the
|
|
construction of the tree. In case that the sublayer tree again
|
|
has a sublayer, it also has a `sublayer_prototype` which is
|
|
also cloned and so on. Thus, a call to the `clone()` function
|
|
generates a sublayer tree which has the complete knowledge about
|
|
its sublayer tree.
|
|
|
|
The trees allow to perform
|
|
window queries, enclosing queries, and inverse range queries on
|
|
the keys. Clearly, an inverse range query makes only sense in the
|
|
segment tree.
|
|
In order to perform an inverse range query, a range query of
|
|
\f$ \epsilon\f$ width has to be performed. We preferred not to offer an
|
|
extra function for this sort of query, since the inverse range
|
|
query is a special case of the range query. Furthermore, offering
|
|
an inverse range query in the segment tree class implies offering this
|
|
function also in the range tree class and having an extra item in
|
|
the traits class that accesses the inverse range query point.
|
|
|
|
The trees are templatized with three arguments: `Data, Window`
|
|
and `Traits`. Type `Data` defines
|
|
the input data type and type `Window` defines the query
|
|
window type. The tree uses a well defined set of functions in
|
|
order to access data. These functions have to be provided by
|
|
class `Traits`.
|
|
|
|
The design partly follows the <I>prototype design pattern</I>
|
|
in \cgalCite{cgal:ghjv-dpero-95}. In comparison to our first approach
|
|
using templates we want to note the following: In this approach
|
|
the sublayer type is defined in
|
|
use of object oriented programming at run time, while in the
|
|
approach using templates, the sublayer type is defined at compile
|
|
time.
|
|
|
|
The runtime overhead caused in use of virtual member
|
|
functions in this object oriented design is negligible since all virtual
|
|
functions are non trivial.
|
|
|
|
The design concept is illustrated in the figure below.
|
|
|
|
\cgalFigureBegin{Search_rsd,rsd.png}
|
|
Design of the range and segment tree data structure. The symbol triangle means that the lower class is derived from the upper class.
|
|
\cgalFigureEnd
|
|
|
|
E.g. in order to define a two dimensional multilayer tree, which
|
|
consists of a range tree in the first dimension and a segment
|
|
tree in the second dimension we proceed as follows: We construct
|
|
an object of type `Tree_anchor` which stops the
|
|
recursion. Then we construct an object of type `Segment_tree_d`,
|
|
which gets as prototype argument our object of type
|
|
`Tree_anchor`. After that, we define an object of type
|
|
`Range_tree_d` which is constructed with the object of type
|
|
`Segment_tree_d` as prototype argument.
|
|
The following piece of code illustrates
|
|
the construction of the two-dimensional multilayer tree.
|
|
|
|
\code{.cpp}
|
|
int main(){
|
|
Tree_Anchor *anchor=new Tree_Anchor;
|
|
Segment_Tree_d *segment_tree = new Segment_Tree_d(*anchor);
|
|
Range_Tree_d *range_segment_tree = new Range_Tree_d(*segment_tree);
|
|
// let data_items be a list of Data items
|
|
range_segment_tree->make_tree(data_items.begin(),data_items.end());
|
|
}
|
|
\endcode
|
|
|
|
Here, class `Tree_Anchor, Segment_Tree_d`, and`Range_Tree_d` are defined by `typedef`s:
|
|
|
|
\code{.cpp}
|
|
typedef Tree_anchor<Data,Window> Tree_Anchor;
|
|
typedef Segment_tree_d<Data,Window,Interval_traits> Segment_Tree_d;
|
|
typedef Range_tree_d<Data,Window,Point_traits> Range_Tree_d;
|
|
\endcode
|
|
|
|
Class `Tree_base` and class
|
|
`Tree_anchor` get two template arguments: a class
|
|
`Data` which defines the type of data that is stored in
|
|
the tree, and a class `Window` which defines the type of a query
|
|
range.
|
|
The derived classes `Range_tree_d` and `Segment_tree_d`
|
|
additionally get an argument called
|
|
`Tree_traits` which defines the interface between the
|
|
`Data` and the tree. Let the `Data` type be a ` d`-dimensional
|
|
tuple, which is either a point data or an interval data in each
|
|
dimension. Then, the class `Tree_traits` provides accessors to
|
|
the point (resp. interval) data of that tree layer and a compare
|
|
function. Remind our example of the two-dimensional tree which
|
|
is a range tree in the first dimension and
|
|
a segment tree in the second dimension. Then, the
|
|
`Tree_traits` class template argument of class
|
|
`Segment_tree_d` defines an accessor to the interval data of
|
|
the `Data`, and the
|
|
`Tree_traits` class template argument of class
|
|
`Range_tree_d` defines an accessor to the point data of
|
|
`Data`.
|
|
An example implementation for these classes is listed below.
|
|
|
|
\code{.cpp}
|
|
struct Data{
|
|
int min,max; // interval data
|
|
double point; // point data
|
|
};
|
|
|
|
struct Window{
|
|
int min,max;
|
|
double min_point, max_point;
|
|
};
|
|
|
|
class Point_traits{
|
|
public:
|
|
typedef double Key;
|
|
Key get_key(Data& d){return d.point;} // key accesso
|
|
Key get_left(Window& w){return w.min_point;}
|
|
Key get_right(Window& w){return w.max_point;}
|
|
bool comp(Key& key1, Key& key2){return (key1 < key2);}
|
|
};
|
|
|
|
class Interval_traits{
|
|
public:
|
|
typedef int Key;
|
|
Key get_left(Data& d){return d.min;}
|
|
Key get_right(Data& d){return d.max;}
|
|
Key get_left_win(Window& w){return w.min;}
|
|
Key get_right_win(Window& w){return w.max;}
|
|
static bool comp(Key& key1, Key& key2){return (key1 < key2);}
|
|
};
|
|
\endcode
|
|
|
|
\section general Creating an Arbitrary Multilayer Tree
|
|
|
|
Now let us have a closer look on how a multilayer tree is built.
|
|
In case of creating a ` d`-dimensional tree, we handle a
|
|
sequence of arbitrary data
|
|
items, where each item defines a ` d`-dimensional interval, point
|
|
or other object. The tree is constructed with an iterator over
|
|
this structure. In the ` i`-th layer, the tree is
|
|
built with respect to the data slot that defines the ` i`-th
|
|
dimension. Therefore, we need to define which data slot
|
|
corresponds to which dimension.
|
|
In addition we want our tree to work with arbitrary data items.
|
|
This requires an
|
|
adaptor between the algorithm and the data item. This is resolved
|
|
by the use of traits classes, implemented in
|
|
form of a traits class using
|
|
function objects.
|
|
These classes provide
|
|
access functions to a specified data slot of a data item.
|
|
A ` d`-dimensional tree is then defined separately for each layer by
|
|
defining a traits class for each layer.
|
|
|
|
\section secrange_trees Range Trees
|
|
|
|
A one-dimensional range tree is a binary search tree on one-dimensional
|
|
point data.
|
|
The point data of the tree is stored in the leaves.
|
|
Each inner vertex stores the highest entry of its left subtree.
|
|
The version of a range tree implemented here is static, which means that
|
|
after construction of the tree, no elements be inserted or deleted.
|
|
A ` d`-dimensional range tree is a binary leaf search tree according to the
|
|
first dimension of the ` d`-dimensional point data, where each vertex contains
|
|
a ` (d-1)`-dimensional search tree of the points in the subtree (sublayer tree)
|
|
with respect to the second dimension.
|
|
See \cgalCite{bkos-cgaa-97} and \cgalCite{s-dasds-90} for more detailed information.
|
|
|
|
A ` d`-dimensional range tree can be used to determine all
|
|
` d`-dimensional points that lie inside a given ` d`-dimensional
|
|
interval (`window_query`).
|
|
|
|
The pictures below show a two-dimensional and a `d`-dimensional range tree.
|
|
|
|
\cgalFigureBegin{Search_range2,range2.png}
|
|
A two and a d-dimensional range tree.
|
|
\cgalFigureEnd
|
|
|
|
The 2-dimensional tree is a binary search tree on the first dimension. Each sublayer tree of a vertex `v` is a binary search tree on the second dimension. The data items in a sublayer tree of `v` are all data items of the subtree of `v`.
|
|
|
|
For the d-dimensional range tree, the figure shows one sublayer tree for each
|
|
layer of the tree.
|
|
|
|
The tree can be built in \f$ O(n\log^{d-1} n)\f$ time and
|
|
needs \f$ O(n\log^{d-1} n)\f$ space. The ` d`-dimensional points that lie in the
|
|
` d`-dimensional query interval can be reported in \f$ O(\log^dn+k)\f$ time,
|
|
where ` n` is the total number of points and ` k` is the number of
|
|
reported points.
|
|
|
|
\subsection secrange_tree_ex Example for Range Tree on Map-like Data
|
|
|
|
The following example program uses the predefined `Range_tree_2` data structure together with the predefined traits
|
|
class `Range_tree_map_traits_2` which has two template
|
|
arguments specifying the
|
|
type of the point data in each dimension
|
|
(`Cartesian<double>`) and the value type of the
|
|
2-dimensional point data (`char`). Therefore the `Range_tree_2` is defined on 2-dimensional point data each of which is
|
|
associated with a character.
|
|
Then, a few data items are created and put into a list. After
|
|
that the tree is constructed according to that list, a window
|
|
query is performed, and the query elements are given out.
|
|
|
|
\code{.cpp}
|
|
#include <CGAL/Cartesian.h>
|
|
#include <CGAL/Range_segment_tree_traits.h>
|
|
#include <CGAL/Range_tree_k.h>
|
|
|
|
typedef CGAL::Cartesian<double> K;
|
|
typedef CGAL::Range_tree_map_traits_2<K, char> Traits;
|
|
typedef CGAL::Range_tree_2<Traits> Range_tree_2_type;
|
|
|
|
int main()
|
|
{
|
|
typedef Traits::Key Key;
|
|
typedef Traits::Interval Interval;
|
|
|
|
std::vector<Key> InputList, OutputList;
|
|
InputList.push_back(Key(K::Point_2(8,5.1), 'a'));
|
|
InputList.push_back(Key(K::Point_2(1,1.1), 'b'));
|
|
InputList.push_back(Key(K::Point_2(3,2.1), 'c'));
|
|
|
|
Range_tree_2_type Range_tree_2(InputList.begin(),InputList.end());
|
|
Interval win(Interval(K::Point_2(4,8.1),K::Point_2(5,8.2)));
|
|
std::cout << "\n Window Query:\n ";
|
|
Range_tree_2.window_query(win, std::back_inserter(OutputList));
|
|
std::vector<Key>::iterator current=OutputList.begin();
|
|
while(current!=OutputList.end()){
|
|
std::cout << (*current).first.x() << "," << (*current).first.y()
|
|
<< ":" << (*current++).second << std::endl;
|
|
}
|
|
}
|
|
\endcode
|
|
|
|
\subsection SearchStructuresExampleforRangeTreeonSetlike Example for Range Tree on Set-like Data
|
|
|
|
This example illustrates the use of the range tree on
|
|
2-dimensional point data (no value is associated to a data item).
|
|
After the definition of the tree, some input data items are
|
|
created and the tree is constructed according to the input data
|
|
items.
|
|
After that, a window query is performed and the query elements
|
|
are given to standard out.
|
|
|
|
\code{.cpp}
|
|
#include <CGAL/Cartesian.h>
|
|
#include <CGAL/Range_segment_tree_traits.h>
|
|
#include <CGAL/Range_tree_k.h>
|
|
|
|
typedef CGAL::Cartesian<double> K;
|
|
typedef CGAL::Range_segment_tree_set_traits_2<K> Traits;
|
|
typedef CGAL::Range_tree_2<Traits> Range_tree_2_type;
|
|
|
|
int main()
|
|
{
|
|
typedef Traits::Key Key;
|
|
typedef Traits::Interval Interval;
|
|
std::vector<Key> InputList, OutputList;
|
|
std::vector<Key>::iterator first, last, current;
|
|
|
|
InputList.push_back(Key(8,5.1));
|
|
InputList.push_back(Key(1,1.1));
|
|
InputList.push_back(Key(3,2.1));
|
|
|
|
Range_tree_2_type Range_tree_2(InputList.begin(),InputList.end());
|
|
|
|
Interval win=Interval(Key(4,8.1),Key(5,8.2));
|
|
std::cout << std::endl << "Window Query: lower left point: (4.0,5.0),";
|
|
std::cout << "upper right point: (8.1,8.2)" << std::endl;
|
|
Range_tree_2.window_query(win, std::back_inserter(OutputList));
|
|
current=OutputList.begin();
|
|
while(current!=OutputList.end()){
|
|
std::cout << (*current).x()<< "-" << (*current).y() << std::endl;
|
|
current++;
|
|
}
|
|
}
|
|
\endcode
|
|
|
|
\section secsegment_trees Segment Trees
|
|
|
|
A segment tree is a static binary search tree for a given set of
|
|
coordinates. The set of coordinates is defined by the endpoints
|
|
of the input data intervals. Any two adjacent coordinates
|
|
build an elementary interval. Every leaf corresponds to an
|
|
elementary interval.
|
|
Inner vertices
|
|
correspond to the union of the subtree intervals of the vertex.
|
|
Each vertex or leaf ` v` contains a sublayer type (or a
|
|
list, if it is one-dimensional) that will contain all intervals ` I`, such that
|
|
` I` contains the interval of vertex ` v` but not the interval
|
|
of the parent vertex of ` v`.
|
|
|
|
A ` d`-dimensional segment tree can be used to solve the following problems:
|
|
<UL>
|
|
<LI>Determine all ` d`-dimensional intervals that contain a
|
|
` d`-dimensional point. This query type is called *inverse range query*.
|
|
<LI>Determine all ` d`-dimensional intervals that enclose a
|
|
given ` d`-dimensional interval
|
|
(*enclosing query*).
|
|
<LI>Determine all ` d`-dimensional intervals that partially overlap or are
|
|
contained in a given ` d`-dimensional interval (*window query*).
|
|
</UL>
|
|
|
|
An example of a one-dimensional segment tree and an example
|
|
of a two-dimensional segment tree are shown below.
|
|
|
|
\cgalFigureBegin{Search_segment2,segment2.png}
|
|
A one and a two dimensional segment tree
|
|
\cgalFigureEnd
|
|
|
|
For the one-dimensional segment
|
|
tree the segments and the corresponding elementary intervals
|
|
are shown below the tree. The arcs from the nodes point to
|
|
their subsets.
|
|
|
|
For the two-dimensional segment
|
|
tree we see that the first layer of the tree is built according to the
|
|
elementary intervals of the first dimension. Each
|
|
sublayer tree of a vertex `v` is a segment tree according to
|
|
the second dimension of all data items of `v`.
|
|
|
|
|
|
The tree can be built in \f$ O(n\log^{d} n)\f$ time and
|
|
needs \f$ O(n\log^{d} n)\f$ space.
|
|
The processing time for inverse range
|
|
queries in an ` d`-dimensional segment tree is \f$ O(\log^d n
|
|
+k)\f$ time, where ` n` is the total number of intervals and ` k` is
|
|
the number of reported intervals.
|
|
|
|
One possible application of a two-dimensional segment tree is the
|
|
following. Given a set of convex polygons in two-dimensional
|
|
space (Polygon_2), we want to determine all polygons
|
|
that intersect a given rectangular query window. Therefore, we define a
|
|
two-dimensional segment tree, where the two-dimensional interval of
|
|
a data item corresponds to the bounding box of a polygon and the
|
|
value type corresponds to the polygon itself. The segment tree is created
|
|
with a sequence of all data items, and a window query is
|
|
performed. The polygons of the resulting data items are finally
|
|
tested independently for intersections.
|
|
|
|
\subsection secsegment_tree_ex Example for Segment Tree on Map-like Data
|
|
|
|
The following example program uses the predefined `Segment_tree_2` data structure together with the predefined traits
|
|
class `Segment_tree_map_traits_2` which has two template arguments
|
|
specifying the
|
|
type of the point data in each dimension
|
|
(`Cartesian<double>`) and the value type of the
|
|
2-dimensional point data (`char`). Therefore the `Segment_tree_2` is defined on 2-dimensional point data
|
|
(`Point_2<Cartesian<double> >`) each of which is
|
|
associated with a character.
|
|
Then, a few data items are created and put into a list. After
|
|
that the tree is constructed according to that list, a window
|
|
query is performed, and the query elements are given out.
|
|
|
|
\code{.cpp}
|
|
#include <CGAL/Cartesian.h>
|
|
#include <CGAL/Segment_tree_k.h>
|
|
#include <CGAL/Range_segment_tree_traits.h>
|
|
|
|
typedef CGAL::Cartesian<double> K;
|
|
typedef CGAL::Segment_tree_map_traits_2<K, char> Traits;
|
|
typedef CGAL::Segment_tree_2<Traits > Segment_tree_2_type;
|
|
|
|
int main()
|
|
{
|
|
typedef Traits::Interval Interval;
|
|
typedef Traits::Pure_interval Pure_interval;
|
|
typedef Traits::Key Key;
|
|
std::list<Interval> InputList, OutputList1, OutputList2;
|
|
|
|
InputList.push_back(Interval(Pure_interval(Key(1,5), Key(2,7)),'a'));
|
|
InputList.push_back(Interval(Pure_interval(Key(2,7), Key(3,8)),'b'));
|
|
InputList.push_back(Interval(Pure_interval(Key(6,9), Key(9,13)),'c'));
|
|
InputList.push_back(Interval(Pure_interval(Key(1,3), Key(3,9)),'d'));
|
|
|
|
Segment_tree_2_type Segment_tree_2(InputList.begin(),InputList.end());
|
|
|
|
Interval a=Interval(Pure_interval(Key(3,6), Key(7,12)),'e');
|
|
Segment_tree_2.window_query(a,std::back_inserter(OutputList1));
|
|
|
|
std::list<Interval>::iterator j = OutputList1.begin();
|
|
std::cout << "\n window_query (3,6),(7,12)\n";
|
|
while(j!=OutputList1.end()){
|
|
std::cout << (*j).first.first.x() << "-" << (*j).first.second.x() << " "
|
|
<< (*j).first.first.y() << "-" << (*j).first.second.y() << std::endl;
|
|
j++;
|
|
}
|
|
|
|
Interval b=Interval(Pure_interval(Key(6,10),Key(7,11)), 'f');
|
|
Segment_tree_2.enclosing_query(b,std::back_inserter(OutputList2));
|
|
j = OutputList2.begin();
|
|
std::cout << "\n enclosing_query (6,10),(7,11)\n";
|
|
while(j!=OutputList2.end()){
|
|
std::cout << (*j).first.first.x() << "-" << (*j).first.second.x() << " "
|
|
<< (*j).first.first.y() << "-" << (*j).first.second.y() << std::endl;
|
|
j++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
\endcode
|
|
|
|
\subsection SearchStructuresExampleforSegmentTreeonSetlike Example for Segment Tree on Set-like Data
|
|
|
|
This example illustrates the use of the predefined segment tree
|
|
on 3-dimensional interval data (with no value associated). After
|
|
the definition of the traits type and tree type, some intervals
|
|
are constructed and the tree is build according to the
|
|
intervals. Then, a window query is performed and the query
|
|
elements are given out.
|
|
|
|
\code{.cpp}
|
|
#include <CGAL/Cartesian.h>
|
|
#include <CGAL/Segment_tree_k.h>
|
|
#include <CGAL/Range_segment_tree_traits.h>
|
|
|
|
typedef CGAL::Cartesian<int> K;
|
|
typedef CGAL::Range_segment_tree_set_traits_3<K> Traits;
|
|
typedef CGAL::Segment_tree_3<Traits > Segment_tree_3_type;
|
|
|
|
int main()
|
|
{
|
|
typedef Traits::Interval Interval;
|
|
typedef Traits::Key Key;
|
|
std::list<Interval> InputList, OutputList;
|
|
|
|
InputList.push_back(Interval(Key(1,5,7), Key(2,7,9)));
|
|
InputList.push_back(Interval(Key(2,7,6), Key(3,8,9)));
|
|
InputList.push_back(Interval(Key(6,9,5), Key(9,13,8)));
|
|
InputList.push_back(Interval(Key(1,3,4), Key(3,9,8)));
|
|
|
|
Segment_tree_3_type Segment_tree_3(InputList.begin(),InputList.end());
|
|
|
|
Interval a(Key(3,6,5), Key(7,12,8));
|
|
Segment_tree_3.window_query(a,std::back_inserter(OutputList));
|
|
std::list<Interval>::iterator j = OutputList1.begin();
|
|
std::cout << "\n window_query (3,6,5),(7,12,8) \n";
|
|
while(j!=OutputList.end()){
|
|
std::cout << (*j).first.x() << "," << (*j).first.y() << ",";
|
|
std::cout << (*j).first.z() <<", " << (*j).second.x() << ",";
|
|
std::cout << (*j).second.y() << "," << (*j).second.z() << std::endl;
|
|
j++;
|
|
}
|
|
}
|
|
\endcode
|
|
|
|
*/
|
|
} /* namespace CGAL */
|
|
|