732 lines
20 KiB
C++
Executable File
732 lines
20 KiB
C++
Executable File
// Copyright (c) 1997 ETH Zurich (SwitzerlanBd).
|
|
// 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$
|
|
// SPDX-License-Identifier: GPL-3.0+
|
|
//
|
|
//
|
|
// Author(s) : Gabriele Neyer
|
|
|
|
#ifndef CGAL_SEGMENT_TREE_D_H
|
|
#define CGAL_SEGMENT_TREE_D_H
|
|
|
|
#include <CGAL/license/SearchStructures.h>
|
|
|
|
|
|
#include <iostream>
|
|
#include <iterator>
|
|
#include <algorithm>
|
|
#include <list>
|
|
#include <vector>
|
|
#include <CGAL/Tree_base.h>
|
|
|
|
// A d-dimensional Segment Tree or a multilayer tree consisting of a Segment
|
|
// and other trees that are derived public Tree_base<C_Data, C_Window,
|
|
// C_Interface> can be constructed within this class.
|
|
// C_Data: container class which contains the d-dim data the tree holds.
|
|
// C_Window: Query window -- a d-dimensional interval
|
|
// C_Interface: Interface for the class with functions that allow to access the
|
|
// data. cf. file _interface.h for the requirements.
|
|
|
|
namespace CGAL {
|
|
|
|
template <class C_Data, class C_Window, class C_Interface>
|
|
class Segment_tree_d;
|
|
|
|
template <class C_Data, class C_Window, class C_Interface>
|
|
struct Segment_tree_node
|
|
: public Tree_node_base<Segment_tree_node<C_Data, C_Window, C_Interface> >
|
|
{
|
|
typedef C_Data Data;
|
|
typedef C_Window Window;
|
|
typedef typename C_Interface::Key Key;
|
|
typedef C_Interface Interface;
|
|
typedef Tree_base< C_Data, C_Window> Tree_base_type;
|
|
std::list< C_Data> objects;
|
|
Key left_key;
|
|
Key right_key;
|
|
Tree_base<C_Data, C_Window> *sublayer;
|
|
public:
|
|
friend class Segment_tree_d< C_Data, C_Window, C_Interface>;
|
|
|
|
typedef Tree_node_base<Segment_tree_node<C_Data, C_Window, C_Interface> > Base;
|
|
|
|
Segment_tree_node()
|
|
: sublayer(0)
|
|
{}
|
|
|
|
Segment_tree_node(const Key& p_left_key,
|
|
const Key& p_right_key)
|
|
: left_key(p_left_key), right_key(p_right_key), sublayer(0)
|
|
{}
|
|
|
|
Segment_tree_node(Segment_tree_node * p_left,
|
|
Segment_tree_node * p_right,
|
|
const Key& p_left_key,
|
|
const Key& p_right_key)
|
|
: Base(p_left,p_right), left_key(p_left_key), right_key(p_right_key), sublayer(0)
|
|
{}
|
|
|
|
~Segment_tree_node(){
|
|
objects.clear();
|
|
if (sublayer != 0)//(tree_base_type *)
|
|
delete sublayer;
|
|
}
|
|
};
|
|
|
|
|
|
template <class C_Data, class C_Window, class C_Interface>
|
|
class Segment_tree_d: public Tree_base< C_Data, C_Window>
|
|
{
|
|
private:
|
|
typedef C_Data Data;
|
|
typedef C_Window Window;
|
|
typedef typename C_Interface::Key Key;
|
|
typedef C_Interface Interface;
|
|
public:
|
|
typedef Tree_base<C_Data, C_Window> tbt;
|
|
protected:
|
|
Tree_base<C_Data, C_Window> *sublayer_tree;
|
|
|
|
// type of a vertex
|
|
// struct Segment_tree_node;
|
|
|
|
friend struct Segment_tree_node<C_Data,C_Window,C_Interface>;
|
|
typedef Segment_tree_node<C_Data,C_Window,C_Interface> Segment_tree_node_t;
|
|
typedef Segment_tree_node<C_Data,C_Window,C_Interface> *link_type;
|
|
|
|
typedef std::allocator<Segment_tree_node_t> allocator_type;
|
|
allocator_type alloc;
|
|
|
|
C_Interface m_interface;
|
|
bool is_built;
|
|
|
|
|
|
bool is_less_equal(const Key& x, const Key& y) const
|
|
{
|
|
return (!m_interface.comp(y,x));
|
|
}
|
|
|
|
static link_type left(link_type x) {
|
|
return x->left_link;
|
|
}
|
|
static link_type right(link_type x) {
|
|
return x->right_link;
|
|
}
|
|
static link_type parent(link_type x) {
|
|
return x->parent_link;
|
|
}
|
|
|
|
link_type header;
|
|
link_type node;
|
|
link_type rightmost(){return right(header);}
|
|
link_type leftmost(){return left(header);}
|
|
link_type root() const{
|
|
if(header!=0)
|
|
return header->parent_link;
|
|
return 0;
|
|
}
|
|
|
|
// returns true, if the object lies inside of win
|
|
bool is_inside( C_Window const &win, C_Data const& object) const
|
|
{
|
|
if(is_less_equal(m_interface.get_left_win(win), m_interface.get_left(object))
|
|
&& is_less_equal(m_interface.get_right(object),
|
|
m_interface.get_right_win(win)))
|
|
{
|
|
return sublayer_tree->is_inside(win,object);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// this tree is not a recursion anchor
|
|
bool is_anchor() const
|
|
{ return false;}
|
|
|
|
void insert_segment(link_type v, C_Data& element)
|
|
{
|
|
if ((is_less_equal(m_interface.get_left(element), v->left_key) &&
|
|
is_less_equal(v->right_key, m_interface.get_right(element)))
|
|
|| left(v)==CGAL_TREE_BASE_NULL)
|
|
v->objects.push_back( element);
|
|
else
|
|
{
|
|
if (!is_less_equal((*left(v)).right_key, m_interface.get_left(element)))
|
|
insert_segment(left(v), element);
|
|
if (!is_less_equal(m_interface.get_right(element), (*right(v)).left_key))
|
|
insert_segment(right(v), element);
|
|
}
|
|
}
|
|
|
|
// according to the list of elements at vertex v, a sublayer tree for these
|
|
// elements is created.
|
|
void build_next_dimension(link_type v)
|
|
{
|
|
if(left(v)!=CGAL_TREE_BASE_NULL)
|
|
{
|
|
build_next_dimension(left(v));
|
|
build_next_dimension(right(v));
|
|
}
|
|
if(! v->objects.empty())
|
|
{
|
|
typename std::list< C_Data>::iterator sub_first = v->objects.begin();
|
|
typename std::list< C_Data>::iterator sub_last = v->objects.end();
|
|
|
|
Tree_base<C_Data, C_Window> *g = sublayer_tree->clone();
|
|
g->make_tree(sub_first, sub_last);
|
|
v->sublayer = g;
|
|
if (!v->sublayer->is_anchor())
|
|
{
|
|
v->objects.clear();
|
|
}
|
|
}
|
|
}
|
|
|
|
link_type new_Segment_tree_node_t(link_type l, link_type r, const Key& kl, const Key& kr)
|
|
{
|
|
Segment_tree_node_t node(l,r,kl,kr);
|
|
Segment_tree_node_t* node_ptr = alloc.allocate(1);
|
|
#ifdef CGAL_CXX11
|
|
std::allocator_traits<allocator_type>::construct(alloc, node_ptr, node);
|
|
#else
|
|
alloc.construct(node_ptr, node);
|
|
#endif
|
|
return node_ptr;
|
|
}
|
|
|
|
link_type new_Segment_tree_node_t(const Key& kl, const Key& kr)
|
|
{
|
|
Segment_tree_node_t node(kl,kr);
|
|
Segment_tree_node_t* node_ptr = alloc.allocate(1);
|
|
#ifdef CGAL_CXX11
|
|
std::allocator_traits<allocator_type>::construct(alloc, node_ptr, node);
|
|
#else
|
|
alloc.construct(node_ptr, node);
|
|
#endif
|
|
return node_ptr;
|
|
}
|
|
|
|
link_type new_Segment_tree_node_t()
|
|
{
|
|
Segment_tree_node_t node;
|
|
Segment_tree_node_t* node_ptr = alloc.allocate(1);
|
|
#ifdef CGAL_CXX11
|
|
std::allocator_traits<allocator_type>::construct(alloc, node_ptr, node);
|
|
#else
|
|
alloc.construct(node_ptr, node);
|
|
#endif
|
|
return node_ptr;
|
|
}
|
|
|
|
// the skeleton of the segment tree is constructed here.
|
|
void build_segment_tree(int n, link_type& leftchild, link_type& rightchild,
|
|
link_type& prevchild, link_type& leftmostlink,
|
|
int& index, int last, const std::vector<Key>& keys)
|
|
{
|
|
// only two elements ==> two leaves and a parent is constructed
|
|
if (n==2)
|
|
{
|
|
link_type vright;
|
|
link_type vleft = new_Segment_tree_node_t
|
|
(keys[index], keys[index+1]);
|
|
index++;
|
|
if(index+1>last)
|
|
{
|
|
vright = new_Segment_tree_node_t
|
|
(keys[index], keys[index]);
|
|
}
|
|
else
|
|
{
|
|
vright = new_Segment_tree_node_t
|
|
(keys[index], keys[index+1]);
|
|
}
|
|
index++;
|
|
link_type vparent = new_Segment_tree_node_t
|
|
(vleft, vright, vleft->left_key, vright->right_key);
|
|
|
|
vleft->parent_link = vparent;
|
|
vright->parent_link = vparent;
|
|
leftchild = vleft;
|
|
rightchild = vright;
|
|
prevchild = vparent;
|
|
if(leftmostlink == CGAL_TREE_BASE_NULL)
|
|
leftmostlink = leftchild;
|
|
}
|
|
else
|
|
// only one element ==> one leaf is constructed
|
|
if(n==1)
|
|
{
|
|
link_type vright;
|
|
if(index+1 > last){
|
|
vright = new_Segment_tree_node_t
|
|
(keys[index], keys[index]);
|
|
}
|
|
else{
|
|
vright = new_Segment_tree_node_t
|
|
(keys[index], keys[index+1]);
|
|
}
|
|
index++;
|
|
|
|
prevchild = vright;
|
|
rightchild = vright;
|
|
}
|
|
else
|
|
{
|
|
// recursiv call for the construction. the interval is devided.
|
|
build_segment_tree(n - (int)n/2, leftchild, rightchild,
|
|
prevchild, leftmostlink, index, last, keys);
|
|
link_type vparent = new_Segment_tree_node_t
|
|
(prevchild, CGAL_TREE_BASE_NULL, prevchild->left_key, prevchild->left_key);
|
|
prevchild->parent_link = vparent;
|
|
build_segment_tree((int)n/2, leftchild, rightchild,
|
|
prevchild, leftmostlink, index, last, keys);
|
|
vparent->right_link = prevchild;
|
|
prevchild->parent_link = vparent;
|
|
vparent->right_key = prevchild->right_key;
|
|
prevchild = vparent;
|
|
}
|
|
}
|
|
|
|
void delete_tree(link_type v)
|
|
{
|
|
if(v->left_link!=CGAL_TREE_BASE_NULL)
|
|
{
|
|
delete_tree(left(v));
|
|
delete_tree(right(v));
|
|
}
|
|
delete_node(v);
|
|
}
|
|
|
|
void delete_node(Segment_tree_node_t* node_ptr)
|
|
{
|
|
#ifdef CGAL_CXX11
|
|
std::allocator_traits<allocator_type>::destroy(alloc, node_ptr);
|
|
#else
|
|
alloc.destroy(node_ptr);
|
|
#endif
|
|
alloc.deallocate(node_ptr,1);
|
|
}
|
|
|
|
// all elements that contain win are inserted into result
|
|
template <class A>
|
|
inline
|
|
A enclosing_query( C_Window const &win,
|
|
A result,
|
|
link_type v)
|
|
{
|
|
if(is_less_equal(m_interface.get_right_win(win), v->left_key)
|
|
|| is_less_equal(v->right_key,m_interface.get_left_win(win)))
|
|
return result;
|
|
if (v->sublayer!=0 && (!v->sublayer->is_anchor())) //(tree_base_type *)
|
|
{
|
|
Tree_base<C_Data, C_Window> *T = v->sublayer;
|
|
|
|
std::list< C_Data> tmp_result;
|
|
std::back_insert_iterator<std::list< C_Data> > tmp_back_inserter =
|
|
std::back_inserter(tmp_result);
|
|
T->enclosing_query(win, tmp_back_inserter);
|
|
typename std::list< C_Data>::iterator tmp = tmp_result.begin();
|
|
while(tmp!=tmp_result.end())
|
|
{
|
|
if(is_less_equal(m_interface.get_left(*tmp),
|
|
m_interface.get_left_win(win)))
|
|
{
|
|
if(is_less_equal(m_interface.get_right_win(win),
|
|
m_interface.get_right(*tmp)))
|
|
if(is_less_equal(v->left_key, m_interface.get_left_win(win)))
|
|
*result++=(*tmp);
|
|
}
|
|
tmp++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(! v->objects.empty())
|
|
{
|
|
typename std::list< C_Data>::iterator j=v->objects.begin();
|
|
while (j!= v->objects.end())
|
|
{
|
|
if(is_less_equal(m_interface.get_left(*j),
|
|
m_interface.get_left_win(win)))
|
|
{
|
|
if(is_less_equal(m_interface.get_right_win(win),
|
|
m_interface.get_right(*j)))
|
|
if(is_less_equal(v->left_key, m_interface.get_left_win(win)))
|
|
*result++=(*j);
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
if(left(v))
|
|
{
|
|
enclosing_query(win, result, left(v));
|
|
enclosing_query(win, result, right(v));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
// all elements that habe non empty intersection with win are put into result
|
|
template <class A>
|
|
inline
|
|
A window_query( C_Window const &win,
|
|
A result,
|
|
const link_type& v) // af: was not const
|
|
{
|
|
if(is_less_equal(m_interface.get_right_win(win), v->left_key) ||
|
|
is_less_equal(v->right_key,m_interface.get_left_win(win)))
|
|
return result;
|
|
if (v->sublayer!=0 && (!v->sublayer->is_anchor())) //(tree_base_type *)
|
|
{
|
|
Tree_base<C_Data, C_Window> *T = v->sublayer;
|
|
|
|
std::list< C_Data> tmp_result;
|
|
std::back_insert_iterator<std::list< C_Data> > tmp_back_inserter =
|
|
std::back_inserter(tmp_result);
|
|
T->window_query(win, tmp_back_inserter);
|
|
typename std::list< C_Data>::iterator tmp = tmp_result.begin();
|
|
while(tmp!=tmp_result.end())
|
|
{
|
|
if(m_interface.comp(m_interface.get_left(*tmp),
|
|
m_interface.get_left_win(win)))
|
|
{
|
|
if(is_less_equal(v->left_key, m_interface.get_left_win(win))){
|
|
*result++=(*tmp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(is_less_equal(v->left_key,m_interface.get_left(*tmp))){
|
|
*result++=(*tmp);
|
|
}
|
|
}
|
|
tmp++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(! v->objects.empty())
|
|
{
|
|
typename std::list< C_Data>::iterator j=v->objects.begin();
|
|
while (j!= v->objects.end())
|
|
{
|
|
if(m_interface.comp(m_interface.get_left(*j), m_interface.get_left_win(win)))
|
|
{
|
|
if(is_less_equal(v->left_key, m_interface.get_left_win(win)))
|
|
{
|
|
*result++=(*j);
|
|
}
|
|
}
|
|
else
|
|
if(is_less_equal(v->left_key,m_interface.get_left(*j)))
|
|
{
|
|
*result++=(*j);
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
if(left(v))
|
|
{
|
|
window_query(win, result, left(v));
|
|
window_query(win, result, right(v));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
bool is_valid(const link_type& v) const // af:was not const reference
|
|
{
|
|
if (v->sublayer != 0)//(tree_base_type *)
|
|
{
|
|
Tree_base<C_Data, C_Window> *T=v->sublayer;
|
|
if(! T->is_valid())
|
|
return false;
|
|
}
|
|
if(left(v)!=CGAL_TREE_BASE_NULL)
|
|
{
|
|
if(!is_valid(left(v)))
|
|
return false;
|
|
if(!is_valid(right(v)))
|
|
return false;
|
|
}
|
|
if(! v->objects.empty())
|
|
{
|
|
// true falls das Object das Segment enthaelt,
|
|
// der parent aber das Segment nicht enthaelt.
|
|
typename std::list< C_Data>::iterator j=v->objects.begin();
|
|
link_type parent_of_v = parent(v);
|
|
while (j!= v->objects.end())
|
|
{
|
|
if(!is_less_equal(m_interface.get_left(*j), v->left_key))
|
|
return false;
|
|
if(!is_less_equal( v->right_key, m_interface.get_right(*j)))
|
|
return false;
|
|
if (parent_of_v != root())
|
|
if((is_less_equal(m_interface.get_left(*j), parent_of_v->left_key))&&
|
|
(is_less_equal( parent_of_v->right_key,
|
|
m_interface.get_right(*j))))
|
|
return false;
|
|
j++;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
// construction of a tree
|
|
Segment_tree_d(Segment_tree_d const &sub_tree, bool):
|
|
sublayer_tree(sub_tree.sublayer_tree->clone()), is_built(false), header(CGAL_TREE_BASE_NULL)
|
|
{}
|
|
|
|
// construction of a tree, definition of the prototype of sublayer tree
|
|
Segment_tree_d(Tree_base<C_Data, C_Window> const &sub_tree):
|
|
sublayer_tree(sub_tree.clone()), is_built(false), header(CGAL_TREE_BASE_NULL)
|
|
{}
|
|
|
|
// destruction
|
|
~Segment_tree_d()
|
|
{
|
|
link_type v=root();
|
|
if(v!=CGAL_TREE_BASE_NULL)
|
|
delete_tree(v);
|
|
if (header!=0)
|
|
delete_node(header);
|
|
if(sublayer_tree!=0)
|
|
delete sublayer_tree;
|
|
}
|
|
|
|
// clone creates a prototype
|
|
Tree_base<C_Data, C_Window> *clone() const {
|
|
return new Segment_tree_d(*this, true); }
|
|
|
|
bool make_tree(const typename std::list< C_Data>::iterator& beg,
|
|
const typename std::list< C_Data>::iterator& end,
|
|
typename tbt::lit * =0){
|
|
return make_tree_impl(beg,end);
|
|
}
|
|
|
|
#ifdef stlvector
|
|
bool make_tree(const typename std::vector< C_Data>::iterator& beg,
|
|
const typename std::vector< C_Data>::iterator& end,
|
|
typename tbt::vbit * =0){
|
|
return make_tree_impl(beg,end);
|
|
}
|
|
#endif
|
|
#ifdef carray
|
|
bool make_tree(const C_Data *beg,
|
|
const C_Data *end){
|
|
return make_tree_impl(beg,end);
|
|
}
|
|
#endif
|
|
|
|
// the tree is build according to Data [first,last)
|
|
template<class A>
|
|
inline
|
|
bool make_tree_impl(const A& first, const A& last)
|
|
{
|
|
if(!is_built)
|
|
is_built = true;
|
|
else
|
|
return false;
|
|
|
|
A count = first;
|
|
int n=0;
|
|
std::vector<Key> keys(2* std::distance(first, last));
|
|
while(count!=last)
|
|
{
|
|
if (m_interface.comp(m_interface.get_left(*count),
|
|
m_interface.get_right(*count)))
|
|
{
|
|
keys[n++]=m_interface.get_left(*count);
|
|
keys[n++]=m_interface.get_right(*count);
|
|
}
|
|
else
|
|
{
|
|
CGAL_Tree_warning_msg(m_interface.comp(m_interface.get_left(*count),
|
|
m_interface.get_right(*count)),
|
|
"invalid segment ignored");
|
|
}
|
|
count++;
|
|
}
|
|
|
|
if(n==0)
|
|
{
|
|
is_built = false;
|
|
return true;
|
|
}
|
|
std::sort(keys.begin(), keys.end(), m_interface.comp);
|
|
std::vector<Key> keys2(2*n + 1);
|
|
int m=0;
|
|
int num=1;
|
|
keys2[0]=keys[0];
|
|
for(m=1;m<n;m++)
|
|
{
|
|
if(m_interface.comp(keys[m],keys2[num-1])||
|
|
m_interface.comp(keys2[num-1],keys[m]))
|
|
{
|
|
keys2[num++]=keys[m];
|
|
}
|
|
}
|
|
|
|
link_type leftchild;
|
|
link_type rightchild;
|
|
link_type prevchild;
|
|
link_type leftmostlink = CGAL_TREE_BASE_NULL;
|
|
|
|
int start = 0;
|
|
build_segment_tree(num-1, leftchild, rightchild, prevchild,
|
|
leftmostlink, start, num-1, keys2);
|
|
|
|
header = new_Segment_tree_node_t();
|
|
header->right_link = rightchild;
|
|
header->parent_link = prevchild;
|
|
prevchild->parent_link = prevchild;
|
|
header->left_link = leftmostlink;
|
|
|
|
A current = first;
|
|
link_type r = root();
|
|
do
|
|
{
|
|
if (m_interface.comp(m_interface.get_left(*current),
|
|
m_interface.get_right(*current)))
|
|
insert_segment(r, *current);
|
|
}while(++current!=last);
|
|
|
|
link_type v=root();
|
|
build_next_dimension(v);
|
|
return true;
|
|
}
|
|
|
|
|
|
std::back_insert_iterator< std::list< C_Data> > window_query
|
|
( C_Window const &win,
|
|
std::back_insert_iterator< std::list< C_Data> > out,
|
|
typename tbt::lbit * =0){
|
|
return window_query_impl(win,out);
|
|
}
|
|
|
|
|
|
std::back_insert_iterator< std::vector< C_Data> > window_query
|
|
( C_Window const &win,
|
|
std::back_insert_iterator< std::vector< C_Data> > out,
|
|
typename tbt::vbit * =0){
|
|
return window_query_impl(win,out);
|
|
}
|
|
#ifdef carray
|
|
C_Data *window_query( C_Window const &win, C_Data *out){
|
|
return window_query_impl(win,out);
|
|
}
|
|
#endif
|
|
|
|
#ifdef ostreamiterator
|
|
std::ostream_iterator< C_Data> window_query( C_Window const &win,
|
|
std::ostream_iterator< C_Data> out,
|
|
typename tbt::oit *dummy=0){
|
|
return window_query_impl(win,out);
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
// all elements that ly inside win are inserted into result
|
|
template <class A>
|
|
inline A window_query_impl( C_Window const &win,
|
|
A result,typename tbt::lbit * =0)
|
|
{
|
|
if(is_less_equal(m_interface.get_right_win(win),
|
|
m_interface.get_left_win(win)))
|
|
{
|
|
CGAL_Tree_warning_msg(m_interface.comp(m_interface.get_right_win(win),
|
|
m_interface.get_left_win(win)),
|
|
"invalid window -- query ignored");
|
|
return result;
|
|
}
|
|
link_type v = root();
|
|
if(v!=CGAL_TREE_BASE_NULL)
|
|
return window_query(win, result, v);
|
|
return result;
|
|
}
|
|
|
|
|
|
std::back_insert_iterator< std::list< C_Data> > enclosing_query(
|
|
C_Window const &win,
|
|
std::back_insert_iterator< std::list< C_Data> > out,
|
|
typename tbt::lbit * =0){
|
|
return enclosing_query_impl(win,out);
|
|
}
|
|
|
|
std::back_insert_iterator< std::vector< C_Data> > enclosing_query(
|
|
C_Window const &win,
|
|
std::back_insert_iterator< std::vector< C_Data> > out,
|
|
typename tbt::vbit * =0){
|
|
return enclosing_query_impl(win,out);
|
|
}
|
|
|
|
|
|
#ifdef carray
|
|
C_Data *enclosing_query( C_Window const &win, C_Data *out){
|
|
return enclosing_query_impl(win,out);
|
|
}
|
|
#endif
|
|
|
|
#ifdef ostreamiterator
|
|
std::ostream_iterator< C_Data>
|
|
enclosing_query( C_Window const &win,
|
|
std::ostream_iterator< C_Data> out,
|
|
typename tbt::oit *dummy=0){
|
|
return enclosing_query_impl(win,out);
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
// all objects that enclose win are inserted into result
|
|
template <class A>
|
|
inline
|
|
A enclosing_query_impl( C_Window const &win,
|
|
A result, typename tbt::lbit * =0)
|
|
{
|
|
if(is_less_equal(m_interface.get_right_win(win),
|
|
m_interface.get_left_win(win)))
|
|
{
|
|
CGAL_Tree_warning_msg(m_interface.comp(m_interface.get_right_win(win),
|
|
m_interface.get_left_win(win)),
|
|
"invalid window -- query ignored");
|
|
return result;
|
|
}
|
|
link_type v = root();
|
|
if(v!=CGAL_TREE_BASE_NULL)
|
|
return enclosing_query(win, result, v);
|
|
return result;
|
|
}
|
|
|
|
bool is_valid() const
|
|
{
|
|
link_type v= root();
|
|
if(v!=CGAL_TREE_BASE_NULL)
|
|
return is_valid(v);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
|
|
} //namespace CGAL
|
|
|
|
#endif
|