mirror of https://github.com/CGAL/cgal
4534 lines
118 KiB
C++
4534 lines
118 KiB
C++
// Copyright (c) 1998 ETH Zurich (Switzerland).
|
|
// All rights reserved.
|
|
//
|
|
// This file is part of CGAL (www.cgal.org); you may redistribute it under
|
|
// the terms of the Q Public License version 1.0.
|
|
// See the file LICENSE.QPL distributed with CGAL.
|
|
//
|
|
// 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) : Gabriele Neyer<neyer@inf.ethz.ch>
|
|
#ifndef __R_TREE_H__
|
|
#define __R_TREE_H__
|
|
|
|
|
|
//*********************************************************************
|
|
// Debug output handling
|
|
//*********************************************************************
|
|
#ifdef CGAL_D_DOGN_Data
|
|
#define CGAL_DOGN_Data(cmd) cmd
|
|
#else
|
|
#define CGAL_DOGN_Data(cmd)
|
|
#endif
|
|
|
|
#ifdef CGAL_D_DOGN_Control
|
|
#define CGAL_DOGN_Control(cmd) cmd
|
|
#else
|
|
#define CGAL_DOGN_Control(cmd)
|
|
#endif
|
|
|
|
#ifdef CGAL_D_DOGN_ControlB
|
|
#define CGAL_DOGN_ControlB(cmd) cmd
|
|
#else
|
|
#define CGAL_DOGN_ControlB(cmd)
|
|
#endif
|
|
|
|
#ifdef CGAL_D_DOGN_Insert
|
|
#define CGAL_DOGN_Insert(cmd) cmd
|
|
#else
|
|
#define CGAL_DOGN_Insert(cmd)
|
|
#endif
|
|
|
|
#ifdef CGAL_D_DOGN_Storage
|
|
#define CGAL_DOGN_Storage(cmd) cmd
|
|
#else
|
|
#define CGAL_DOGN_Storage(cmd)
|
|
#endif
|
|
|
|
#ifdef CGAL_D_DOGN_Search
|
|
#define CGAL_DOGN_Search(cmd) cmd
|
|
#else
|
|
#define CGAL_DOGN_Search(cmd)
|
|
#endif
|
|
|
|
#ifdef CGAL_D_DOGN_Delete
|
|
#define CGAL_DOGN_Delete(cmd) cmd
|
|
#else
|
|
#define CGAL_DOGN_Delete(cmd)
|
|
#endif
|
|
|
|
#include <CGAL/basic.h>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <stack>
|
|
#include <list>
|
|
#include <map>
|
|
#include <vector>
|
|
#include <unistd.h>
|
|
|
|
CGAL_BEGIN_NAMESPACE
|
|
|
|
// this information suffices to retrieve a node from disk
|
|
// it is used especially for the iterator
|
|
struct Node_info{
|
|
int level;
|
|
int pnext;
|
|
};
|
|
|
|
void print_node_infos(std::list<Node_info*>& node_stack)
|
|
{
|
|
std::list<Node_info*>::iterator it;
|
|
std::cerr << "Node_info_list &&&&&&&&&&&\n";
|
|
if(!node_stack.empty())
|
|
{
|
|
for(it=node_stack.begin();it!=node_stack.end();it++)
|
|
{
|
|
std::cerr << "level" << (*it)->level << std::endl;
|
|
std::cerr << "pnext" << (*it)->pnext << std::endl;
|
|
std::cerr << std::endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Each entry of an inner node is of this type.
|
|
// pnext points to its offset in the file (not the physical offset).
|
|
template <class Traits>
|
|
class R_tree_value {
|
|
public:
|
|
typedef typename Traits::Key Key;
|
|
typedef R_tree_value *iterator;
|
|
Key key;
|
|
long pnext;
|
|
bool deleted;
|
|
Traits traits;
|
|
R_tree_value(){deleted=true;}
|
|
~R_tree_value(){}
|
|
R_tree_value(const R_tree_value& t)
|
|
{
|
|
pnext=t.pnext;
|
|
key=t.key;
|
|
deleted=t.deleted;
|
|
}
|
|
R_tree_value & operator=(const R_tree_value &t)
|
|
{
|
|
pnext=t.pnext;
|
|
key=t.key;
|
|
deleted=t.deleted;
|
|
return *this;
|
|
}
|
|
int size()
|
|
{
|
|
return (int)(sizeof(long) +sizeof(bool) + traits.written_size_key(key));
|
|
}
|
|
void read(char **s)
|
|
{
|
|
int slong=(int)sizeof(long);
|
|
int sbool=(int)sizeof(bool);
|
|
char *from_long=new char[slong];
|
|
char *from_bool=new char[sbool];
|
|
int i,r=0;
|
|
traits.read_key(s,key);
|
|
r=traits.written_size_key(key);
|
|
for (i=0; i<slong; i++)
|
|
from_long[i] = (*s)[r+i];
|
|
pnext=*((long *)from_long);
|
|
r+=slong;
|
|
for (i=0; i<sbool; i++)
|
|
from_bool[i] = (*s)[r+i];
|
|
deleted=*((bool *)from_bool);
|
|
delete[] from_long;
|
|
delete[] from_bool;
|
|
CGAL_DOGN_Data(
|
|
std::cerr << "R-tree-value:";
|
|
traits.dump(key);
|
|
std::cerr << "--pnext:" << pnext << "--" << deleted << std::endl;
|
|
)
|
|
|
|
}
|
|
|
|
void write(char **s)
|
|
{
|
|
int slong=(int)sizeof(long);
|
|
int sbool=(int)sizeof(bool);
|
|
char *from_long=new char[slong];
|
|
char *from_bool=new char[sbool];
|
|
int i,r=0;
|
|
traits.write_key(s,key);
|
|
r=traits.written_size_key(key);
|
|
memcpy(from_long,(char *)(&pnext),sizeof(long));
|
|
for (i=0; i<slong; i++)
|
|
(*s)[i+r] = from_long[i];
|
|
r += slong;
|
|
memcpy(from_bool,(char *)(&deleted),sizeof(bool));
|
|
for (i=0; i<sbool; i++)
|
|
(*s)[i+r] = from_bool[i];
|
|
delete[] from_bool;
|
|
delete[] from_long;
|
|
CGAL_DOGN_Data(
|
|
//testing
|
|
Key test;
|
|
std::cerr << "R-tree-value:";
|
|
traits.read_key(s,test);
|
|
traits.dump(test);
|
|
std::cerr << "=====test keys\n";
|
|
)
|
|
}
|
|
|
|
};
|
|
|
|
// Each data entry is of this type.
|
|
template <class Traits>
|
|
class R_tree_leaf_data {
|
|
public:
|
|
typedef typename Traits::Data Data;
|
|
typedef typename Traits::Key Key;
|
|
typedef R_tree_leaf_data *iterator;
|
|
// bool deleted;
|
|
Data ele;
|
|
Key key;
|
|
Traits traits;
|
|
size_t size(){
|
|
return traits.written_size(ele) + traits.written_size_key(key);
|
|
// return sizeof(*this);
|
|
}
|
|
R_tree_leaf_data(){}
|
|
~R_tree_leaf_data(){}
|
|
R_tree_leaf_data(const R_tree_leaf_data& t)
|
|
{
|
|
ele=t.ele;
|
|
key=t.key;
|
|
}
|
|
R_tree_leaf_data & operator=(const R_tree_leaf_data &t)
|
|
{
|
|
ele=t.ele;
|
|
key=t.key;
|
|
return *this;
|
|
}
|
|
void read(char** s)
|
|
{
|
|
int r=0;
|
|
traits.read(s,ele);
|
|
r=traits.written_size(ele);
|
|
traits.read_key(&((*s)+r),key);
|
|
}
|
|
|
|
void write(char **s)
|
|
{
|
|
int r=0;
|
|
traits.write(s,data);
|
|
r=traits.written_size(ele);
|
|
traits.write_key(&((*s)+r),key);
|
|
}
|
|
};
|
|
|
|
//abstract base class defining the base type of a node and of a leaf
|
|
template<class v_type, class Data, class Key, class Traits,
|
|
const int IO_min_cap_nodes,const int IO_max_cap_nodes,
|
|
const int IO_min_cap_leaves, const int IO_page_size>
|
|
class abstract_node_entry
|
|
{
|
|
public:
|
|
int eles;
|
|
long pthis;
|
|
int level;
|
|
abstract_node_entry(){}
|
|
virtual ~abstract_node_entry(){}
|
|
virtual v_type & begin()=0;
|
|
virtual v_type & end()=0;
|
|
virtual bool overfilled( int offset)=0;
|
|
virtual bool underfilled()=0;
|
|
virtual void clear()=0;
|
|
virtual void read(char **s)=0;
|
|
virtual void write (char **s) =0;
|
|
virtual size_t size() =0;
|
|
};
|
|
|
|
|
|
// inner node can store Max_cap v_type elements
|
|
template<class v_type,class Data, class Key, class Traits,
|
|
const int IO_min_cap_nodes, const int IO_max_cap_nodes,
|
|
const int IO_min_cap_leaves, const int IO_page_size>
|
|
class node_entry : public abstract_node_entry<v_type,Data,Key,Traits,
|
|
IO_min_cap_nodes,IO_max_cap_nodes,IO_min_cap_leaves,IO_page_size>
|
|
{
|
|
public:
|
|
v_type ele[IO_max_cap_nodes];
|
|
|
|
node_entry(int the_level=1){
|
|
level=the_level;
|
|
pthis=-1;
|
|
// is_init=true;
|
|
int i;
|
|
for (i=0; i < IO_max_cap_nodes; ++i)
|
|
{
|
|
ele[i].deleted = true;
|
|
}
|
|
eles = 0;
|
|
}
|
|
|
|
void clear(){
|
|
eles = 0;
|
|
int i;
|
|
for (i=0; i < IO_max_cap_nodes; ++i) {
|
|
ele[i].deleted = true;
|
|
}
|
|
}
|
|
|
|
virtual v_type & begin() {
|
|
return ele[0];
|
|
}
|
|
|
|
virtual v_type & end() { return ele[eles]; }
|
|
|
|
virtual size_t size() {
|
|
return 2*sizeof(int) + sizeof(long) + IO_max_cap_nodes*ele[0].size();
|
|
}
|
|
|
|
bool overfilled( int number)
|
|
{
|
|
return (eles <= IO_max_cap_nodes ?false : true);
|
|
}
|
|
|
|
bool underfilled()
|
|
{
|
|
return (eles < IO_min_cap_nodes ?true : false);
|
|
}
|
|
|
|
|
|
virtual void read(char **s)
|
|
{
|
|
int slong=(int)sizeof(long);
|
|
int sint=(int)sizeof(int);
|
|
char *from_int=new char[sint];
|
|
char *from_long=new char[slong];
|
|
int i,r=0;
|
|
for (i=0; i<sint; i++)
|
|
from_int[i] = (*s)[i];
|
|
r += sint;
|
|
eles=*((int *)from_int);
|
|
|
|
for (i=0; i<slong; i++)
|
|
from_long[i]=(*s)[i+r];
|
|
r += slong;
|
|
pthis=*((long *)from_long);
|
|
|
|
for (i=0; i<sint; i++)
|
|
from_int[i]=(*s)[i+r];
|
|
r += sint;
|
|
level=*((int *)from_int);
|
|
char **k;
|
|
k = new char *;
|
|
int ele_size=ele[0].size();
|
|
for (i=0; i<IO_max_cap_nodes; i++)
|
|
{
|
|
*k=((*s)+r);
|
|
ele[i].read(k);
|
|
r+=ele_size;
|
|
}
|
|
delete[] from_int;
|
|
delete k;
|
|
delete[] from_long;
|
|
}
|
|
|
|
virtual void write (char **s)
|
|
{
|
|
int slong=(int)sizeof(long);
|
|
int sint=(int)sizeof(int);
|
|
char *from_int=new char[sint];
|
|
char *from_long=new char[slong];
|
|
int i,r=0;
|
|
memcpy(from_int,(char *)(&eles),sint);
|
|
for (i=0; i<sint; i++)
|
|
(*s)[i] = from_int[i];
|
|
r += sint;
|
|
|
|
memcpy(from_long,(char *)(&pthis),slong);
|
|
for (i=0; i<slong; i++)
|
|
(*s)[i+r] = from_long[i];
|
|
r += slong;
|
|
|
|
memcpy(from_int,(char *)(&level),sint);
|
|
for (i=0; i<sint; i++)
|
|
(*s)[i+r] = from_int[i];
|
|
r += sint;
|
|
|
|
int ele_size=ele[0].size();
|
|
char **k;
|
|
k = new char *;
|
|
for (i=0; i<IO_max_cap_nodes; i++){
|
|
*k=((*s)+r);
|
|
ele[i].write(k);
|
|
r+=ele_size;
|
|
}
|
|
delete k;
|
|
delete[] from_int;
|
|
delete[] from_long;
|
|
}
|
|
};
|
|
|
|
//leaf node can contain data in its field raw_data.
|
|
template<class v_type, class Data, class Key, class Traits,
|
|
const int IO_min_cap_nodes, const int IO_max_cap_nodes,
|
|
const int IO_min_cap_leaves, const int IO_page_size>
|
|
class data_entry : public abstract_node_entry<v_type,Data,Key,Traits,
|
|
IO_min_cap_nodes, IO_max_cap_nodes,IO_min_cap_leaves, IO_page_size>
|
|
{
|
|
public:
|
|
v_type fake;
|
|
int leaf_offset;
|
|
char raw_data[IO_page_size];
|
|
data_entry(){
|
|
pthis=-1;
|
|
level=0;
|
|
leaf_offset = 0;
|
|
eles = 0;
|
|
}
|
|
|
|
void clear(){
|
|
eles = 0;
|
|
leaf_offset = 0;
|
|
}
|
|
virtual size_t size() {
|
|
// return 3*sizeof(int) + sizeof(long) + IO_page_size*sizeof(char)+2;
|
|
return 3*sizeof(int) + sizeof(long) + IO_page_size*sizeof(char);
|
|
}
|
|
virtual v_type & begin(){
|
|
return fake; }
|
|
virtual v_type & end(){
|
|
return fake;}
|
|
|
|
void delete_key( int offset, int num)
|
|
{
|
|
char *tmp1=raw_data + offset;
|
|
char *tmp2=raw_data +offset +num;
|
|
memcpy(tmp1, tmp2, leaf_offset -num -offset);
|
|
leaf_offset = leaf_offset - num;
|
|
eles--;
|
|
}
|
|
bool overfilled( int leafnumber)
|
|
{
|
|
return (available_space(leafnumber)>0 ?false : true);
|
|
}
|
|
|
|
bool underfilled()
|
|
{
|
|
if (eles<IO_min_cap_leaves)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
int available_space ( int offset) {
|
|
return(IO_page_size - offset);
|
|
}
|
|
|
|
virtual void read(char **s){
|
|
int slong=(int)sizeof(long);
|
|
int sint=(int)sizeof(int);
|
|
char *from_int=new char[sint];
|
|
char *from_long=new char[slong];
|
|
int i,r=0;
|
|
for (i=0; i<sint; i++)
|
|
from_int[i] = (*s)[i];
|
|
r += sint;
|
|
eles=*((int *)from_int);
|
|
|
|
for (i=0; i<slong; i++)
|
|
from_long[i]=(*s)[i+r];
|
|
r += slong;
|
|
pthis=*((long *)from_long);
|
|
|
|
for (i=0; i<sint; i++)
|
|
from_int[i]=(*s)[i+r];
|
|
r += sint;
|
|
level=*((int *)from_int);
|
|
|
|
for (i=0; i<sint; i++)
|
|
from_int[i]=(*s)[i+r];
|
|
r += sint;
|
|
leaf_offset=*((int *)from_int);
|
|
|
|
for (i=0; i<IO_page_size; i++)
|
|
raw_data[i]=(*s)[i+r];
|
|
r += IO_page_size;
|
|
delete[] from_int;
|
|
delete[] from_long;
|
|
|
|
CGAL_DOGN_Data(
|
|
char **ff;
|
|
ff=new char *;
|
|
Data element;
|
|
Key key;
|
|
Traits traits;
|
|
int offset=0;
|
|
std::cerr << "ausgabe von read :" << eles << std::endl;
|
|
std::cerr << *s << std::endl;
|
|
for(i=0;i<eles; i++)
|
|
{
|
|
*ff=raw_data +offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
traits.dump(key);
|
|
offset += traits.written_size(element);
|
|
std::cerr <<"new offset:" << offset << std::endl;
|
|
}
|
|
std::cerr << std::endl;
|
|
delete ff;
|
|
)
|
|
}
|
|
|
|
virtual void write (char **s) {
|
|
int slong=(int)sizeof(long);
|
|
int sint=(int)sizeof(int);
|
|
char *from_int=new char[sint];
|
|
char *from_long=new char[slong];
|
|
int i,r=0;
|
|
memcpy(from_int,(char *)(&eles),sint);
|
|
for (i=0; i<sint; i++)
|
|
(*s)[i] = from_int[i];
|
|
r += sint;
|
|
memcpy(from_long,(char *)(&pthis),slong);
|
|
for (i=0; i<slong; i++)
|
|
(*s)[i+r] = from_long[i];
|
|
r += slong;
|
|
memcpy(from_int,(char *)(&level),sint);
|
|
for (i=0; i<sint; i++)
|
|
(*s)[i+r] = from_int[i];
|
|
r += sint;
|
|
memcpy(from_int,(char *)(&leaf_offset),sint);
|
|
for (i=0; i<sint; i++)
|
|
(*s)[i+r] = from_int[i];
|
|
r += sint;
|
|
|
|
for (i=0; i<IO_page_size; i++)
|
|
(*s)[i+r] = raw_data[i];
|
|
r += IO_page_size;
|
|
delete[] from_int;
|
|
delete[] from_long;
|
|
|
|
CGAL_DOGN_Data(
|
|
char **ff;
|
|
ff=new char *;
|
|
Data element;
|
|
Key key;
|
|
Traits traits;
|
|
int offset=0;
|
|
std::cerr << "ausgabe von write :";
|
|
for(i=0;i<eles; i++)
|
|
{
|
|
*ff=raw_data + offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
traits.dump(key);
|
|
offset += traits.written_size(element);
|
|
std::cerr <<"new offset:" << offset << std::endl;
|
|
}
|
|
std::cerr << std::endl;
|
|
data_entry d;
|
|
d.read(s);
|
|
offset=0;
|
|
std::cerr << "ausgabe von read :" << d.eles << std::endl;
|
|
std::cerr << *s << std::endl;
|
|
for(i=0;i<d.eles; i++)
|
|
{
|
|
*ff=d.raw_data + offset;
|
|
traits.read(ff, element);
|
|
key = traits.build(element);
|
|
traits.dump(key);
|
|
offset += traits.written_size(element);
|
|
std::cerr <<"new offset:" << offset << std::endl;
|
|
}
|
|
std::cerr << std::endl;
|
|
delete ff;
|
|
)
|
|
}
|
|
};
|
|
|
|
|
|
|
|
// Range Tree node: Implementation of a node of the R_Tree.
|
|
// We differ between an inner node containing only keys of data
|
|
// elements and leaf nodes which contain the data.
|
|
// Data_traits: R_Tree_interface
|
|
// DATA: Data
|
|
// V: R_Tree_node_type<Key>
|
|
// D: R_Tree_data_type<Key>
|
|
// S1: split function for inner vertices
|
|
// S2: split function for leaf vertices
|
|
// page_size: size of the buffer for data.
|
|
// E.g. disk block size - sizeof(extra data).
|
|
// long name conflict: exchange R_tree_node R_Tree_node
|
|
// reinserted when an overflow occurs.
|
|
template <class Data_traits, class R_tree_index,
|
|
class IO_tree_traits_nodes, class IO_tree_traits_leaves,
|
|
int IO_min_cap_nodes,
|
|
int IO_max_cap_nodes, int IO_min_cap_leaves,
|
|
int IO_page_size>
|
|
class R_tree_node {
|
|
public:
|
|
typedef R_tree_node Node;
|
|
typedef IO_tree_traits_nodes IO_intf_nodes;
|
|
typedef typename Data_traits::Key Key;
|
|
typedef typename Data_traits::Data Data;
|
|
typedef Data_traits Traits;
|
|
typedef R_tree_value<Traits> v_type;
|
|
typedef R_tree_leaf_data<Traits> d_type;
|
|
|
|
Traits traits;
|
|
|
|
//definition of the inner node type depending on the template parameters
|
|
typedef node_entry<v_type, Data, Key, Traits, IO_min_cap_nodes,
|
|
IO_max_cap_nodes, IO_min_cap_leaves, IO_page_size> Node_entry;
|
|
//definition of the leaf node type
|
|
typedef data_entry<v_type, Data, Key, Traits, IO_min_cap_nodes,
|
|
IO_max_cap_nodes,IO_min_cap_leaves, IO_page_size> Data_entry;
|
|
|
|
typedef IO_tree_traits_nodes Tree;
|
|
typedef IO_tree_traits_leaves Leaf_data;
|
|
typedef size_t size_type;
|
|
typedef v_type* iterator;
|
|
typedef iterator const_iterator;
|
|
typedef d_type* d_iterator;
|
|
long data_size;
|
|
long node_size;
|
|
char **data_space;
|
|
char **node_space;
|
|
char **ff;
|
|
|
|
protected:
|
|
Tree *tree;
|
|
Leaf_data *leaf_data;
|
|
typename R_tree_index::Split_node ps;
|
|
typename R_tree_index::Split_leaf ps_leaf;
|
|
typename R_tree_index::Choose_subtree choose_subtree;
|
|
typename R_tree_index::Reinsertion_leaf reinsertion_leaf;
|
|
typename R_tree_index::Reinsertion_node reinsertion_node;
|
|
|
|
public:
|
|
// XX is always used to store the current node
|
|
abstract_node_entry<v_type,Data,Key,Traits,IO_min_cap_nodes,
|
|
IO_max_cap_nodes, IO_min_cap_leaves, IO_page_size> *XX;
|
|
|
|
R_tree_node() {
|
|
Data_entry d;
|
|
Node_entry n;
|
|
data_size=d.size();
|
|
node_size=n.size();
|
|
|
|
CGAL_DOGN_Data(std::cerr << "Size of data: "
|
|
<< data_size << " size of node: "
|
|
<< node_size << std::endl;)
|
|
data_space=new char *;
|
|
*data_space= new char[data_size];
|
|
node_space=new char *;
|
|
*node_space= new char[node_size];
|
|
ff=new char *;
|
|
}
|
|
|
|
// A new node is constructed. Either a leaf node or an inner node.
|
|
// If level=0 then a leaf is constructed
|
|
R_tree_node( int level)
|
|
{
|
|
Data_entry d;
|
|
Node_entry n;
|
|
data_size=d.size();
|
|
node_size=n.size();
|
|
CGAL_DOGN_Data(std::cerr << "Size of data: " << data_size <<
|
|
" size of node: " << node_size << std::endl;)
|
|
data_space=new char *;
|
|
*data_space= new char[data_size];
|
|
node_space=new char *;
|
|
*node_space= new char[node_size];
|
|
ff=new char *;
|
|
if(level==0)
|
|
{
|
|
XX = new Data_entry();
|
|
}
|
|
else
|
|
{
|
|
XX = new Node_entry(level);
|
|
}
|
|
}
|
|
|
|
// deletion of the node
|
|
virtual ~R_tree_node()
|
|
{
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
delete dynamic_cast<Data_entry*>(XX);
|
|
else
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
delete dynamic_cast<Node_entry*>(XX);
|
|
|
|
delete[] *data_space;
|
|
delete data_space;
|
|
delete[] *node_space;
|
|
delete node_space;
|
|
delete ff;
|
|
CGAL_DOGN_ControlB(std::cerr << "Delete r_tree_node called\n";)
|
|
}
|
|
|
|
void clear() {
|
|
XX->clear();
|
|
}
|
|
|
|
iterator begin() {
|
|
return &XX->begin();
|
|
}
|
|
iterator end() {
|
|
return &XX->end();}
|
|
|
|
|
|
void open(Tree &t, Leaf_data &l) { tree = &t; leaf_data = &l; }
|
|
|
|
|
|
// The data of the node (either leaf or not) is read.
|
|
// Therefore, the data at position num in the file is retrieved
|
|
// by a database call.
|
|
bool get( int level, long num) {
|
|
if (level==0)
|
|
{
|
|
if(dynamic_cast<Data_entry*>(XX)){
|
|
if ((*leaf_data).get(num,data_space))
|
|
(*(dynamic_cast<Data_entry*>(XX))).read(data_space);
|
|
else{
|
|
CGAL_DOGN_Control(std::cerr << "Could not get leaf data number: "
|
|
<< num << std::endl;)
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
delete dynamic_cast<Node_entry*>(XX);
|
|
XX = new Data_entry();
|
|
CGAL_DOGN_Data(std::cerr << "Size of data in get: "<< data_size
|
|
<< std::endl;)
|
|
if ((*leaf_data).get(num,data_space))
|
|
(*(dynamic_cast<Data_entry*>(XX))).read(data_space);
|
|
else
|
|
{
|
|
CGAL_DOGN_Control(
|
|
std::cerr << "Could not get leaf data" << num
|
|
<< std::endl;
|
|
)
|
|
return false;
|
|
}
|
|
}
|
|
CGAL_DOGN_Data(
|
|
std::cerr << "GET a data entry \n";
|
|
dump(*(dynamic_cast<Data_entry*>(XX)),0,0);
|
|
std::cerr << "GET a data entry -- end \n";
|
|
)
|
|
}
|
|
else{
|
|
if(dynamic_cast<Node_entry*>(XX)){
|
|
if((*tree).get(num, node_space))
|
|
(*(dynamic_cast<Node_entry*>(XX))).read(node_space);
|
|
else
|
|
{
|
|
CGAL_DOGN_Control(
|
|
std::cerr << "Could not get tree data: number"
|
|
<< num << std::endl;
|
|
)
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
delete dynamic_cast<Data_entry*>(XX);
|
|
XX = new Node_entry();
|
|
if((*tree).get(num,node_space))
|
|
(*(dynamic_cast<Node_entry*>(XX))).read(node_space);
|
|
else
|
|
{
|
|
CGAL_DOGN_Control(
|
|
std::cerr << "Could not get tree data: number"
|
|
<< num << std::endl;
|
|
)
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// The data of the node (either leaf or not) is written.
|
|
// Therefore, the data at position num in the file is written
|
|
// by a database call.
|
|
void put(long num = -1)
|
|
{
|
|
if(num>-1)
|
|
XX->pthis=num;
|
|
if (XX->level==0)
|
|
{
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
{
|
|
if (XX->pthis > -1)
|
|
{
|
|
(*(dynamic_cast<Data_entry*>(XX))).write(data_space);
|
|
(*leaf_data).update(XX->pthis,data_space);
|
|
}
|
|
else
|
|
{
|
|
//set the number where the data is positioned
|
|
(*(dynamic_cast<Data_entry*>(XX))).pthis =
|
|
(*leaf_data).get_pos();
|
|
CGAL_DOGN_Storage(
|
|
std::cerr << "New pos: " << XX->pthis
|
|
<< std::endl;
|
|
)
|
|
(*(dynamic_cast<Data_entry*>(XX))).write(data_space);
|
|
(*leaf_data).insert(XX->pthis,data_space);
|
|
}
|
|
}
|
|
CGAL_DOGN_Control(
|
|
else
|
|
std::cerr << "Error wrong Node_entry\n";
|
|
)
|
|
}
|
|
else
|
|
{
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
{
|
|
if (XX->pthis > -1)
|
|
{
|
|
(*(dynamic_cast<Node_entry*>(XX))).write(node_space);
|
|
(*tree).update(XX->pthis, node_space);
|
|
(*(dynamic_cast<Node_entry*>(XX))).read(node_space); //test
|
|
}
|
|
else
|
|
{
|
|
XX->pthis = (*tree).get_pos();
|
|
CGAL_DOGN_Storage(
|
|
std::cerr << "New pos: " << XX->pthis
|
|
<< std::endl;
|
|
)
|
|
(*(dynamic_cast<Node_entry*>(XX))).write(node_space);
|
|
(*tree).insert(XX->pthis,node_space);
|
|
(*(dynamic_cast<Node_entry*>(XX))).read(node_space); //test
|
|
}
|
|
}
|
|
CGAL_DOGN_Control(
|
|
else
|
|
std::cerr << "Error wrong Node_entry\n";)
|
|
}
|
|
}
|
|
|
|
// YY is written to the database
|
|
void put_data(Data_entry& YY,long num = -1)
|
|
{
|
|
if(num>-1)
|
|
YY.pthis=num;
|
|
if (YY.pthis > -1)
|
|
{
|
|
YY.write(data_space);
|
|
(*leaf_data).update(YY.pthis,data_space);
|
|
}
|
|
else
|
|
{
|
|
//set the number where the data is positioned
|
|
YY.pthis = (*leaf_data).get_pos();
|
|
CGAL_DOGN_ControlB(std::cerr << "New pos: " << YY.pthis << std::endl;)
|
|
YY.write(data_space);
|
|
(*leaf_data).insert(YY.pthis,data_space);
|
|
}
|
|
}
|
|
|
|
// YY is written to the database
|
|
void put_node(Node_entry& YY, long num=-1)
|
|
{
|
|
if(num>-1)
|
|
YY.pthis=num;
|
|
|
|
if (YY.pthis > -1)
|
|
{
|
|
YY.write(node_space);
|
|
(*tree).update(YY.pthis, node_space);
|
|
}
|
|
else
|
|
{
|
|
YY.pthis = (*tree).get_pos();
|
|
CGAL_DOGN_ControlB(std::cerr << "New pos: " << YY.pthis << std::endl;)
|
|
YY.write(node_space);
|
|
(*tree).insert(YY.pthis,node_space);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// the data on the associated file at offset num is marked deleted.
|
|
void erase(long num = -1) {
|
|
if (XX->level==0)
|
|
{
|
|
if (num > -1) XX->pthis = num;
|
|
if (XX->pthis > -1) (*leaf_data).erase(XX->pthis);
|
|
}
|
|
else
|
|
{
|
|
if (num > -1) XX->pthis = num;
|
|
if (XX->pthis > -1) (*tree).erase(XX->pthis);
|
|
}
|
|
}
|
|
|
|
//*****************Beckmann Kriegel ******************
|
|
// A data element is inserted into the tree. The best position in
|
|
// respect to the minimum cost is determined and then the element is
|
|
// either there inserted if the available space is sufficiently large
|
|
// or the node is split.
|
|
void insert_star(Data& d, v_type& v, std::vector<v_type> &children,
|
|
std::vector<v_type> &root_children,
|
|
std::vector<bool>& Reinsert, int MaxLevel,
|
|
std::pair< int,long> *LevelPthis)
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "Insert_star\n";
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
dump((* dynamic_cast<Data_entry*>(XX)),0,0);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
dump_this_node((* dynamic_cast<Node_entry*>(XX)),0,0);
|
|
)
|
|
if (XX->level==0) // leaf insertion
|
|
{
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
insert_star(d, children,root_children, Reinsert, MaxLevel,
|
|
LevelPthis);
|
|
CGAL_DOGN_Control(
|
|
else
|
|
std::cerr << "Error dynamic cast \n";)
|
|
}
|
|
else
|
|
{
|
|
int pos=0;
|
|
typename std::vector<v_type>::iterator i;
|
|
long XXpthis=XX->pthis;
|
|
int XXlevel=XX->level;
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "pthis: " << XX->pthis << std::endl;
|
|
)
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
{
|
|
Node_entry YY=*(dynamic_cast<Node_entry*>(XX));
|
|
//choose the subtree in which to position v
|
|
iterator pos_it = choose_subtree(v.key, &YY.ele[0],
|
|
&YY.ele[IO_max_cap_nodes],YY.level);
|
|
while (pos_it!=&YY.ele[pos]&&pos<YY.eles) pos++;
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "The choosed position is:"
|
|
<< pos << std::endl;
|
|
)
|
|
}
|
|
CGAL_DOGN_Control(
|
|
else
|
|
std::cerr << "Wrong dynamic cast 1\n";
|
|
)
|
|
std::pair< int,long> p(pos,XXpthis);
|
|
LevelPthis[XXlevel]=p;
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[pos].key= traits.unify(
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[pos].key, v.key);
|
|
put();
|
|
// decent the tree, call the insertion routine for the chosen subtree
|
|
get(XX->level-1,(*(dynamic_cast<Node_entry*>(XX))).ele[pos].pnext);
|
|
insert_star(d, v, children, root_children, Reinsert, MaxLevel,
|
|
LevelPthis);
|
|
get(XXlevel,XXpthis); // get the actual XX back
|
|
if (!children.empty()) { //the lower tree was split, insert children
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[pos]= (*children.begin());
|
|
children.erase(children.begin());
|
|
if(dynamic_cast<Node_entry*>(XX)){
|
|
for (i = children.begin(); i != children.end(); ++i)
|
|
// the children are simply put into the vertex
|
|
insert_star((*i), *(dynamic_cast<Node_entry*>(XX)));
|
|
}
|
|
CGAL_DOGN_Control(
|
|
else
|
|
std::cerr << "Wrong dynamic cast 2\n";
|
|
)
|
|
children.erase(children.begin(), children.end());
|
|
}
|
|
put(XXpthis); //update the vertex
|
|
split_node_star(children,root_children,Reinsert,MaxLevel,LevelPthis);
|
|
}
|
|
}
|
|
//*****************end Beckmann Kriegel ******************
|
|
|
|
// special insertion which is only called if the place of insertion
|
|
// was determined before and when there is enough place in the vertex.
|
|
bool insert_special_star( int i, v_type &v, Node_entry& YY) {
|
|
YY.ele[i] = v;
|
|
YY.eles++;
|
|
put();
|
|
return true;
|
|
}
|
|
|
|
// a node is reinserted on the same level
|
|
void forced_reinsert_node(v_type& v, std::vector<v_type> &children,
|
|
std::vector<v_type> &root_children,
|
|
int OnLevel, std::vector<bool>& Reinsert,
|
|
int MaxLevel,
|
|
std::pair< int,long> *LevelPthis)
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "FORCED REINSERT NODE\n";
|
|
dump_this_node((* dynamic_cast<Node_entry*>(XX)),0,0);
|
|
)
|
|
int act_level=XX->level;
|
|
long act_pthis=XX->pthis;
|
|
if (XX->level==OnLevel) //the right level to insert the node
|
|
{
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
insert_star(v,(* dynamic_cast<Node_entry*>(XX)));
|
|
put();
|
|
split_node_star(children,root_children,Reinsert,MaxLevel, LevelPthis);
|
|
}
|
|
else //a subtree in which to position the entry has to be chosen
|
|
{
|
|
int pos=0;
|
|
std::vector<v_type>::iterator i;
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
{
|
|
Node_entry YY=*(dynamic_cast<Node_entry*>(XX));
|
|
iterator pos_it = choose_subtree(v.key, &YY.ele[0],
|
|
&YY.ele[IO_max_cap_nodes],
|
|
YY.level);
|
|
while (pos_it!=&YY.ele[pos]&&pos<YY.eles) pos++;
|
|
CGAL_DOGN_Insert(std::cerr << "The choosed position is:" << pos
|
|
<< std::endl;)
|
|
}
|
|
CGAL_DOGN_Control(
|
|
else
|
|
std::cerr << "Wrong dynamic cast 1\n";
|
|
)
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[pos].key=
|
|
traits.unify((*(dynamic_cast<Node_entry*>(XX))).ele[pos].key, v.key);
|
|
put();
|
|
get(XX->level-1,(*(dynamic_cast<Node_entry*>(XX))).ele[pos].pnext);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
forced_reinsert_node(v, children,
|
|
root_children,
|
|
OnLevel,Reinsert,MaxLevel,LevelPthis);
|
|
CGAL_DOGN_Control(
|
|
else
|
|
std::cerr << "Wrong dynamic cast 3\n";
|
|
)
|
|
get(act_level,act_pthis);
|
|
// may be the reinsertion produces new splits
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "Reinsertion produces another split\n ";
|
|
)
|
|
if (!children.empty())
|
|
{
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[pos]= (*children.begin());
|
|
children.erase(children.begin());
|
|
if(dynamic_cast<Node_entry*>(XX)){
|
|
for (i = children.begin(); i != children.end(); ++i)
|
|
// the children are simply put into the vertex
|
|
insert_star((*i), *(dynamic_cast<Node_entry*>(XX)));
|
|
}
|
|
CGAL_DOGN_Control(
|
|
else
|
|
std::cerr << "Wrong dynamic cast 4\n";)
|
|
children.erase(children.begin(), children.end());
|
|
}
|
|
put();
|
|
split_node_star(children, root_children ,Reinsert, MaxLevel,
|
|
LevelPthis);
|
|
}
|
|
}
|
|
|
|
// a node is reinserted. This procedure is called first. The root node
|
|
// is retrieved and then the node is either inserted or the right subtree
|
|
// is searched by calling forced_reinsert
|
|
void root_forced_reinsert(v_type& v,std::vector<v_type>& root_children,
|
|
int OnLevel, std::vector<bool>& Reinsert,
|
|
int MaxLevel,
|
|
std::pair< int,long> *LevelPthis)
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "ROOT FORCED REINSERT NODE\n";
|
|
dump_this_node((* dynamic_cast<Node_entry*>(XX)),0,0);
|
|
std::cerr << "Rootpthis is:" << LevelPthis[MaxLevel].second
|
|
<< std::endl;
|
|
)
|
|
std::vector<v_type> act_children;
|
|
int pos;
|
|
get(MaxLevel,LevelPthis[MaxLevel].second);
|
|
if (XX->level==OnLevel)
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "Insert in root level" << std::endl;
|
|
)
|
|
insert_star(v,(* dynamic_cast<Node_entry*>(XX)));
|
|
put();
|
|
split_node_star(act_children,root_children,Reinsert,MaxLevel,
|
|
LevelPthis);
|
|
if(!act_children.empty()) {
|
|
root_children.insert(root_children.begin(),*act_children.begin());
|
|
act_children.erase(act_children.begin());
|
|
}
|
|
while(!act_children.empty()){
|
|
root_children.push_back(*act_children.begin());
|
|
act_children.erase(act_children.begin());
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
pos=0;
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
{
|
|
Node_entry YY=*(dynamic_cast<Node_entry*>(XX));
|
|
iterator pos_it = choose_subtree(v.key, &YY.ele[0],
|
|
&YY.ele[IO_max_cap_nodes],
|
|
YY.level);
|
|
while (pos_it!=&YY.ele[pos]&&pos<YY.eles) pos++;
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "The choosed position is:" << pos
|
|
<< std::endl;
|
|
)
|
|
}
|
|
CGAL_DOGN_Control(
|
|
else
|
|
std::cerr << "Wrong dynamic cast 5\n";)
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[pos].key=
|
|
traits.unify((*(dynamic_cast<Node_entry*>(XX))).ele[pos].key, v.key);
|
|
put();
|
|
get(XX->level-1,(*(dynamic_cast<Node_entry*>(XX))).ele[pos].pnext);
|
|
forced_reinsert_node(v, act_children,root_children, OnLevel,
|
|
Reinsert,MaxLevel,LevelPthis);
|
|
if(!act_children.empty()) {
|
|
root_children.insert(root_children.begin(),*act_children.begin());
|
|
act_children.erase(act_children.begin());
|
|
}
|
|
while(!act_children.empty()){
|
|
root_children.push_back(*act_children.begin());
|
|
act_children.erase(act_children.begin());
|
|
}
|
|
if(!root_children.empty()) {
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "Rootpthis is:"
|
|
<< LevelPthis[MaxLevel].second << std::endl;
|
|
)
|
|
get(MaxLevel,LevelPthis[MaxLevel].second);
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[pos]=(*root_children.begin());
|
|
root_children.erase(root_children.begin());
|
|
while(XX->eles < IO_max_cap_nodes && !root_children.empty())
|
|
{
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[XX->eles]=
|
|
*(root_children.begin());
|
|
root_children.erase(root_children.begin());
|
|
XX->eles++;
|
|
}
|
|
//no more childs fit into the root node. Give them back to the root
|
|
put();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//the elements are sorted according to the reinsertion order. Then the first
|
|
//70% are left in the node. The rest has to be reinserted
|
|
void compute_to_split_assign(Node_entry &YY, Key &knew,
|
|
std::back_insert_iterator<std::vector<v_type> > to_reinsert)
|
|
{
|
|
std::vector<v_type> new_elements;
|
|
std::vector<v_type>::iterator It;
|
|
int count=0;
|
|
reinsertion_node((v_type *) &YY.ele[0], (v_type *) &YY.ele[YY.eles],
|
|
std::back_inserter(new_elements),
|
|
to_reinsert,
|
|
IO_min_cap_nodes, IO_max_cap_nodes );
|
|
|
|
YY.clear();
|
|
knew=(*new_elements.begin()).key;
|
|
for(It=new_elements.begin();It!=new_elements.end();It++)
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
traits.dump((*It).key);
|
|
)
|
|
YY.ele[count]=(*It);
|
|
YY.eles++;
|
|
knew = traits.unify(knew, (*It).key);
|
|
count++;
|
|
}
|
|
}
|
|
|
|
void reinsert_node( std::vector<v_type>& root_children,
|
|
int OnLevel,
|
|
std::vector<bool>& Reinsert,
|
|
int MaxLevel,
|
|
std::pair< int,long> *LevelPthis) {
|
|
|
|
std::vector<v_type> to_reinsert;
|
|
std::vector<v_type>::iterator reIt;
|
|
Key knew;
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "REINSERT NODE\n";
|
|
dump_this_node((* dynamic_cast<Node_entry*>(XX)),0,0);
|
|
)
|
|
//for all entries compute the distance between the conters of their
|
|
//rectangles and the center of the bounding rectangle of it.
|
|
//access to the elements is in increasing order
|
|
int act_level=XX->level;
|
|
long act_pthis=XX->pthis;
|
|
compute_to_split_assign(*(dynamic_cast<Node_entry*>(XX)),knew,
|
|
std::back_inserter(to_reinsert));
|
|
put();
|
|
adapt_parent_keys(LevelPthis,knew,act_level+1,MaxLevel);
|
|
for(reIt=to_reinsert.begin();reIt!=to_reinsert.end();reIt++)
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
traits.dump((*reIt).key);
|
|
)
|
|
root_forced_reinsert((*reIt), root_children, OnLevel,
|
|
Reinsert,MaxLevel,LevelPthis);
|
|
get(act_level,act_pthis);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void reinsert_data_split(Data &d, Data_entry &YY, Key &knew,
|
|
std::vector<d_type> &to_reinsert)
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "Reinsert data split\n";
|
|
dump((* dynamic_cast<Data_entry*>(XX)),0,0);
|
|
)
|
|
Data element;
|
|
int i,offset=0;
|
|
std::vector<d_type> new_elements;
|
|
d_type *V;
|
|
V= new d_type[YY.eles+2];
|
|
d_type val;
|
|
val.key = traits.build(d);
|
|
val.ele = d;
|
|
V[0]=val;
|
|
for(i=0;i<YY.eles; i++)
|
|
{
|
|
*ff=YY.raw_data + offset;
|
|
traits.read(ff,element);
|
|
V[i+1].key = traits.build(element);
|
|
V[i+1].ele = element;
|
|
offset += traits.written_size(element);
|
|
}
|
|
reinsertion_leaf(&V[0], &V[YY.eles+1], std::back_inserter(new_elements),
|
|
std::back_inserter(to_reinsert), IO_min_cap_leaves,
|
|
IO_page_size);
|
|
delete[] V;
|
|
d_type *dt;
|
|
YY.leaf_offset=0;
|
|
YY.eles=0;
|
|
knew =new_elements.begin()->key;
|
|
for(dt=new_elements.begin();dt!=new_elements.end();dt++)
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
traits.dump((*dt).key);
|
|
std::cerr << "size: " << traits.written_size((*dt).ele)
|
|
<< std::endl;
|
|
)
|
|
|
|
if(YY.leaf_offset + traits.written_size((*dt).ele) <
|
|
IO_page_size)
|
|
{
|
|
*ff=YY.raw_data + YY.leaf_offset;
|
|
traits.write(ff,(*dt).ele);
|
|
YY.leaf_offset += traits.written_size((*dt).ele);
|
|
YY.eles++;
|
|
knew = traits.unify(knew, dt->key);
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "\n will stay in leaf: ";
|
|
traits.dump(dt->key);
|
|
)
|
|
}
|
|
else
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "reinsertion_leaf has distributed
|
|
to many data elements in the old
|
|
leaf -- the rest will be inserted
|
|
into the other reinsertion vector";
|
|
)
|
|
to_reinsert.push_back(*dt);
|
|
}
|
|
}
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "the bounding box of the leaf is now:";
|
|
traits.dump(knew);
|
|
)
|
|
}
|
|
|
|
|
|
void reinsert_data(Data &d, std::vector<v_type>& root_children,
|
|
int OnLevel, std::vector<bool>& Reinsert,
|
|
int MaxLevel, std::pair< int,long> *LevelPthis)
|
|
{
|
|
std::vector<d_type> to_reinsert;
|
|
std::vector<d_type>::iterator reIt;
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "REINSERT DATA\n";
|
|
dump((* dynamic_cast<Data_entry*>(XX)),0,0);
|
|
)
|
|
int act_level=XX->level;
|
|
long act_pthis=XX->pthis;
|
|
Key knew;
|
|
//determine the elements that are to be reinserted
|
|
reinsert_data_split(d, *(dynamic_cast<Data_entry*>(XX)),knew,to_reinsert);
|
|
put();
|
|
int pos;
|
|
int count=0;
|
|
std::pair< int,long> *IndexPthis= new std::pair< int,long>[MaxLevel+1] ;
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "The new key of the leaf is: " << std::endl;
|
|
traits.dump(knew);
|
|
std::cerr << "Call adapt parent keys\n";
|
|
)
|
|
adapt_parent_keys(LevelPthis,knew,act_level+1,MaxLevel);
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "END of adapt parent keys, now reinsert elements\n";
|
|
)
|
|
for(reIt=to_reinsert.begin();reIt!=to_reinsert.end();reIt++)
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "\n We now reinsert: ";
|
|
traits.dump((*reIt).key);
|
|
std::cerr << "Rootpthis is:" <<
|
|
LevelPthis[MaxLevel].second << std::endl;
|
|
)
|
|
std::vector<v_type> act_children;
|
|
get(MaxLevel,LevelPthis[MaxLevel].second);
|
|
v_type v;
|
|
v.deleted = false;
|
|
v.key= (*reIt).key;
|
|
//use now ordinary insert since it has not to be
|
|
//inserted on a special level
|
|
pos=0;
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
{
|
|
Node_entry YY=*(dynamic_cast<Node_entry*>(XX));
|
|
iterator pos_it = choose_subtree(v.key, &YY.ele[0],
|
|
&YY.ele[IO_max_cap_nodes],
|
|
YY.level);
|
|
while (pos_it!=&YY.ele[pos]&&pos<YY.eles) pos++;
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "The choosed position is:" <<
|
|
pos << std::endl;
|
|
)
|
|
}
|
|
CGAL_DOGN_Control(
|
|
else
|
|
std::cerr << "Wrong dynamic cast 7\n";
|
|
)
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[pos].key=
|
|
traits.unify((*(dynamic_cast<Node_entry*>(XX))).ele[pos].key, v.key);
|
|
put();
|
|
get(XX->level-1,(*(dynamic_cast<Node_entry*>(XX))).ele[pos].pnext);
|
|
insert_star((*reIt).ele, v, act_children,root_children,Reinsert,
|
|
MaxLevel,IndexPthis);
|
|
if(!act_children.empty()) {
|
|
root_children.insert(root_children.begin(),*act_children.begin());
|
|
act_children.erase(act_children.begin());}
|
|
while(!act_children.empty()){
|
|
root_children.push_back(*act_children.begin());
|
|
act_children.erase(act_children.begin());
|
|
}
|
|
if(!root_children.empty()) {
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "Rootpthis is:"
|
|
<< LevelPthis[MaxLevel].second << std::endl;
|
|
)
|
|
get(MaxLevel,LevelPthis[MaxLevel].second);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
{
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[pos]=
|
|
*(root_children.begin());
|
|
root_children.erase(root_children.begin());
|
|
while(XX->eles < IO_max_cap_nodes && !root_children.empty())
|
|
{
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[XX->eles]=
|
|
*(root_children.begin());
|
|
root_children.erase(root_children.begin());
|
|
XX->eles++;
|
|
}
|
|
//no more childs fit into the root node.
|
|
//Give them back to the root
|
|
}
|
|
put();
|
|
}
|
|
count++;
|
|
}
|
|
get(act_level,act_pthis);
|
|
delete [] IndexPthis;
|
|
}
|
|
|
|
|
|
|
|
// a inner node is split.
|
|
void split_node_star(std::vector<v_type> &children,
|
|
std::vector<v_type> &root_children,
|
|
std::vector<bool>& Reinsert,
|
|
int MaxLevel,
|
|
std::pair< int,long> *LevelPthis) {
|
|
int act_level=XX->level;
|
|
if (XX->eles >= IO_max_cap_nodes)
|
|
{
|
|
//it makes no sense to reinsert in the root level
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "(((((((((REINSERT)))))))))))"
|
|
<< act_level << std::endl;
|
|
)
|
|
if(!Reinsert[act_level] || act_level==MaxLevel)
|
|
{
|
|
split_star(children,*(dynamic_cast<Node_entry*>(XX)));
|
|
}
|
|
else
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "(((((((((REINSERT-REALLY)))))))))))"
|
|
<< act_level << std::endl;
|
|
)
|
|
Reinsert[act_level]=false;
|
|
reinsert_node(root_children, act_level,Reinsert,MaxLevel,
|
|
LevelPthis);
|
|
}
|
|
}
|
|
}
|
|
//end R_star
|
|
|
|
void direct_insert(Data &d, Data_entry& YY) {
|
|
*ff=YY.raw_data + YY.leaf_offset;
|
|
traits.write(ff,d);
|
|
YY.leaf_offset += traits.written_size(d);
|
|
YY.eles++;
|
|
CGAL_DOGN_ControlB(
|
|
std::cerr << "direct insert: number of elements"
|
|
<< YY.eles << std::endl;
|
|
)
|
|
}
|
|
|
|
|
|
// the element is inserted into a leaf node.
|
|
// If the available space is not large enough, the
|
|
// data of the leaf node is split according to the split
|
|
// strategy
|
|
bool must_be_reinserted(Data &d,
|
|
std::vector<v_type>& children, std::vector<v_type>& root_children,
|
|
Data_entry& YY,std::vector<bool>& Reinsert, int MaxLevel,
|
|
std::pair< int,long> *LevelPthis) {
|
|
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "Must Be Reinserted\n";
|
|
dump((* dynamic_cast<Data_entry*>(XX)),0,0);
|
|
)
|
|
if (( int)YY.available_space(YY.leaf_offset)< (int)traits.written_size(d))
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "available_space :" <<
|
|
YY.available_space(YY.leaf_offset) << std::endl;
|
|
std::cerr << "size of data:" << traits.written_size(d)
|
|
<< std::endl;
|
|
std::cerr << "pagesize:" << IO_page_size << std::endl;
|
|
std::cerr << "(((((((((REINSERT))))))))))) 0 "
|
|
<< std::endl;
|
|
)
|
|
if(!Reinsert[0] || MaxLevel==0 ) //no reinsertion but a split
|
|
{
|
|
std::vector<Data> V;
|
|
std::vector<d_type> left, right;
|
|
d_type *old;
|
|
old= new d_type[YY.eles+2];
|
|
Data_entry *nleft=new Data_entry();
|
|
Data_entry *nright=new Data_entry();
|
|
Data element;
|
|
d_type val;
|
|
v_type vleft, vright;
|
|
val.key = traits.build(d);
|
|
val.ele = d;
|
|
old[0]=val;
|
|
int i, offset =0;
|
|
for(i=0;i<YY.eles; i++)
|
|
{
|
|
*ff=YY.raw_data + offset;
|
|
traits.read(ff, element);
|
|
V.push_back(element);
|
|
old[i+1].key = traits.build(element);
|
|
old[i+1].ele = element;
|
|
offset += traits.written_size(element);
|
|
}
|
|
|
|
ps_leaf(&old[0], &old[YY.eles+1], std::back_inserter(left),
|
|
std::back_inserter(right), IO_min_cap_leaves,
|
|
IO_page_size);
|
|
delete[] old;
|
|
|
|
d_type *dt;
|
|
Key kleft =left.begin()->key;
|
|
Key kright =right.begin()->key;
|
|
for(dt=left.begin();dt!=left.end();dt++)
|
|
{
|
|
direct_insert(dt->ele,*nleft);
|
|
kleft = traits.unify(kleft, dt->key);
|
|
}
|
|
for(dt=right.begin();dt!=right.end();dt++)
|
|
{
|
|
direct_insert(dt->ele, *nright);
|
|
kright = traits.unify(kright, dt->key);
|
|
}
|
|
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "SPLIT the left and right keys are: "
|
|
<< std::endl;
|
|
traits.dump(kleft);
|
|
traits.dump(kright);
|
|
std::cerr << std::endl;
|
|
)
|
|
|
|
vleft.key = kleft;
|
|
put_data(*nleft, YY.pthis);
|
|
vleft.pnext = YY.pthis;
|
|
vleft.deleted = false;
|
|
|
|
vright.key = kright;
|
|
put_data(*nright,-1);
|
|
vright.pnext = nright->pthis;
|
|
vright.deleted = false;
|
|
|
|
children.erase(children.begin(), children.end());
|
|
children.push_back(vleft);
|
|
children.push_back(vright);
|
|
get(0, YY.pthis);
|
|
delete nleft;
|
|
delete nright;
|
|
return false;
|
|
}
|
|
else{ // do reinsertion - return true
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "(((((((((REINSERT))))))))))) of 0 level"
|
|
<< std::endl;
|
|
)
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*ff=YY.raw_data + YY.leaf_offset;
|
|
traits.write(ff,d);
|
|
YY.leaf_offset += traits.written_size(d);
|
|
YY.eles++;
|
|
put();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
//******************* end R_star
|
|
|
|
// the element is inserted into a leaf node.
|
|
// If the available space is not large enough, the
|
|
// data of the leaf node is split according to the split
|
|
// strategy
|
|
bool insert_star(Data &d,
|
|
std::vector<v_type>& children,
|
|
std::vector<v_type>& root_children,
|
|
std::vector<bool>& Reinsert, int MaxLevel,
|
|
std::pair< int,long> *LevelPthis) {
|
|
int act_level=XX->level;
|
|
long act_pthis=XX->pthis;
|
|
if( must_be_reinserted(d,children, root_children,
|
|
*(dynamic_cast<Data_entry*>(XX)),Reinsert,
|
|
MaxLevel, LevelPthis))
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "(((((((((((REINSERT REALLY)))))))))"
|
|
<< act_level << std::endl;
|
|
)
|
|
get(act_level,act_pthis);
|
|
Reinsert[0]=false;
|
|
reinsert_data(d,root_children,0,Reinsert, MaxLevel,LevelPthis);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
// the data is inserted into an inner node. The node is split
|
|
// if necessary
|
|
bool insert_star(v_type &v, Node_entry& YY) {
|
|
if ((YY.eles >= 0) && (YY.eles < IO_max_cap_nodes)) {
|
|
YY.ele[YY.eles] = v;
|
|
YY.eles++;
|
|
put();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
protected:
|
|
|
|
// a node YY is split into two.
|
|
void split_star(std::vector<v_type> &children, Node_entry &YY) {
|
|
v_type vleft, vright;
|
|
long act_pthis=YY.pthis;
|
|
int act_level=YY.level;
|
|
Node_entry *XXLeft=new Node_entry(YY.level);
|
|
Node_entry *XXRight=new Node_entry(YY.level);
|
|
ps(&YY.ele[0], &YY.ele[YY.eles], &XXLeft->ele[0], &XXRight->ele[0] ,
|
|
IO_min_cap_nodes, IO_max_cap_nodes );
|
|
|
|
vleft.key = build(*XXLeft);
|
|
XXLeft->pthis=act_pthis;
|
|
CGAL_DOGN_Insert(
|
|
dump_this_node((*dynamic_cast<Node_entry*>(XX)),0,0);
|
|
dump_this_node(*XXLeft,0,0);
|
|
)
|
|
put_node(*XXLeft, act_pthis);
|
|
vleft.pnext = act_pthis;
|
|
vleft.deleted = false;
|
|
|
|
vright.key = build(*XXRight);
|
|
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "SPLIT the left and right keys are: "
|
|
<< std::endl;
|
|
traits.dump(vleft.key);
|
|
traits.dump(vright.key);
|
|
std::cerr << std::endl;
|
|
)
|
|
put_node(*XXRight,-1);
|
|
vright.pnext = XXRight->pthis;
|
|
vright.deleted = false;
|
|
|
|
CGAL_DOGN_Insert(
|
|
dump_this_node(*XXRight,0,0);
|
|
dump_this_node(*XXLeft,0,0);
|
|
get(XXRight->level,XXRight->pthis);
|
|
dump_this_node((*dynamic_cast<Node_entry*>(XX)),0,0);
|
|
get(XXLeft->level,XXLeft->pthis);
|
|
dump_this_node((*dynamic_cast<Node_entry*>(XX)),0,0);
|
|
)
|
|
children.erase(children.begin(), children.end());
|
|
children.push_back(vleft);
|
|
children.push_back(vright);
|
|
get(act_level,act_pthis);
|
|
delete XXLeft;
|
|
delete XXRight;
|
|
}
|
|
|
|
public:
|
|
// the key of a node YY is build. It is the union of all keys
|
|
Key build(Node_entry &YY) {
|
|
Key k;
|
|
int i=0;
|
|
while( i<IO_max_cap_nodes && YY.ele[i].deleted)
|
|
i++;
|
|
if(i<IO_max_cap_nodes)
|
|
{
|
|
YY.eles=1;
|
|
k = YY.ele[i].key;
|
|
i++;
|
|
for ( ;i<IO_max_cap_nodes; i++) {
|
|
if (!YY.ele[i].deleted) {
|
|
YY.eles++;
|
|
k=traits.unify(k,YY.ele[i].key);
|
|
}
|
|
}
|
|
}
|
|
return k;
|
|
}
|
|
|
|
// the key of an data entry is build
|
|
Key build(Data_entry &YY)
|
|
{
|
|
Data element;
|
|
Key key;
|
|
int i, offset=0;
|
|
if(YY.eles >0)
|
|
{
|
|
*ff=YY.raw_data + offset;
|
|
traits.read(ff, element);
|
|
key=traits.build(element);
|
|
offset += traits.written_size(element);
|
|
}
|
|
for(i=1;i<YY.eles; i++)
|
|
{
|
|
*ff=YY.raw_data + offset;
|
|
traits.read(ff,element);
|
|
key = traits.unify(key,traits.build(element));
|
|
offset += traits.written_size(element);
|
|
}
|
|
return key;
|
|
}
|
|
|
|
//the data entry is searched for a key a
|
|
bool find_key_data(Key& a, Data_entry& YY)
|
|
{
|
|
Data element;
|
|
Key key;
|
|
int i, offset=0;
|
|
for(i=0;i<YY.eles; i++)
|
|
{
|
|
*ff=YY.raw_data + offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
if(traits.equal_key(key,a))
|
|
return true;
|
|
offset += traits.written_size(element);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool get_next_pos(Key& a, int& pos, long& pnext, Node_entry& YY)
|
|
{
|
|
bool found=false;
|
|
while(!found && pos<YY.eles)
|
|
{
|
|
if (traits.include(YY.ele[pos].key,a)) //compare before
|
|
{
|
|
found=true;
|
|
pnext = YY.ele[pos].pnext;
|
|
}
|
|
pos++;
|
|
}
|
|
return found;
|
|
}
|
|
|
|
//the data entry is searched for a key a
|
|
bool find_key_node(Key& a)
|
|
{
|
|
int act_level=XX->level;
|
|
long act_pthis=XX->pthis;
|
|
int pos=0;
|
|
long pnext=0;
|
|
while(get_next_pos(a, pos,pnext,*(dynamic_cast<Node_entry*>(XX)) ))
|
|
{
|
|
get(act_level-1,pnext);
|
|
if(find_key(a))
|
|
return true;
|
|
get(act_level,act_pthis);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// an entry is searched for a key a
|
|
bool find_key(Key& a) {
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
return find_key_data(a, *(dynamic_cast<Data_entry*>(XX)));
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
return find_key_node(a);
|
|
}
|
|
|
|
//the number of times key a is in YY is returned.
|
|
long search_data(Key& a, Data_entry& YY)
|
|
{
|
|
long k = 0;
|
|
Data element;
|
|
Key key;
|
|
int i, offset=0;
|
|
for(i=0;i<YY.eles; i++)
|
|
{
|
|
*ff=YY.raw_data + offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
if(traits.equal_key(key,a))
|
|
k++;
|
|
offset += traits.written_size(element);
|
|
}
|
|
return k;
|
|
}
|
|
|
|
//the number of times key a is in YY is returned.
|
|
long search_node(Key& a)
|
|
{
|
|
int act_level=XX->level;
|
|
long act_pthis=XX->pthis;
|
|
long k=0;
|
|
long pnext;
|
|
int pos=0;
|
|
while(get_next_pos(a, pos,pnext,*(dynamic_cast<Node_entry*>(XX)) ))
|
|
{
|
|
get(act_level-1,pnext);
|
|
k+= search(a);
|
|
get(act_level,act_pthis);
|
|
}
|
|
return k;
|
|
}
|
|
|
|
//the number of times key a is in a node is returned.
|
|
long search(Key& a) {
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
return search_data(a, *(dynamic_cast<Data_entry*>(XX)));
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
return search_node(a);
|
|
}
|
|
|
|
|
|
|
|
//the number of times key a is in included in XX is returned.
|
|
bool find_key_include(Key& a) {
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
return find_key_include_data(a, *(dynamic_cast<Data_entry*>(XX)));
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
return find_key_include_node(a);
|
|
return false;
|
|
}
|
|
|
|
// true is returned if a is included by an element
|
|
bool find_key_include_data(Key& a, Data_entry& YY)
|
|
{
|
|
Data element;
|
|
Key key;
|
|
int i, offset=0;
|
|
for(i=0;i<YY.eles; i++)
|
|
{
|
|
*ff=YY.raw_data + offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
//returns true if key includes a
|
|
if(traits.include(key,a))
|
|
return true;
|
|
offset += traits.written_size(element);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool get_next_pos_include(Key& a, int& pos, int& pnext, Node_entry& YY)
|
|
{
|
|
bool found=false;
|
|
while(!found && pos<YY.eles)
|
|
{
|
|
if (traits.include(YY.ele[pos].key,a))
|
|
{
|
|
found=true;
|
|
pnext = YY.ele[pos].pnext;
|
|
}
|
|
pos++;
|
|
}
|
|
return found;
|
|
}
|
|
|
|
//the data entry is searched for a key a
|
|
bool find_key_include_node(Key& a)
|
|
{
|
|
int act_level=XX->level;
|
|
long act_pthis=XX->pthis;
|
|
int pos=0, pnext;
|
|
while(get_next_pos_include(a,pos,pnext,*(dynamic_cast<Node_entry*>(XX)) ))
|
|
{
|
|
get(act_level-1,pnext);
|
|
if(find_key_include(a))
|
|
return true;
|
|
get(act_level,act_pthis);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
// true is returned if a is intersected by an element
|
|
bool find_key_intersect_data(Key& a, Data_entry& YY)
|
|
{
|
|
Data element;
|
|
Key key;
|
|
int i, offset=0;
|
|
|
|
for(i=0;i<YY.eles; i++)
|
|
{
|
|
*ff=YY.raw_data + offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
if(traits.intersect(key,a))
|
|
return true;
|
|
offset += traits.written_size(element);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool get_next_pos_inter(Key& a, int& pos, int& pnext, Node_entry& YY)
|
|
{
|
|
bool found=false;
|
|
while(!found && pos<YY.eles)
|
|
{
|
|
if (traits.intersect(YY.ele[pos].key,a))
|
|
{
|
|
found=true;
|
|
pnext = YY.ele[pos].pnext;
|
|
}
|
|
pos++;
|
|
}
|
|
return found;
|
|
}
|
|
|
|
// true is returned if a is intersected by an element
|
|
bool find_key_intersect_node(Key& a)
|
|
{
|
|
int pos=0,pnext;
|
|
int act_level=XX->level;
|
|
long act_pthis=XX->pthis;
|
|
|
|
while(get_next_pos_inter(a, pos,pnext,*(dynamic_cast<Node_entry*>(XX)) ))
|
|
{
|
|
get(act_level-1,pnext);
|
|
if(find_key_intersect(a))
|
|
return true;
|
|
get(act_level,act_pthis);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// true is returned if a is intersected by an element
|
|
bool find_key_intersect(Key& a) {
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
return find_key_intersect_data(a, *(dynamic_cast<Data_entry*>(XX)));
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
return find_key_intersect_node(a);
|
|
return false;
|
|
}
|
|
|
|
//********************INTERSECTION ITERATOR **************************
|
|
|
|
// the node infos are colleced in a stack. Therefore the iteration
|
|
// process can resume from the last node info on the stack
|
|
void collect_node_infos(Node_entry& YY,
|
|
std::list<Node_info*>& node_stack, Key k){
|
|
int i;
|
|
Node_info *n;
|
|
for (i = 0; i < YY.eles; i++)
|
|
{
|
|
if (traits.intersect(YY.ele[i].key,k))
|
|
{
|
|
n=new Node_info;
|
|
n->level=YY.level-1;
|
|
n->pnext=YY.ele[i].pnext;
|
|
node_stack.push_front(n);
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "element put on stack with key: ";
|
|
traits.dump(YY.ele[i].key,4);
|
|
std::cerr << std::endl;
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
//same as above. But for the end iterator everything is reversed
|
|
void reverse_collect_node_infos(Node_entry& YY,
|
|
std::list<Node_info*>& node_stack, Key k){
|
|
int i;
|
|
Node_info *n;
|
|
for (i = 0; i<YY.eles; i++)
|
|
{
|
|
if (traits.intersect(YY.ele[i].key,k))
|
|
{
|
|
n=new Node_info;
|
|
n->level=YY.level-1; //???
|
|
n->pnext=YY.ele[i].pnext;
|
|
node_stack.push_back(n);
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "element put on stack with key: ";
|
|
traits.dump(YY.ele[i].key,4);
|
|
std::cerr << "level" << n->level << std::endl;
|
|
std::cerr << "pnext" << n->pnext << std::endl;
|
|
std::cerr << std::endl;
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void test_actual_data(Data_entry &actual_data)
|
|
{
|
|
int element_offset=0;
|
|
int next_element=0;
|
|
Data element;
|
|
Key key;
|
|
while (next_element < actual_data.eles)
|
|
{
|
|
*ff=actual_data.raw_data + element_offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
traits.dump(key);
|
|
next_element++;
|
|
element_offset+=traits.written_size(element);
|
|
}
|
|
}
|
|
|
|
bool found_init_iterator_data(Data_entry& YY,
|
|
std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data, int& next_element,
|
|
Key k, Data &next_data, int& element_offset)
|
|
{
|
|
Data element;
|
|
Key key;
|
|
element_offset=0;
|
|
next_element=0;
|
|
bool found=false;
|
|
while (next_element < YY.eles && !found)
|
|
{
|
|
*ff=YY.raw_data + element_offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "data init 1\n";
|
|
traits.dump(key,4);
|
|
)
|
|
if(traits.intersect(key,k))
|
|
{
|
|
next_data=element;
|
|
found = true;
|
|
for( int i=0;i<IO_page_size;i++)
|
|
actual_data.raw_data[i]=YY.raw_data[i];
|
|
actual_data.eles=YY.eles;
|
|
CGAL_DOGN_Search(
|
|
std::cerr<< "-------------Test actual data:\n";
|
|
test_actual_data(actual_data);
|
|
std::cerr << "------------end\n";
|
|
)
|
|
}
|
|
element_offset += traits.written_size(element);
|
|
next_element++;
|
|
}
|
|
return found;
|
|
}
|
|
|
|
bool init_iterator_data(std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data, int& next_element, Key k,
|
|
Data &next_data, int& element_offset)
|
|
{
|
|
if(!found_init_iterator_data((*dynamic_cast<Data_entry*>(XX)),
|
|
node_stack,actual_data, next_element, k,
|
|
next_data,element_offset))
|
|
{
|
|
Node_info *ni;
|
|
if(!node_stack.empty())
|
|
{
|
|
ni=(*node_stack.begin());
|
|
node_stack.pop_front();
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "data init 5 -- node stack not empty\n";
|
|
std::cerr << "00000000pop from stack \n";
|
|
std::cerr << "stack length " << node_stack.size()
|
|
<< std::endl;
|
|
std::cerr << "level:" << ni->level << std::endl;
|
|
std::cerr << "pnext:" << ni->pnext << std::endl;
|
|
)
|
|
get(ni->level,ni->pnext);
|
|
delete ni;
|
|
return init_iterator(node_stack,actual_data,next_element,
|
|
k,next_data,element_offset);
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool found_reverse_init_iterator_data(Data_entry& YY,
|
|
std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data,
|
|
int& next_element, Key k,
|
|
Data &next_data, int& element_offset)
|
|
{
|
|
Data element;
|
|
Key key;
|
|
element_offset=0;
|
|
next_element=0;
|
|
bool found=false;
|
|
while (next_element < YY.eles)
|
|
{
|
|
*ff=YY.raw_data + element_offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
if(traits.intersect(key,k))
|
|
{
|
|
next_data=element;
|
|
found = true;
|
|
for( int i=0;i<IO_page_size;i++)
|
|
actual_data.raw_data[i]=YY.raw_data[i];
|
|
actual_data.eles=YY.eles;
|
|
}
|
|
element_offset += traits.written_size(element);
|
|
next_element++;
|
|
}
|
|
return found;
|
|
}
|
|
|
|
bool reverse_init_iterator_data(std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data,
|
|
int& next_element, Key k,
|
|
Data &next_data, int& element_offset)
|
|
{
|
|
Node_info *ni;
|
|
if(!found_reverse_init_iterator_data((*dynamic_cast<Data_entry*>(XX)),
|
|
node_stack,actual_data, next_element,
|
|
k, next_data,element_offset))
|
|
{
|
|
if(!node_stack.empty())
|
|
{
|
|
ni=*(node_stack.begin());
|
|
node_stack.pop_front();
|
|
get(ni->level,ni->pnext);
|
|
delete ni;
|
|
return reverse_init_iterator(node_stack,actual_data,next_element,
|
|
k,next_data,element_offset);
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool init_iterator_node(std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data, int& next_element, Key k,
|
|
Data &next_data, int& element_offset)
|
|
{
|
|
Node_info *ni;
|
|
collect_node_infos((*dynamic_cast<Node_entry*>(XX)) ,node_stack,k);
|
|
if(!node_stack.empty())
|
|
{
|
|
ni=*(node_stack.begin());
|
|
node_stack.pop_front();
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "init_iterator node 2\n";
|
|
std::cerr << "0000000000pop from stack\n";
|
|
std::cerr << "stack length " << node_stack.size()
|
|
<< std::endl;
|
|
std::cerr << "level:" << ni->level << std::endl;
|
|
std::cerr << "pnext:" << ni->pnext << std::endl;
|
|
std::cerr << "init_iterator node 3\n";
|
|
)
|
|
get(ni->level,ni->pnext);
|
|
delete ni;
|
|
return init_iterator(node_stack,actual_data,next_element,
|
|
k,next_data,element_offset);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool reverse_init_iterator_node(std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data, int& next_element,
|
|
Key k, Data &next_data, int& element_offset)
|
|
{
|
|
Node_info *ni;
|
|
|
|
reverse_collect_node_infos((*dynamic_cast<Node_entry*>(XX)),node_stack,k);
|
|
if(!node_stack.empty())
|
|
{
|
|
ni=*(node_stack.begin());
|
|
node_stack.pop_front();
|
|
get(ni->level,ni->pnext);
|
|
delete ni;
|
|
return reverse_init_iterator(node_stack,actual_data,next_element,
|
|
k,next_data,element_offset);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
bool init_iterator(std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data, int& next_element,
|
|
Key k, Data &next_data, int& element_offset)
|
|
{
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
return init_iterator_data(node_stack,
|
|
actual_data,next_element,k,next_data,element_offset);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
return init_iterator_node(node_stack,
|
|
actual_data,next_element,k,next_data,element_offset);
|
|
return false;
|
|
}
|
|
|
|
bool reverse_init_iterator(std::list<Node_info*>& node_stack,
|
|
Data_entry& actual_data, int& next_element,
|
|
Key k, Data& next_data, int& element_offset)
|
|
{
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
return reverse_init_iterator_data(node_stack,
|
|
actual_data,next_element,k,next_data,
|
|
element_offset);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
return reverse_init_iterator_node(node_stack,
|
|
actual_data,next_element,k,next_data,
|
|
element_offset);
|
|
return false;
|
|
}
|
|
|
|
|
|
// find the next element of the iteration
|
|
bool next_element(std::list<Node_info*>& node_stack,
|
|
Data_entry& actual_data, int& next_element,
|
|
Key k, Data& next_data, int& element_offset)
|
|
{
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "next element 1\n";
|
|
std::cerr << next_element << std::endl;
|
|
std::cerr << element_offset << std::endl;
|
|
std::cerr<< "-------------Test actual data:\n";
|
|
test_actual_data(actual_data);
|
|
std::cerr << "------------end\n";
|
|
)
|
|
Node_info *ni;
|
|
Data element;
|
|
Key key;
|
|
bool found=false;
|
|
while (next_element < actual_data.eles && !found)
|
|
{
|
|
*ff=actual_data.raw_data + element_offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "next element 2\n";
|
|
traits.dump(key,4);
|
|
)
|
|
if(traits.intersect(key,k))
|
|
{
|
|
next_data=element;
|
|
found = true;
|
|
}
|
|
element_offset += traits.written_size(element);
|
|
next_element++;
|
|
}
|
|
if(!found)
|
|
{
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "next element 4\n";
|
|
)
|
|
if(!node_stack.empty())
|
|
{
|
|
ni=*(node_stack.begin());
|
|
|
|
int zz=ni->level;
|
|
CGAL_DOGN_Search(
|
|
int z=ni->level;
|
|
std::cerr << "next element 5\n";
|
|
std::cerr << "stack length " << node_stack.size()
|
|
<< std::endl;
|
|
std::cerr << "0000000000pop from stack\n";
|
|
std::cerr << "level:" << ni->level << std::endl;
|
|
std::cerr << "pnext:" << ni->pnext << std::endl;
|
|
std::cerr << "level:z " << z << std::endl;
|
|
std::cerr << "level:" << ni->level << std::endl;
|
|
std::cerr << "level:" << ni->level << std::endl;
|
|
z=ni->level;
|
|
)
|
|
get(zz,ni->pnext);
|
|
node_stack.pop_front();
|
|
delete ni;
|
|
return init_iterator(node_stack,actual_data,next_element,
|
|
k,next_data,element_offset);
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//********************ENCLOSING ITERATOR **************************
|
|
//everything for the enclosing iterator
|
|
|
|
void collect_encl_node_infos(Node_entry& YY,
|
|
std::list<Node_info*>& node_stack, Key k){
|
|
iterator i;
|
|
Node_info *n;
|
|
for (i = &YY.ele[0]; i !=&YY.ele[YY.eles];i++)
|
|
{
|
|
if (traits.include((*i).key,k))
|
|
{
|
|
n=new Node_info;
|
|
n->level=YY.level-1; // or like that???
|
|
n->pnext=(*i).pnext;
|
|
node_stack.push_front(n);
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "element put on stack with key: ";
|
|
traits.dump((*i).key,4);
|
|
std::cerr << std::endl;
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
void reverse_collect_encl_node_infos(Node_entry& YY,
|
|
std::list<Node_info*>& node_stack, Key k){
|
|
iterator i;
|
|
Node_info *n;
|
|
for (i = &YY.ele[0]; i !=&YY.ele[YY.eles];i++)
|
|
{
|
|
if (traits.intersect((*i).key,k))
|
|
{
|
|
n=new Node_info;
|
|
n->level=YY.level-1; //or like that ???
|
|
n->pnext=(*i).pnext;
|
|
node_stack.push_back(n);
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "element put on stack with key: ";
|
|
traits.dump((*i).key,4);
|
|
std::cerr << std::endl;
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
bool found_init_encl_iterator_data(Data_entry& YY, std::list<Node_info*>&
|
|
node_stack, Data_entry &actual_data,
|
|
int& next_element, Key k,
|
|
Data &next_data, int& element_offset)
|
|
{
|
|
Data element;
|
|
Key key;
|
|
element_offset=0;
|
|
next_element=0;
|
|
bool found=false;
|
|
while (next_element < YY.eles && !found)
|
|
{
|
|
*ff=YY.raw_data + element_offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
CGAL_DOGN_Search(
|
|
traits.dump(key,4);
|
|
)
|
|
if(traits.include(key,k))
|
|
{
|
|
next_data=element;
|
|
found = true;
|
|
for( int i=0;i<IO_page_size;i++)
|
|
actual_data.raw_data[i]=YY.raw_data[i];
|
|
actual_data.eles=YY.eles;
|
|
}
|
|
element_offset += traits.written_size(element);
|
|
next_element++;
|
|
}
|
|
return found;
|
|
}
|
|
|
|
|
|
bool init_encl_iterator_data(std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data, int& next_element,
|
|
Key k, Data &next_data, int& element_offset)
|
|
{
|
|
Node_info *ni;
|
|
if(!found_init_encl_iterator_data((*dynamic_cast<Data_entry*>(XX)),
|
|
node_stack,actual_data, next_element, k,
|
|
next_data,element_offset))
|
|
{
|
|
if(!node_stack.empty())
|
|
{
|
|
ni=(*node_stack.begin());
|
|
node_stack.pop_front();
|
|
get(ni->level,ni->pnext);
|
|
delete ni;
|
|
return init_encl_iterator(node_stack,actual_data,next_element,
|
|
k,next_data,element_offset);
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
bool found_reverse_init_encl_iterator_data(Data_entry& YY,
|
|
std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data,
|
|
int& next_element, Key k,
|
|
Data &next_data,
|
|
int& element_offset)
|
|
{
|
|
Data element;
|
|
Key key;
|
|
element_offset=0;
|
|
next_element=0;
|
|
bool found=false;
|
|
while (next_element < YY.eles)
|
|
{
|
|
*ff=YY.raw_data + element_offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
if(traits.include(key,k))
|
|
{
|
|
next_data=element;
|
|
found = true;
|
|
for( int i=0;i<IO_page_size;i++)
|
|
actual_data.raw_data[i]=YY.raw_data[i];
|
|
actual_data.eles=YY.eles;
|
|
}
|
|
element_offset += traits.written_size(element);
|
|
next_element++;
|
|
}
|
|
return found;
|
|
}
|
|
|
|
bool reverse_init_encl_iterator_data(std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data,
|
|
int& next_element, Key k,
|
|
Data &next_data, int& element_offset)
|
|
{
|
|
Node_info *ni;
|
|
if(!found_reverse_init_encl_iterator_data(
|
|
(*dynamic_cast<Data_entry*>(XX)),
|
|
node_stack,actual_data, next_element, k,
|
|
next_data,element_offset))
|
|
{
|
|
if(!node_stack.empty())
|
|
{
|
|
ni=*(node_stack.begin());
|
|
node_stack.pop_front();
|
|
get(ni->level,ni->pnext);
|
|
delete ni;
|
|
return reverse_init_encl_iterator(node_stack,actual_data,
|
|
next_element,
|
|
k,next_data,element_offset);
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool init_encl_iterator_node(std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data,
|
|
int& next_element, Key k,
|
|
Data &next_data, int& element_offset)
|
|
{
|
|
Node_info *ni;
|
|
// std::cerr << "init_iterator node 1\n";
|
|
collect_encl_node_infos((*dynamic_cast<Node_entry*>(XX)),node_stack,k);
|
|
if(!node_stack.empty())
|
|
{
|
|
ni=*(node_stack.begin());
|
|
node_stack.pop_front();
|
|
get(ni->level,ni->pnext);
|
|
delete ni;
|
|
return init_encl_iterator(node_stack,actual_data,next_element,
|
|
k,next_data,element_offset);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
bool reverse_init_encl_iterator_node(std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data,
|
|
int& next_element, Key k,
|
|
Data &next_data, int& element_offset)
|
|
{
|
|
Node_info *ni;
|
|
|
|
reverse_collect_node_infos((*dynamic_cast<Node_entry*>(XX)),node_stack,k);
|
|
if(!node_stack.empty())
|
|
{
|
|
ni=*(node_stack.begin());
|
|
node_stack.pop_front();
|
|
get(ni->level,ni->pnext);
|
|
delete ni;
|
|
return reverse_init_encl_iterator(node_stack,actual_data,next_element,
|
|
k,next_data,element_offset);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
bool init_encl_iterator(std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data, int& next_element,
|
|
Key k, Data &next_data, int& element_offset)
|
|
{
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
return init_encl_iterator_data(node_stack,
|
|
actual_data,next_element,k,next_data,
|
|
element_offset);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
return init_encl_iterator_node(node_stack,
|
|
actual_data,next_element,k,next_data,
|
|
element_offset);
|
|
return false;
|
|
}
|
|
|
|
bool reverse_init_encl_iterator(std::list<Node_info*>& node_stack,
|
|
Data_entry& actual_data, int& next_element,
|
|
Key k, Data& next_data, int& element_offset)
|
|
{
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
return reverse_init_encl_iterator_data(node_stack,
|
|
actual_data,next_element,k,next_data,
|
|
element_offset);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
return reverse_init_encl_iterator_node(node_stack,
|
|
actual_data,next_element,k,next_data,
|
|
element_offset);
|
|
return false;
|
|
}
|
|
|
|
bool next_encl_element(std::list<Node_info*>& node_stack,
|
|
Data_entry& actual_data, int& next_element,
|
|
Key k, Data& next_data, int& element_offset)
|
|
{
|
|
Node_info *ni;
|
|
Data element;
|
|
Key key;
|
|
bool found=false;
|
|
while (next_element < actual_data.eles && !found)
|
|
{
|
|
*ff=actual_data.raw_data + element_offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
CGAL_DOGN_Search(
|
|
traits.dump(key,4);
|
|
)
|
|
if(traits.include(key,k))
|
|
{
|
|
next_data=element;
|
|
found = true;
|
|
}
|
|
element_offset += traits.written_size(element);
|
|
next_element++;
|
|
}
|
|
if(!found)
|
|
{
|
|
if(!node_stack.empty())
|
|
{
|
|
ni=*(node_stack.begin());
|
|
int zz=ni->level;
|
|
get(zz,ni->pnext);
|
|
node_stack.pop_front();
|
|
delete ni;
|
|
return init_encl_iterator(node_stack,actual_data,next_element,
|
|
k,next_data,element_offset);
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
//********************COMPARE ITERATOR **************************
|
|
|
|
|
|
void collect_compare_node_infos(Node_entry& YY,
|
|
std::list<Node_info*>& node_stack, Key k){
|
|
iterator i;
|
|
Node_info *n;
|
|
for (i = &YY.ele[0]; i !=&YY.ele[YY.eles];i++)
|
|
{
|
|
if (traits.compare((*i).key,k))
|
|
{
|
|
n=new Node_info;
|
|
n->level=YY.level-1; // or like that???
|
|
n->pnext=(*i).pnext;
|
|
node_stack.push_front(n);
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "element put on stack with key: ";
|
|
traits.dump((*i).key,4);
|
|
std::cerr << std::endl;
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
void reverse_collect_compare_node_infos(Node_entry& YY,
|
|
std::list<Node_info*>& node_stack, Key k){
|
|
iterator i;
|
|
Node_info *n;
|
|
for (i = &YY.ele[0]; i !=&YY.ele[YY.eles];i++)
|
|
{
|
|
if (traits.compare((*i).key,k))
|
|
{
|
|
n=new Node_info;
|
|
n->level=YY.level-1; //or like that ???
|
|
n->pnext=(*i).pnext;
|
|
node_stack.push_back(n);
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "element put on stack with key: ";
|
|
traits.dump((*i).key,4);
|
|
std::cerr << std::endl;
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
bool found_init_compare_iterator_data(Data_entry& YY,
|
|
std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data, int& next_element,
|
|
Key k, Data &next_data, int& element_offset)
|
|
{
|
|
Data element;
|
|
Key key;
|
|
element_offset=0;
|
|
next_element=0;
|
|
bool found=false;
|
|
while (next_element < YY.eles && !found)
|
|
{
|
|
*ff=YY.raw_data + element_offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
CGAL_DOGN_Search(
|
|
traits.dump(key,4);
|
|
)
|
|
if(traits.compare(key,k))
|
|
{
|
|
next_data=element;
|
|
found = true;
|
|
for( int i=0;i<IO_page_size;i++)
|
|
actual_data.raw_data[i]=YY.raw_data[i];
|
|
actual_data.eles=YY.eles;
|
|
}
|
|
element_offset += traits.written_size(element);
|
|
next_element++;
|
|
}
|
|
return found;
|
|
}
|
|
|
|
|
|
bool init_compare_iterator_data(std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data, int& next_element,
|
|
Key k, Data &next_data, int& element_offset)
|
|
{
|
|
Node_info *ni;
|
|
if(!found_init_compare_iterator_data((*dynamic_cast<Data_entry*>(XX)),
|
|
node_stack,actual_data,
|
|
next_element, k,
|
|
next_data,element_offset))
|
|
{
|
|
if(!node_stack.empty())
|
|
{
|
|
ni=(*node_stack.begin());
|
|
node_stack.pop_front();
|
|
get(ni->level,ni->pnext);
|
|
delete ni;
|
|
return init_compare_iterator(node_stack,actual_data,next_element,
|
|
k,next_data,element_offset);
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
bool found_reverse_init_compare_iterator_data(Data_entry& YY,
|
|
std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data,
|
|
int& next_element, Key k,
|
|
Data &next_data,
|
|
int& element_offset)
|
|
{
|
|
Data element;
|
|
Key key;
|
|
element_offset=0;
|
|
next_element=0;
|
|
bool found=false;
|
|
while (next_element < YY.eles)
|
|
{
|
|
*ff=YY.raw_data + element_offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
if(traits.compare(key,k))
|
|
{
|
|
next_data=element;
|
|
found = true;
|
|
for( int i=0;i<IO_page_size;i++)
|
|
actual_data.raw_data[i]=YY.raw_data[i];
|
|
actual_data.eles=YY.eles;
|
|
}
|
|
element_offset += traits.written_size(element);
|
|
next_element++;
|
|
}
|
|
return found;
|
|
}
|
|
|
|
bool reverse_init_compare_iterator_data(std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data,
|
|
int& next_element, Key k,
|
|
Data &next_data, int& element_offset)
|
|
{
|
|
Node_info *ni;
|
|
if(!found_reverse_init_compare_iterator_data(
|
|
(*dynamic_cast<Data_entry*>(XX)),
|
|
node_stack,actual_data, next_element, k,
|
|
next_data,element_offset))
|
|
{
|
|
if(!node_stack.empty())
|
|
{
|
|
ni=*(node_stack.begin());
|
|
node_stack.pop_front();
|
|
get(ni->level,ni->pnext);
|
|
delete ni;
|
|
return reverse_init_compare_iterator(
|
|
node_stack,actual_data,next_element,
|
|
k,next_data,element_offset);
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool init_compare_iterator_node(std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data,
|
|
int& next_element, Key k,
|
|
Data &next_data, int& element_offset)
|
|
{
|
|
Node_info *ni;
|
|
// std::cerr << "init_iterator node 1\n";
|
|
collect_compare_node_infos((*dynamic_cast<Node_entry*>(XX)),node_stack,k);
|
|
if(!node_stack.empty())
|
|
{
|
|
ni=*(node_stack.begin());
|
|
node_stack.pop_front();
|
|
get(ni->level,ni->pnext);
|
|
delete ni;
|
|
return init_compare_iterator(node_stack,actual_data,next_element,
|
|
k,next_data,element_offset);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
bool reverse_init_compare_iterator_node(std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data,
|
|
int& next_element, Key k,
|
|
Data &next_data, int& element_offset)
|
|
{
|
|
Node_info *ni;
|
|
|
|
reverse_collect_node_infos((*dynamic_cast<Node_entry*>(XX)),node_stack,k);
|
|
if(!node_stack.empty())
|
|
{
|
|
ni=*(node_stack.begin());
|
|
node_stack.pop_front();
|
|
get(ni->level,ni->pnext);
|
|
delete ni;
|
|
return reverse_init_compare_iterator(node_stack,
|
|
actual_data,next_element,
|
|
k,next_data,element_offset);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
bool init_compare_iterator(std::list<Node_info*>& node_stack,
|
|
Data_entry &actual_data, int& next_element,
|
|
Key k, Data &next_data, int& element_offset)
|
|
{
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
return init_compare_iterator_data(node_stack,
|
|
actual_data,next_element,k,next_data,
|
|
element_offset);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
return init_compare_iterator_node(node_stack,
|
|
actual_data,next_element,k,next_data,
|
|
element_offset);
|
|
return false;
|
|
}
|
|
|
|
bool reverse_init_compare_iterator(std::list<Node_info*>& node_stack,
|
|
Data_entry& actual_data, int& next_element,
|
|
Key k, Data& next_data, int& element_offset)
|
|
{
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
return reverse_init_compare_iterator_data(node_stack,
|
|
actual_data,next_element,k,next_data,
|
|
element_offset);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
return reverse_init_compare_iterator_node(node_stack,
|
|
actual_data,next_element,k,next_data,
|
|
element_offset);
|
|
return false;
|
|
}
|
|
|
|
bool next_compare_element(std::list<Node_info*>& node_stack,
|
|
Data_entry& actual_data, int& next_element,
|
|
Key k, Data& next_data, int& element_offset)
|
|
{
|
|
Node_info *ni;
|
|
Data element;
|
|
Key key;
|
|
bool found=false;
|
|
while (next_element < actual_data.eles && !found)
|
|
{
|
|
*ff=actual_data.raw_data + element_offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
CGAL_DOGN_Search(
|
|
traits.dump(key,4);
|
|
)
|
|
if(traits.compare(key,k))
|
|
{
|
|
next_data=element;
|
|
found = true;
|
|
}
|
|
element_offset += traits.written_size(element);
|
|
next_element++;
|
|
}
|
|
if(!found)
|
|
{
|
|
if(!node_stack.empty())
|
|
{
|
|
ni=*(node_stack.begin());
|
|
int zz=ni->level;
|
|
get(zz,ni->pnext);
|
|
node_stack.pop_front();
|
|
delete ni;
|
|
return init_compare_iterator(node_stack,actual_data,next_element,
|
|
k,next_data,element_offset);
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
//*************************SEARCH ***************************
|
|
|
|
|
|
|
|
|
|
// the elements are returned that a intersects.
|
|
std::back_insert_iterator<std::list<Data> > search_intersect(Key& a,
|
|
Data_entry& YY,
|
|
std::back_insert_iterator<std::list<Data> >& result)
|
|
{
|
|
Data element;
|
|
Key key;
|
|
int i, offset=0;
|
|
for(i=0;i<YY.eles; i++)
|
|
{
|
|
*ff=YY.raw_data + offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
if(traits.intersect(key,a))
|
|
(*result++)=element;
|
|
offset += traits.written_size(element);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
Key bounding_box(Data_entry& YY)
|
|
{
|
|
Key key,k;
|
|
Data element;
|
|
int i, offset=0;
|
|
*ff=YY.raw_data + offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
for(i=0;i<YY.eles; i++)
|
|
{
|
|
*ff=YY.raw_data + offset;
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
k=traits.unify(k,key);
|
|
offset += traits.written_size(element);
|
|
CGAL_DOGN_ControlB(
|
|
traits.dump(k,4);
|
|
)
|
|
}
|
|
return k;
|
|
}
|
|
|
|
Key bounding_box(Node_entry& YY)
|
|
{
|
|
int i;
|
|
Key k;
|
|
k=YY.ele[0].key;
|
|
for (i = 1; i < YY.eles; i++)
|
|
{
|
|
k=traits.unify(k,YY.ele[i].key);
|
|
CGAL_DOGN_ControlB(
|
|
traits.dump(k,4);
|
|
)
|
|
}
|
|
return k;
|
|
}
|
|
|
|
|
|
Key bounding_box()
|
|
{
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
return bounding_box(*(dynamic_cast<Data_entry*>(XX)));
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
return bounding_box(*(dynamic_cast<Node_entry*>(XX)));
|
|
Key a; //fake
|
|
return a;
|
|
}
|
|
|
|
|
|
//the key at pos i was deleted. Another key is copied to that place
|
|
void reorder_keys(Node_entry& YY, int i)
|
|
{
|
|
int ki=YY.eles;
|
|
while(ki>i && YY.ele[ki].deleted)
|
|
ki--;
|
|
if(ki>i)
|
|
{
|
|
YY.ele[i]=YY.ele[ki];
|
|
YY.ele[ki].deleted=true;
|
|
}
|
|
}
|
|
|
|
//after a reinsertion call the parent keys have to be adapted
|
|
void adapt_parent_keys(std::pair< int,long>* LevelPthis, Key k, int level,
|
|
int MaxLevel)
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "ADAPT PARENT KEYS\n";
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
dump((* dynamic_cast<Data_entry*>(XX)),0,0);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
dump_this_node((* dynamic_cast<Node_entry*>(XX)),0,0);
|
|
)
|
|
if(level<=MaxLevel)
|
|
{
|
|
get(level,LevelPthis[level].second);
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[LevelPthis[level].first].key=k;
|
|
put();
|
|
k = build(*(dynamic_cast<Node_entry*>(XX)));
|
|
adapt_parent_keys(LevelPthis,k,level+1,MaxLevel);
|
|
}
|
|
}
|
|
|
|
void adapt_parent_keys(std::pair< int,long>* LevelPthis, int level,
|
|
int MaxLevel,std::vector<v_type>& root_children,
|
|
std::vector<bool>& Reinsert)
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "ADAPT PARENT KEYS\n";
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
dump((* dynamic_cast<Data_entry*>(XX)),0,0);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
dump_this_node((* dynamic_cast<Node_entry*>(XX)),0,0);
|
|
)
|
|
if(level<=MaxLevel)
|
|
{
|
|
get(level,LevelPthis[level].second);
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[LevelPthis[level].first].deleted=
|
|
true;
|
|
XX->eles--;
|
|
reorder_keys(*(dynamic_cast<Node_entry*>(XX)),LevelPthis[level].first);
|
|
put();
|
|
CGAL_DOGN_Insert(
|
|
dump_this_node((* dynamic_cast<Node_entry*>(XX)),0,0);
|
|
)
|
|
if(XX->eles < IO_min_cap_nodes && level < MaxLevel)
|
|
//must be deleted
|
|
{
|
|
adapt_parent_keys(LevelPthis,level+1,MaxLevel,
|
|
root_children,Reinsert);
|
|
// get the child node again and reinsert all element on level
|
|
get(level,LevelPthis[level].second);
|
|
int j;
|
|
for(j=0;j<XX->eles;j++)
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
dump_this_node((* dynamic_cast<Node_entry*>(XX)),
|
|
0,0);
|
|
)
|
|
v_type v=((*dynamic_cast<Node_entry*>(XX))).ele[j];
|
|
root_forced_reinsert(v,root_children, level,Reinsert,
|
|
MaxLevel,LevelPthis);
|
|
get(level,LevelPthis[level].second);
|
|
}
|
|
erase(LevelPthis[level].second);
|
|
}
|
|
else
|
|
{
|
|
Key k;
|
|
k = build(*(dynamic_cast<Node_entry*>(XX)));
|
|
CGAL_DOGN_Insert(
|
|
traits.dump(k);
|
|
dump_this_node((* dynamic_cast<Node_entry*>(XX)),0,0);
|
|
)
|
|
adapt_parent_keys(LevelPthis,k,level+1,MaxLevel);
|
|
}
|
|
}
|
|
}
|
|
|
|
// the elements are deleted that have key a.
|
|
bool XXdelete_key_data(Key& a,
|
|
Data& result,
|
|
std::pair< int,long> *LevelPthis,
|
|
std::vector<bool>& Reinsert, int MaxLevel,
|
|
std::vector<v_type>& children)
|
|
{
|
|
bool found=false;
|
|
CGAL_DOGN_Delete(
|
|
std::cerr << "XXdelete_key_data\n";
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
dump((* dynamic_cast<Data_entry*>(XX)),0,0);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
dump_this_node((* dynamic_cast<Node_entry*>(XX)),0,0);
|
|
)
|
|
Data element;
|
|
Key key;
|
|
bool touched = false;
|
|
int i, num_eles = XX->eles;
|
|
int offset=0, act_level=XX->level;
|
|
long act_pthis=XX->pthis;
|
|
std::list<Data> to_del;
|
|
i=0;
|
|
while(i<num_eles && !found)
|
|
{
|
|
*ff=((*(dynamic_cast<Data_entry*>(XX))).raw_data + offset);
|
|
traits.read(ff,element);
|
|
key = traits.build(element);
|
|
if(traits.equal_key(key,a))
|
|
{
|
|
touched = true;
|
|
found = true;
|
|
result=element;
|
|
(*(dynamic_cast<Data_entry*>(XX))).delete_key(offset,
|
|
traits.written_size(element));
|
|
put();
|
|
CGAL_DOGN_Delete(
|
|
dump((* dynamic_cast<Data_entry*>(XX)),0,0);
|
|
)
|
|
}
|
|
else
|
|
offset += traits.written_size(element);
|
|
i++;
|
|
}
|
|
if(XX->underfilled() && MaxLevel > 0) //otherwise a node can be underfilled
|
|
{
|
|
// the vertex is eliminated, the parent keys are adapted
|
|
adapt_parent_keys( LevelPthis,XX->level+1, MaxLevel,
|
|
children, Reinsert);
|
|
get(act_level,act_pthis);
|
|
CGAL_DOGN_Delete(
|
|
dump((* dynamic_cast<Data_entry*>(XX)),0,0);
|
|
)
|
|
Data element;
|
|
std::vector<v_type> act_children;
|
|
v_type v;
|
|
int j,offset=0;
|
|
num_eles=XX->eles;
|
|
for(j=0;j<num_eles;j++)
|
|
{
|
|
*ff=(*(dynamic_cast<Data_entry*>(XX))).raw_data + offset;
|
|
traits.read(ff,element);
|
|
offset += traits.written_size(element);
|
|
get(MaxLevel,LevelPthis[MaxLevel].second);
|
|
v.deleted = false;
|
|
v.key= traits.build(element);
|
|
//use now ordenary insert since it has not to be
|
|
//inserted on a special level
|
|
insert_star(element, v, act_children,children,Reinsert,
|
|
MaxLevel,LevelPthis);
|
|
if(!act_children.empty()) {
|
|
children.insert(children.begin(),*act_children.begin());
|
|
act_children.erase(act_children.begin());
|
|
}
|
|
while(!act_children.empty()){
|
|
children.push_back(*act_children.begin());
|
|
act_children.erase(act_children.begin());
|
|
}
|
|
if(!children.empty()) {
|
|
CGAL_DOGN_Delete(
|
|
std::cerr << "Rootpthis is:" <<
|
|
LevelPthis[MaxLevel].second << std::endl;
|
|
)
|
|
get(MaxLevel,LevelPthis[MaxLevel].second);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
{
|
|
int pos=LevelPthis[MaxLevel].first; //the changed index
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[pos]=*
|
|
(children.begin());
|
|
children.erase(children.begin());
|
|
while(XX->eles < IO_max_cap_nodes && !children.empty())
|
|
{
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[XX->eles]=
|
|
*(children.begin());
|
|
children.erase(children.begin());
|
|
XX->eles++;
|
|
}
|
|
//no more childs fit into the root node.
|
|
//Give them back to the root
|
|
}
|
|
put();
|
|
}
|
|
get(act_level,act_pthis);
|
|
}
|
|
erase();
|
|
}
|
|
else
|
|
if(touched)
|
|
{
|
|
Key k= build(*(dynamic_cast<Data_entry*>(XX)));
|
|
adapt_parent_keys(LevelPthis,k,XX->level+1,MaxLevel);
|
|
// the vertex is eliminated, the parent keys are adapted
|
|
get(act_level,act_pthis);
|
|
put();
|
|
offset = 0;
|
|
CGAL_DOGN_Delete(
|
|
std::cerr << "Key touched. New elements are: ";
|
|
dump(*(dynamic_cast<Data_entry*>(XX)),1,0);
|
|
std::cerr << "\n\n";
|
|
)
|
|
}
|
|
return found;
|
|
}
|
|
|
|
|
|
bool delete_key(Key& a,
|
|
Data & result,
|
|
std::pair< int,long> *LevelPthis,
|
|
std::vector<bool>& Reinsert, int MaxLevel,
|
|
std::vector<v_type>& children)
|
|
{
|
|
bool found=false;
|
|
CGAL_DOGN_Delete(
|
|
std::cerr << "Delete Key\n";
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
dump((* dynamic_cast<Data_entry*>(XX)),0,0);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
dump_this_node((* dynamic_cast<Node_entry*>(XX)),0,0);
|
|
)
|
|
int i, act_level=XX->level;
|
|
long act_pthis=XX->pthis;
|
|
long child_pthis;
|
|
for (i = 0; i< XX->eles; i++)
|
|
{
|
|
if(!(*(dynamic_cast<Node_entry*>(XX))).ele[i].deleted)
|
|
{
|
|
// true if key includes a
|
|
if (traits.include((*(dynamic_cast<Node_entry*>(XX))).ele[i].key,a))
|
|
{
|
|
std::pair< int,long> p(i,act_pthis);
|
|
LevelPthis[act_level]=p;
|
|
child_pthis=(*(dynamic_cast<Node_entry*>(XX))).ele[i].pnext;
|
|
get(act_level-1,child_pthis);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
found = delete_key(a, result, LevelPthis ,Reinsert,
|
|
MaxLevel, children);
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
found = XXdelete_key_data(a, result, LevelPthis, Reinsert,
|
|
MaxLevel, children);
|
|
if (!get(act_level,act_pthis))
|
|
{
|
|
CGAL_DOGN_Control(
|
|
std::cerr << "should not happen - node was deleted, everything ok\n";
|
|
)
|
|
return false;
|
|
}
|
|
if(found)
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return found;
|
|
}
|
|
|
|
|
|
// the nodes YY and ZZ are tried to put together.
|
|
void add_or_split(std::vector<v_type>& children, Node_entry& YY,
|
|
Node_entry& ZZ, std::vector<bool>& Reinsert)
|
|
{
|
|
int i;
|
|
long act_pthis=YY.pthis;
|
|
int act_level=YY.level;
|
|
if(YY.eles + ZZ.eles < IO_max_cap_nodes)
|
|
{
|
|
for(i=0;i<IO_max_cap_nodes ;i++)
|
|
{
|
|
if(!ZZ.ele[i].deleted)
|
|
insert_star(ZZ.ele[i], YY);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
v_type vleft, vright;
|
|
Node_entry *XXLeft=new Node_entry(YY.level);
|
|
Node_entry *XXRight=new Node_entry(YY.level);
|
|
v_type keys[2*IO_max_cap_nodes]; //[YY.eles+ZZ.eles];
|
|
int j,k=0;
|
|
for (j=0; j < IO_max_cap_nodes; ++j)
|
|
{
|
|
if (!YY.ele[j].deleted)
|
|
keys[k++]=YY.ele[j];
|
|
}
|
|
for (j=0; j < IO_max_cap_nodes; ++j)
|
|
{
|
|
if (!ZZ.ele[j].deleted)
|
|
keys[k++]=ZZ.ele[j];
|
|
}
|
|
ps(keys, &keys[YY.eles+ZZ.eles], &XXLeft->ele[0], &XXRight->ele[0],
|
|
IO_min_cap_nodes, IO_max_cap_nodes);
|
|
vleft.key = build(*XXLeft);
|
|
XXLeft->pthis=act_pthis;
|
|
put_node(*XXLeft, act_pthis);
|
|
vleft.pnext = act_pthis;
|
|
vleft.deleted = false;
|
|
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "SPLIT the left and right keys are: "
|
|
<< std::endl;
|
|
traits.dump(vleft.key);
|
|
traits.dump(vright.key);
|
|
std::cerr << std::endl;
|
|
)
|
|
put_node(*XXRight,-1);
|
|
vright.pnext = XXRight->pthis;
|
|
vright.deleted = false;
|
|
|
|
children.erase(children.begin(), children.end());
|
|
children.push_back(vleft);
|
|
children.push_back(vright);
|
|
|
|
CGAL_DOGN_Insert(
|
|
dump_this_node(*XXRight,0,0);
|
|
dump_this_node(*XXLeft,0,0);
|
|
get(XXRight->level,XXRight->pthis);
|
|
dump_this_node((*dynamic_cast<Node_entry*>(XX)),0,0);
|
|
get(XXLeft->level,XXLeft->pthis);
|
|
dump_this_node((*dynamic_cast<Node_entry*>(XX)),0,0);
|
|
)
|
|
get(act_level,act_pthis);
|
|
}
|
|
}
|
|
|
|
// the data nodes YY and ZZ are tried to put together
|
|
void add_or_split(std::vector<v_type>& children, Data_entry& YY,
|
|
Data_entry& ZZ,
|
|
std::vector<bool>& Reinsert)
|
|
{
|
|
if (YY.available_space(YY.leaf_offset)<ZZ.leaf_offset)
|
|
{
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "available_space :" <<
|
|
YY.available_space(YY.leaf_offset) << std::endl;
|
|
std::cerr << "size of data: ZZ style" << ZZ.leaf_offset
|
|
<< std::endl;
|
|
std::cerr << "pagesize:" << IO_page_size << std::endl;
|
|
)
|
|
std::vector<Data> V;
|
|
std::vector<d_type> left, right;
|
|
d_type *old;
|
|
old= new d_type[YY.eles+YY.eles +2];
|
|
Data_entry *nleft=new Data_entry();
|
|
Data_entry *nright=new Data_entry();
|
|
Data element;
|
|
v_type vleft, vright;
|
|
int i,j, offset =0;
|
|
for(i=0;i<YY.eles; i++)
|
|
{
|
|
*ff=YY.raw_data + offset;
|
|
traits.read(ff,element);
|
|
V.push_back(element);
|
|
old[i].key = traits.build(element);
|
|
old[i].ele = element;
|
|
offset += traits.written_size(element);
|
|
}
|
|
offset=0;
|
|
for(j=0;j<ZZ.eles; i++)
|
|
{
|
|
*ff=ZZ.raw_data + offset;
|
|
traits.read(ff,element);
|
|
V.push_back(element);
|
|
old[j+i].key = traits.build(element);
|
|
old[j+i].ele = element;
|
|
offset += traits.written_size(element);
|
|
}
|
|
ps_leaf(&old[0], &old[j+i], std::back_inserter(left),
|
|
std::back_inserter(right), IO_min_cap_leaves,
|
|
IO_page_size);
|
|
delete[] old;
|
|
d_type *dt;
|
|
Key kleft =left.begin()->key;
|
|
Key kright =right.begin()->key;
|
|
for(dt=left.begin();dt!=left.end();dt++)
|
|
{
|
|
direct_insert(dt->ele,*nleft);
|
|
kleft = traits.unify(kleft, dt->key);
|
|
}
|
|
for(dt=right.begin();dt!=right.end();dt++)
|
|
{
|
|
direct_insert(dt->ele, *nright);
|
|
kright = traits.unify(kright, dt->key);
|
|
}
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "SPLIT the left and right keys are: "
|
|
<< std::endl;
|
|
traits.dump(kleft);
|
|
traits.dump(kright);
|
|
std::cerr << std::endl;
|
|
)
|
|
|
|
vleft.key = kleft;
|
|
put_data(*nleft, YY.pthis);
|
|
vleft.pnext = YY.pthis;
|
|
vleft.deleted = false;
|
|
|
|
vright.key = kright;
|
|
put_data(*nright,-1);
|
|
vright.pnext = nright->pthis;
|
|
vright.deleted = false;
|
|
|
|
children.erase(children.begin(), children.end());
|
|
children.push_back(vleft);
|
|
children.push_back(vright);
|
|
delete nleft;
|
|
delete nright;
|
|
get(0, YY.pthis);
|
|
}
|
|
else
|
|
{
|
|
Data element;
|
|
int i, offset =0;
|
|
for(i=0;i<ZZ.eles; i++)
|
|
{
|
|
*ff=ZZ.raw_data + offset;
|
|
traits.read(ff,element);
|
|
*ff=YY.raw_data + YY.leaf_offset;
|
|
traits.write(ff,element);
|
|
YY.leaf_offset += traits.written_size(element);
|
|
YY.eles++;
|
|
offset += traits.written_size(element);
|
|
}
|
|
put();
|
|
}
|
|
}
|
|
|
|
|
|
// tree information is given out
|
|
void dump(Data_entry & YY, int levelX, int indent)
|
|
{
|
|
std::cerr << "********************************************\n";
|
|
std::cerr << " dump of data\n";
|
|
Data element;
|
|
Key key;
|
|
int i, offset=0;
|
|
for(i=0;i<YY.eles; i++)
|
|
{
|
|
*ff=YY.raw_data + offset;
|
|
traits.read(ff,element);
|
|
offset += traits.written_size(element);
|
|
key = traits.build(element);
|
|
for( int j=0;j<indent; j++)
|
|
std::cerr << " ";
|
|
traits.dump(key);
|
|
}
|
|
std::cerr << std::endl;
|
|
std::cerr << "********************************************\n";
|
|
}
|
|
|
|
void dump_this_node(Node_entry& YY, int levelX, int indent){
|
|
int j;
|
|
iterator i;
|
|
std::cerr << "============================================\n";
|
|
std::cerr << " dump of node\n";
|
|
for (i = &YY.ele[0];i !=&YY.ele[YY.eles]; i++) {
|
|
for(j=0;j<indent; j++)
|
|
std::cerr << " ";
|
|
std::cerr << "pnext " << (*i).pnext;
|
|
std::cerr << ((*i).deleted ? "*" : "") << "\t";
|
|
for(j=0;j<indent; j++)
|
|
std::cerr << " ";
|
|
traits.dump((*i).key,0);
|
|
std::cerr << std::endl;
|
|
}
|
|
std::cerr << std::endl;
|
|
std::cerr << "============================================\n";
|
|
}
|
|
|
|
|
|
void dump_node( int levelX, int indent){
|
|
int j;
|
|
int act_level=XX->level; long act_pthis=XX->pthis;
|
|
dump_this_node(*(dynamic_cast<Node_entry*>(XX)), levelX, indent);
|
|
std::cerr << std::endl;
|
|
std::cerr << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n";
|
|
std::cerr << "Dump of children: \n";
|
|
int l=0;
|
|
while (l<XX->eles)
|
|
{
|
|
std::cerr << "parent has number: " << act_pthis << std::endl;
|
|
for(j=0;j<indent; j++)
|
|
std::cerr << " ";
|
|
traits.dump((*(dynamic_cast<Node_entry*>(XX))).ele[l].key);
|
|
std::cerr << "going down: " << act_pthis << std::endl;
|
|
std::cerr << "level: " << act_level-1 << " pnext: "
|
|
<< (*(dynamic_cast<Node_entry*>(XX))).ele[l].pnext << std::endl;
|
|
if(get(act_level-1,(*(dynamic_cast<Node_entry*>(XX))).ele[l].pnext))
|
|
dump(levelX,indent+1);
|
|
get(act_level,act_pthis);
|
|
std::cerr << "going up: " << act_pthis << std::endl;
|
|
for(j=0;j<indent; j++)
|
|
std::cerr << " ";
|
|
traits.dump((*(dynamic_cast<Node_entry*>(XX))).ele[l].key);
|
|
std::cerr << std::endl;
|
|
l++;
|
|
}
|
|
std::cerr << std::endl;
|
|
std::cerr << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n";
|
|
}
|
|
|
|
|
|
void dump( int levelX, int indent) {
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
dump(*(dynamic_cast<Data_entry*>(XX)), levelX, indent);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
dump_node(levelX, indent);
|
|
}
|
|
|
|
|
|
void dump_vertex(Data_entry& YY, bool ok, int levelX, int speach)
|
|
{
|
|
}
|
|
|
|
void dump_vertex_simple(Node_entry & YY)
|
|
{
|
|
int i;
|
|
std::cerr << std::endl;
|
|
std::cerr << "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
|
|
std::cerr << "Output of a node\n";
|
|
for(i=0;i<YY.eles;i++)
|
|
traits.dump(YY.ele[i].key);
|
|
std::cerr << std::endl;
|
|
std::cerr << "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
|
|
}
|
|
|
|
|
|
void dump_vertex_node(bool ok, int levelX, int speach)
|
|
{
|
|
Key elem;
|
|
int act_level=XX->level;
|
|
long act_pthis=XX->pthis;
|
|
int i, pnext;
|
|
std::cerr << std::endl;
|
|
std::cerr << "+++++++++++++++++++++++++++++++++++++++++++++\n";
|
|
std::cerr << "Output of a node\n";
|
|
for(i=0;i<XX->eles;i++)
|
|
{
|
|
pnext=(*(dynamic_cast<Node_entry*>(XX))).ele[i].pnext;
|
|
std::cerr << "Adress is " << pnext << std::endl;
|
|
if (pnext >= 0)
|
|
{
|
|
get(act_level-1,pnext);
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
elem = build(*(dynamic_cast<Data_entry*>(XX)));
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
elem = build( *(dynamic_cast<Node_entry*>(XX)));
|
|
get(act_level,act_pthis);
|
|
if (!(traits.equal_key(elem,
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[i].key)))
|
|
{
|
|
if (speach > 0)
|
|
{
|
|
std::cerr << "!!! Error !!! Invalid parent key ";
|
|
traits.dump((*(dynamic_cast<Node_entry*>(XX))).ele[i].key);
|
|
std::cerr << " instead of ";
|
|
traits.dump(elem);
|
|
}
|
|
std::cerr << "not ok since invalid parent key" << std::endl;
|
|
ok = false;
|
|
(*(dynamic_cast<Node_entry*>(XX))).ele[i].key = elem;
|
|
put();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (speach > 0)
|
|
{
|
|
std::cerr << "!!! Error !!! Invalid tree pointer ";
|
|
std::cerr << "(past end of tree structure) in node ";
|
|
}
|
|
std::cerr << "not ok since invalid tree pointer" << std::endl;
|
|
ok = false;
|
|
}
|
|
}
|
|
int c,j;
|
|
for (c = 0, j = 0; j<IO_max_cap_nodes; ++j)
|
|
{
|
|
if (!(*(dynamic_cast<Node_entry*>(XX))).ele[j].deleted)
|
|
c++;
|
|
}
|
|
if (c != XX->eles)
|
|
{
|
|
if (speach > 0)
|
|
{
|
|
std::cerr << "!!! Error !!! Wrong number of children in node ";
|
|
std::cerr << ", " << c << " instead of " << XX->eles << std::endl;
|
|
}
|
|
std::cerr << "not ok since wrong number of children " << std::endl;
|
|
ok = false;
|
|
}
|
|
if (!ok) put();
|
|
for (j=0;j<IO_max_cap_nodes; j++)
|
|
{
|
|
if(!(*(dynamic_cast<Node_entry*>(XX))).ele[j].deleted)
|
|
get(act_level-1, (*(dynamic_cast<Node_entry*>(XX))).ele[j].pnext);
|
|
isvalid(levelX, speach);
|
|
}
|
|
get(act_level,act_pthis);
|
|
if (speach > 1)
|
|
std::cerr << "\tnode number " << act_pthis << (ok ? " ok" : " not ok")
|
|
<< std::endl;
|
|
std::cerr << std::endl;
|
|
std::cerr << "+++++++++++++++++++++++++++++++++++++++++++++\n";
|
|
}
|
|
|
|
|
|
// the tree structure is tested.
|
|
bool isvalid( int levelX = 0, int speach = 0)
|
|
{
|
|
bool ok = true;
|
|
Key elem;
|
|
|
|
if (speach > 1)
|
|
std::cerr << "Testing\tnode number " << XX->pthis << std::endl;
|
|
if(!XX->level>0)
|
|
{
|
|
if(XX->overfilled(XX->eles)){
|
|
if (speach > 0) {
|
|
std::cerr << "!!! Error !!! Too many children in node ";
|
|
std::cerr << ", " << XX->eles << " instead of "
|
|
<< IO_max_cap_nodes << std::endl;
|
|
}
|
|
std::cerr << "not ok since overfilled" << std::endl;
|
|
ok = false;
|
|
}
|
|
else
|
|
if (XX->eles > IO_max_cap_nodes)
|
|
{
|
|
if (speach > 0)
|
|
{
|
|
std::cerr << "!!! Error !!! Too many children in node ";
|
|
std::cerr << ", " << XX->eles << " instead of "
|
|
<< IO_max_cap_nodes << std::endl;
|
|
}
|
|
std::cerr << "not ok since eles > IO_max_cap" << std::endl;
|
|
ok = false;
|
|
}
|
|
if(XX->underfilled())
|
|
{
|
|
if (speach > 0)
|
|
{
|
|
std::cerr << "!!! Warning !!! Too few children in node ";
|
|
std::cerr << ", " << XX->eles << " instead of "
|
|
<< IO_min_cap_nodes << std::endl;
|
|
std::cerr << "Tree needs reorganization" << std::endl;
|
|
}
|
|
std::cerr << "not ok in underfilled";
|
|
ok = false;
|
|
}
|
|
}
|
|
if(dynamic_cast<Data_entry*>(XX))
|
|
dump_vertex(*(dynamic_cast<Data_entry*>(XX)), ok, levelX, speach);
|
|
if(dynamic_cast<Node_entry*>(XX))
|
|
dump_vertex_node( ok, levelX, speach);
|
|
return ok;
|
|
}
|
|
|
|
};
|
|
|
|
//this structure contains the necessary information of the tree
|
|
// that is its heights, if it is empty and the address of the root
|
|
class header_type {
|
|
public:
|
|
int tree_height;
|
|
bool empty;
|
|
long rootpthis;
|
|
// size_t size() { return sizeof(int) + sizeof(bool) + sizeof(long)+3;}
|
|
size_t size() { return sizeof(int) + sizeof(bool) + sizeof(long);}
|
|
|
|
void read(char **s){
|
|
int sint=(int)sizeof(int);
|
|
int slong=(int)sizeof(long);
|
|
int sbool=(int)sizeof(bool);
|
|
char *from_int=new char[sint];
|
|
char *from_bool=new char[sbool];
|
|
char *from_long=new char[slong];
|
|
int i,r=0;
|
|
for (i=0; i<sint; i++)
|
|
from_int[i] = (*s)[i];
|
|
r += sint;
|
|
tree_height=*((int *)from_int);
|
|
|
|
for (i=0; i<slong; i++)
|
|
from_long[i] = (*s)[i+r];
|
|
rootpthis=*((long *)from_long);
|
|
r += slong;
|
|
|
|
for (i=0; i<sbool; i++)
|
|
from_bool[i] = (*s)[i+r];
|
|
empty=*((bool *)from_bool);
|
|
|
|
delete[] from_bool;
|
|
delete[] from_int;
|
|
delete[] from_long;
|
|
}
|
|
void write (char **s) {
|
|
int sint=(int)sizeof(int);
|
|
int slong=(int)sizeof(long);
|
|
int sbool=(int)sizeof(bool);
|
|
|
|
char *from_int=new char[sint];
|
|
char *from_bool=new char[sbool];
|
|
char *from_long=new char[slong];
|
|
int i,r=0;
|
|
memcpy(from_int,(char *)(&tree_height),sint);
|
|
for (i=0; i<sint; i++)
|
|
(*s)[i] = from_int[i];
|
|
r += sint;
|
|
memcpy(from_long,(char *)(&rootpthis),slong);
|
|
for (i=0; i<slong; i++)
|
|
(*s)[i+r] = from_long[i];
|
|
r += slong;
|
|
|
|
memcpy(from_bool,(char *)(&empty),sbool);
|
|
for (i=0; i<sbool; i++)
|
|
(*s)[i+r] = from_bool[i];
|
|
r += sbool;
|
|
|
|
delete[] from_bool;
|
|
delete[] from_int;
|
|
delete[] from_long;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
// Implementation of the R_Tree.
|
|
template <class Traits, class R_tree_index, class R_tree_storage>
|
|
class R_tree {
|
|
public:
|
|
const static bool reinsertions = R_tree_index::reinsertions;
|
|
const static int IO_min_cap_nodes=R_tree_storage::IO_min_cap_nodes;
|
|
const static int IO_max_cap_nodes=R_tree_storage::IO_max_cap_nodes;
|
|
const static int IO_min_cap_leaves=
|
|
R_tree_storage::IO_min_cap_leaves;
|
|
const static int IO_page_size=R_tree_storage::IO_page_size;
|
|
const static bool headerextern=R_tree_storage::headerextern;
|
|
typedef typename Traits::Data Data;
|
|
typedef typename Traits::Key Key;
|
|
typedef typename R_tree_storage::IO_tree_traits_nodes IO_intf_nodes;
|
|
typedef typename R_tree_storage::IO_tree_traits_leaves IO_intf_leaves;
|
|
typedef typename R_tree_storage::IO_tree_traits_nodes IO_tree_traits_nodes;
|
|
typedef typename R_tree_storage::IO_tree_traits_leaves IO_tree_traits_leaves;
|
|
typedef R_tree_node<Traits,R_tree_index,
|
|
IO_tree_traits_nodes, IO_tree_traits_leaves, IO_min_cap_nodes,
|
|
IO_max_cap_nodes, IO_min_cap_leaves,
|
|
IO_page_size> Node;
|
|
typedef typename Node::Tree Tree;
|
|
typedef typename Node::Leaf_data Leaf_data;
|
|
typedef typename Node::v_type v_type;
|
|
typedef typename Node::Node_entry Node_entry;
|
|
typedef typename Node::Data_entry Data_entry;
|
|
typedef typename Node::size_type size_type;
|
|
typedef R_tree<Traits, R_tree_index,R_tree_storage> RT;
|
|
Traits traits;
|
|
|
|
protected:
|
|
|
|
Leaf_data leaf_data;
|
|
Tree tree;
|
|
std::fstream head;
|
|
header_type header;
|
|
int header_number;
|
|
char fhead[80], ftree[80], fdata[80], fleaf_data[80];
|
|
Node *root;
|
|
int speach;
|
|
int rootlevel;
|
|
long rootpthis;
|
|
char **header_string;
|
|
int header_size;
|
|
|
|
public:
|
|
std::vector<bool> Reinsert;
|
|
|
|
R_tree() {root=0;}
|
|
|
|
// initialization of the R_Tree from the files h,t,leaf_data_file.
|
|
// Either these files are empty or they were created in a previous run.
|
|
// Otherwise no guarantee can be given.
|
|
R_tree(char *h, char *t, char *leaf_data_file) {
|
|
//allocate memory for the header
|
|
header_string = new (char *);
|
|
*header_string= new char[header.size()];
|
|
header_size=header.size();
|
|
open(h, t, leaf_data_file);
|
|
if(header.empty){
|
|
root = new Node(0); //set level of root to 0
|
|
root->open(tree, leaf_data);
|
|
header.rootpthis=rootpthis=root->XX->pthis=leaf_data.get_pos();
|
|
CGAL_DOGN_ControlB(
|
|
std::cerr << "Rootpthis " << rootpthis;
|
|
)
|
|
(*(dynamic_cast<Data_entry*>(root->XX))).write((root->data_space));
|
|
leaf_data.insert(root->XX->pthis,(root->data_space));
|
|
rootlevel=0;
|
|
}
|
|
else
|
|
{
|
|
if(header.tree_height==0){
|
|
rootlevel=0;
|
|
root = new Node(0);
|
|
}
|
|
else
|
|
{
|
|
root = new Node(header.tree_height);
|
|
rootlevel = header.tree_height;
|
|
rootpthis=header.rootpthis;
|
|
}
|
|
}
|
|
root->open(tree, leaf_data);
|
|
root->get(rootlevel,rootpthis);
|
|
int i;
|
|
if(reinsertions)
|
|
{
|
|
for(i=0;i<=header.tree_height;i++)
|
|
Reinsert.push_back(true);
|
|
}
|
|
else
|
|
for(i=0;i<=header.tree_height;i++)
|
|
Reinsert.push_back(false);
|
|
}
|
|
virtual ~R_tree()
|
|
{
|
|
if(header.empty)
|
|
{
|
|
root->get(rootlevel,rootpthis);
|
|
root->erase();
|
|
}
|
|
if(headerextern)
|
|
{
|
|
header.write(header_string);
|
|
head.seekp(0);
|
|
head.write(*header_string,header_size);
|
|
head.close();
|
|
}
|
|
tree.close();
|
|
leaf_data.close();
|
|
delete[] *header_string;
|
|
delete header_string;
|
|
if(root!=0)
|
|
delete root;
|
|
CGAL_DOGN_ControlB(
|
|
std::cerr << "R_tree destructor called\n";
|
|
)
|
|
}
|
|
|
|
protected:
|
|
// the files are opend and the tree initialized
|
|
void open(char *h, char *t, char *leaf_data_file) {
|
|
Node_entry n_entry;
|
|
Data_entry d_entry;
|
|
if(headerextern){
|
|
//fake the SGI CC - compiler: it does not want to open empty
|
|
//files for reading
|
|
std::fstream fake_open;
|
|
fake_open.open(h,std::fstream::out|std::fstream::app);
|
|
CGAL_DOGN_Control(
|
|
if(!fake_open.is_open())
|
|
std::cerr << "fake open is not open";
|
|
else
|
|
std::cerr << "header fake open is open";
|
|
)
|
|
fake_open.close();
|
|
head.open(h,(std::fstream::in|std::fstream::out|std::fstream::ate));
|
|
CGAL_DOGN_Control(
|
|
//SGI CC compiler does not like to open empty files for input
|
|
if(!head.is_open())
|
|
{
|
|
std::cerr << "Header file did not open! Data will not be saved.\n";
|
|
}
|
|
)
|
|
}
|
|
tree.open(n_entry.size(),t,
|
|
(std::fstream::binary|std::fstream::in|std::fstream::out));
|
|
leaf_data.open(d_entry.size(),leaf_data_file,
|
|
(std::fstream::binary|std::fstream::in|std::fstream::out));
|
|
strcpy(fhead, h);
|
|
strcpy(ftree, t);
|
|
strcpy(fleaf_data, leaf_data_file);
|
|
|
|
if(headerextern){
|
|
head.seekp(0, std::fstream::end);
|
|
int teller;
|
|
teller = head.tellp();
|
|
if (0>=teller || leaf_data.number_of_elements()==0) { // no entries
|
|
CGAL_DOGN_ControlB(
|
|
std::cerr<<"no entries for header\n";
|
|
)
|
|
header.empty=true;
|
|
header.rootpthis = -1;
|
|
header.tree_height = 0;
|
|
header.write(header_string);
|
|
head.write(*header_string,header_size);
|
|
}
|
|
else{
|
|
CGAL_DOGN_ControlB(
|
|
std::cerr<<"entries for header\n";
|
|
)
|
|
head.seekg(0);
|
|
head.get(*header_string,header_size);
|
|
header.read(header_string);
|
|
}
|
|
}
|
|
else{
|
|
header.empty=true;
|
|
header.tree_height = 0;
|
|
header.rootpthis =-1;
|
|
}
|
|
CGAL_DOGN_ControlB(
|
|
std::cerr << "Header information: \n";
|
|
std::cerr << "empty: " << header.empty << " treeheight "
|
|
<< header.tree_height;
|
|
std::cerr << "Rootpthis: " << header.rootpthis << std::endl;
|
|
)
|
|
empty = header.empty;
|
|
tree_height = header.tree_height;
|
|
}
|
|
|
|
// the offset of rootXX in the file is returned.
|
|
long get_pnext(Node_entry& rootXX)
|
|
{
|
|
return rootXX.ele[0].pnext;
|
|
}
|
|
|
|
public:
|
|
bool empty;
|
|
int tree_height;
|
|
|
|
|
|
// insertion of an element into the tree
|
|
void insert(Data& elem) {
|
|
std::vector<v_type> children, root_children;
|
|
std::pair< int,long> *IndexPthis= new std::pair< int,long>[rootlevel+1];
|
|
typename std::vector<v_type>::iterator i;
|
|
v_type v;
|
|
|
|
v.deleted = false;
|
|
v.key= traits.build(elem);
|
|
root->get(rootlevel,rootpthis);
|
|
root->insert_star(elem, v, children,root_children, Reinsert,
|
|
rootlevel,IndexPthis);
|
|
if(header.empty==true)
|
|
{
|
|
header.empty=false;
|
|
if(headerextern){
|
|
header.write(header_string);
|
|
head.seekp(0);
|
|
head.write(*header_string,header_size);
|
|
}
|
|
}
|
|
|
|
root->get(rootlevel,rootpthis);
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "Output of the root element right after insert"
|
|
<< std::endl;
|
|
if(rootlevel>0)
|
|
{
|
|
if(dynamic_cast<Node_entry*>(root->XX))
|
|
root->dump_vertex_simple(*(dynamic_cast<Node_entry*>(root->XX)));
|
|
}
|
|
std::cerr << "end\n";
|
|
)
|
|
while(!root_children.empty()){
|
|
children.push_back(*root_children.begin());
|
|
root_children.erase(root_children.begin());
|
|
}
|
|
if (!children.empty()) {
|
|
if(reinsertions)
|
|
Reinsert.push_back(true);
|
|
else
|
|
Reinsert.push_back(false);
|
|
header.tree_height++;
|
|
rootlevel++;
|
|
if(dynamic_cast<Node_entry*>(root->XX)){
|
|
root->XX->pthis = tree.get_pos();
|
|
(*(dynamic_cast<Node_entry*>(root->XX))).write((root->node_space));
|
|
tree.insert(root->XX->pthis, (root->node_space));
|
|
(*children.begin()).pnext = root->XX->pthis;
|
|
root->XX->pthis = rootpthis;
|
|
root->clear();
|
|
root->XX->level=rootlevel;
|
|
}
|
|
else
|
|
{
|
|
delete root;
|
|
root = new Node(1);
|
|
root->open(tree, leaf_data);
|
|
header.rootpthis=rootpthis=root->XX->pthis = tree.get_pos();
|
|
(*(dynamic_cast<Node_entry*>(root->XX))).write((root->node_space));
|
|
tree.insert(root->XX->pthis,(root->node_space));
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "root pthis moved to : " << root->XX->pthis
|
|
<< std::endl;
|
|
)
|
|
}
|
|
if(dynamic_cast<Node_entry*>(root->XX))
|
|
{
|
|
for (i = children.begin(); i != children.end(); i++){
|
|
root->insert_star((*i), *(dynamic_cast<Node_entry*>(root->XX) ));
|
|
CGAL_DOGN_Insert(
|
|
std::cerr << "number " << i->pnext << std::endl;
|
|
)
|
|
}
|
|
root->put();
|
|
}
|
|
|
|
if(headerextern){
|
|
header.write(header_string);
|
|
head.seekp(0);
|
|
head.write(*header_string,header_size);
|
|
}
|
|
}
|
|
CGAL_DOGN_Insert(
|
|
dump(0,0);
|
|
std::cerr << "Output of the root element right after insert"
|
|
<< std::endl;
|
|
if(rootlevel>0)
|
|
{
|
|
if(dynamic_cast<Node_entry*>(root->XX))
|
|
root->dump_vertex_simple(*(dynamic_cast<Node_entry*>(root->XX)));
|
|
}
|
|
std::cerr << "end\n";
|
|
)
|
|
delete[] IndexPthis;
|
|
}
|
|
|
|
|
|
// returns true if a is contained in an key.
|
|
bool find_key_include(Key& a) {
|
|
root->get(rootlevel,rootpthis);
|
|
return root->find_key_include(a);
|
|
}
|
|
|
|
// returns true if a intersects another element.
|
|
bool find_key_intersect(Key& a) {
|
|
root->get(rootlevel,rootpthis);
|
|
return root->find_key_intersect(a);
|
|
}
|
|
|
|
|
|
// all elements with key a are deleted and returned
|
|
bool delete_key(Key& a, Data& result)
|
|
{
|
|
bool found=false;
|
|
std::pair< int,long> *IndexPthis= new std::pair< int,long>[rootlevel+1];
|
|
std::vector<v_type> children;
|
|
std::vector<v_type>::iterator i;
|
|
root->get(rootlevel,rootpthis);
|
|
if(dynamic_cast<Data_entry*>(root->XX))
|
|
found = root->XXdelete_key_data(a,result,IndexPthis,Reinsert,rootlevel,
|
|
children);
|
|
else
|
|
if(dynamic_cast<Node_entry*>(root->XX))
|
|
found = root->delete_key(a,result,IndexPthis,Reinsert,rootlevel,
|
|
children);
|
|
root->get(rootlevel,rootpthis);
|
|
if (!children.empty()) {
|
|
header.empty=false;
|
|
header.tree_height++;
|
|
rootlevel++;
|
|
// copy root at another place, the place is given to the first child.
|
|
if(dynamic_cast<Node_entry*>(root->XX)){
|
|
root->XX->pthis=tree.get_pos();
|
|
(*(dynamic_cast<Node_entry*>(root->XX))).write((root->node_space));
|
|
tree.insert(root->XX->pthis, (root->node_space));
|
|
(*children.begin()).pnext = root->XX->pthis;
|
|
root->XX->pthis = rootpthis;
|
|
root->clear();
|
|
root->XX->level=rootlevel;
|
|
}
|
|
else
|
|
{
|
|
delete root;
|
|
root = new Node(1); //give root level 1 now
|
|
root->open(tree, leaf_data);
|
|
root->XX->pthis=tree.get_pos();
|
|
(*(dynamic_cast<Node_entry*>(root->XX))).write((root->node_space));
|
|
tree.insert(root->XX->pthis, (root->node_space));
|
|
CGAL_DOGN_Delete(
|
|
std::cerr << "number: " << root->XX->pthis << std::endl;
|
|
)
|
|
}
|
|
if(dynamic_cast<Node_entry*>(root->XX))
|
|
{
|
|
for (i = children.begin(); i != children.end(); i++){
|
|
root->insert_star((*i), *(dynamic_cast<Node_entry*>(root->XX) ));
|
|
CGAL_DOGN_Delete(
|
|
std::cerr << "number " << i->pnext << std::endl;
|
|
)
|
|
}
|
|
root->put();
|
|
}
|
|
CGAL_DOGN_Delete(
|
|
dump(0,0);
|
|
)
|
|
if(headerextern){
|
|
header.write(header_string);
|
|
head.seekp(0);
|
|
head.write(*header_string,header_size);
|
|
}
|
|
}
|
|
else{
|
|
if(root->XX->eles<1 && dynamic_cast<Data_entry*>(root->XX))
|
|
{
|
|
root->erase();
|
|
header.empty=true;
|
|
delete root;
|
|
root = new Node(0);
|
|
rootlevel=0;
|
|
root->open(tree, leaf_data);
|
|
root->XX->pthis=-1;
|
|
root->put(-1);
|
|
header.rootpthis=rootpthis=root->XX->pthis;
|
|
Reinsert.erase(Reinsert.end());
|
|
if(reinsertions)
|
|
Reinsert.push_back(true);
|
|
else
|
|
Reinsert.push_back(false);
|
|
if(headerextern){
|
|
header.write(header_string);
|
|
head.seekp(0);
|
|
head.write(*header_string,header_size);
|
|
}
|
|
}
|
|
while(root->XX->eles<=1 && dynamic_cast<Node_entry*>(root->XX) )
|
|
{
|
|
header.tree_height--;
|
|
rootlevel--;
|
|
Reinsert.erase(Reinsert.end());
|
|
Node *n= new Node(root->XX->level-1);
|
|
n->open(tree, leaf_data);
|
|
long pnext = get_pnext(*(dynamic_cast<Node_entry*>(root->XX)));
|
|
n->get(root->XX->level-1, pnext);
|
|
n->erase();
|
|
n->XX->pthis=-1;
|
|
root->erase();
|
|
delete root;
|
|
n->put(-1);
|
|
header.rootpthis=rootpthis=n->XX->pthis;
|
|
root = n;
|
|
if(headerextern){
|
|
header.write(header_string);
|
|
head.seekp(0);
|
|
head.write(*header_string,header_size);
|
|
}
|
|
}
|
|
}
|
|
CGAL_DOGN_Delete(
|
|
std::cerr << " $$$$$$$$AFTER DELETE KEY :";
|
|
traits.dump(a);
|
|
dump(0,0);
|
|
)
|
|
delete [] IndexPthis;
|
|
return found;
|
|
}
|
|
|
|
|
|
|
|
//the level of the root is returned
|
|
int get_rootlevel()
|
|
{
|
|
return rootlevel;
|
|
}
|
|
|
|
bool get_reinsertion_flag(int the_level)
|
|
{
|
|
if (the_level <= rootlevel)
|
|
return Reinsert[the_level];
|
|
return false;
|
|
}
|
|
|
|
//if value=true => the next time a node in level the_level
|
|
//is split, the vertices are reinserted on the same level
|
|
//if value=false => reinsertion at level the_level is prohibited
|
|
bool set_reinsertion_level( int the_level,bool value)
|
|
{
|
|
if(the_level<=rootlevel && reinsertions)
|
|
{
|
|
Reinsert[the_level]=value;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
// information about the tree is given out
|
|
void dump( int levelX=0, int indent=0) {
|
|
root->get(rootlevel,rootpthis);
|
|
|
|
std::cerr << "Dump of R-tree" << std::endl;
|
|
std::cerr << "_________________________" << std::endl;
|
|
std::cerr << "Tree Height " << header.tree_height << std::endl;
|
|
std::cerr << "Number of nodes in tree\t\t" << tree.number_of_elements()
|
|
<< std::endl;
|
|
std::cerr << "Number of leaves in tree\t\t"
|
|
<< leaf_data.number_of_elements() << std::endl;
|
|
std::cerr << "Associated files are" << std::endl;
|
|
std::cerr << "\tHeader\t\t\t" << fhead << std::endl;
|
|
std::cerr << "\tTree\t\t\t" << ftree << std::endl;
|
|
std::cerr << "\tData\t\t\t" << fleaf_data << std::endl;
|
|
if(!header.empty)
|
|
root->dump(levelX,0);
|
|
}
|
|
|
|
// return true if the tree structure is valid
|
|
bool isvalid( int levelX = 0) {
|
|
root->get(rootlevel,rootpthis);
|
|
return root->isvalid(levelX, speach);
|
|
}
|
|
|
|
// class iterator is used to iterate through the data elements
|
|
class iterator;
|
|
friend class iterator;
|
|
public:
|
|
|
|
iterator begin()
|
|
{
|
|
root->get(rootlevel,rootpthis);
|
|
Key k=root->bounding_box();
|
|
return iterator( k, this, 1,0);
|
|
}
|
|
iterator end()
|
|
{
|
|
root->get(rootlevel,rootpthis);
|
|
Key k=root->bounding_box();
|
|
return iterator( k, this, 0,0);
|
|
}
|
|
|
|
iterator begin(Key start)
|
|
{
|
|
root->get(rootlevel,rootpthis);
|
|
return iterator(start, this, 1,0);
|
|
}
|
|
iterator end(Key stop)
|
|
{
|
|
root->get(rootlevel,rootpthis);
|
|
return iterator(stop, this, 0,0);
|
|
}
|
|
iterator begin_intersect(Key start)
|
|
{
|
|
root->get(rootlevel,rootpthis);
|
|
return iterator(start, this, 1,0);
|
|
}
|
|
iterator end_intersect(Key stop)
|
|
{
|
|
root->get(rootlevel,rootpthis);
|
|
return iterator(stop, this, 0,0);
|
|
}
|
|
|
|
|
|
iterator begin_enclose(Key start)
|
|
{
|
|
root->get(rootlevel,rootpthis);
|
|
return iterator(start, this, 1,1);
|
|
}
|
|
iterator end_enclose(Key stop)
|
|
{
|
|
root->get(rootlevel,rootpthis);
|
|
return iterator(stop, this, 0,1);
|
|
}
|
|
|
|
iterator begin_compare(Key start)
|
|
{
|
|
root->get(rootlevel,rootpthis);
|
|
return iterator(start, this, 1,2);
|
|
}
|
|
|
|
iterator end_compare(Key stop)
|
|
{
|
|
root->get(rootlevel,rootpthis);
|
|
return iterator(stop, this, 0,2);
|
|
}
|
|
|
|
|
|
class iterator{
|
|
protected:
|
|
std::list<Node_info *> node_stack;
|
|
std::list<Node_info *> end_node_stack;
|
|
|
|
// this type is 0 for intersection, 1 for enclosing, 2 for compare
|
|
int iterator_compare_type;
|
|
int next_element, end_next_element;
|
|
int offset, end_offset;
|
|
Data iterator_element;
|
|
Key win;
|
|
Data_entry actual_data, end_actual_data;
|
|
RT *rtree;
|
|
bool valid;
|
|
bool past_the_end;
|
|
|
|
public:
|
|
|
|
iterator():valid(false){ next_element=0;}
|
|
~iterator(){
|
|
Node_info *ni;
|
|
CGAL_DOGN_Search(
|
|
print_node_infos(node_stack);
|
|
print_node_infos(end_node_stack);
|
|
)
|
|
while(!node_stack.empty()){
|
|
ni=(*node_stack.begin());
|
|
node_stack.erase(node_stack.begin());
|
|
delete ni;
|
|
}
|
|
while(!end_node_stack.empty()){
|
|
ni=(*end_node_stack.begin());
|
|
end_node_stack.erase(end_node_stack.begin());
|
|
delete ni;
|
|
}
|
|
}
|
|
|
|
|
|
iterator(Key v_win, RT *r_tree, bool is_start, int intersection_type)
|
|
: win(v_win)
|
|
{
|
|
//set the type of the compare function of the iterator.
|
|
iterator_compare_type=intersection_type;
|
|
Node_info *ni;
|
|
r_tree->root->get(r_tree->rootlevel,r_tree->rootpthis);
|
|
if(is_start)
|
|
{
|
|
past_the_end = false; // mark iterator as non past the end iterator
|
|
while(!node_stack.empty()){
|
|
ni=(*node_stack.begin());
|
|
node_stack.erase(node_stack.begin());
|
|
delete ni;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
past_the_end = true; // mark iterator as past the end iterator
|
|
while(!end_node_stack.empty()){
|
|
ni=(*end_node_stack.begin());
|
|
end_node_stack.erase(end_node_stack.begin());
|
|
delete ni;
|
|
}
|
|
}
|
|
rtree=r_tree;
|
|
if(intersection_type==0)
|
|
{
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "INTERSECTION ITERATOR\n";
|
|
)
|
|
if(is_start)
|
|
{
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "iterator 2\n";
|
|
)
|
|
if (r_tree->traits.intersect(v_win,r_tree->root->bounding_box()))
|
|
{
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "iterator 3\n";
|
|
)
|
|
if (r_tree->root->init_iterator(node_stack,actual_data,
|
|
next_element,
|
|
win,iterator_element,offset))
|
|
valid = true;
|
|
else
|
|
valid = false;
|
|
r_tree->root->get(r_tree->rootlevel,r_tree->rootpthis);
|
|
CGAL_DOGN_Search(
|
|
std::cerr <<
|
|
std::cerr<< "-------------Test actual data:\n";
|
|
rtree->root->test_actual_data(actual_data);
|
|
std::cerr << "------------end\n";
|
|
)
|
|
r_tree->root->get(r_tree->rootlevel,r_tree->rootpthis);
|
|
}
|
|
else
|
|
valid = false;
|
|
}
|
|
else
|
|
{
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "iterator 5\n";
|
|
)
|
|
if (r_tree->traits.intersect(v_win,r_tree->root->bounding_box()))
|
|
{
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "iterator 6\n";
|
|
)
|
|
if(r_tree->root->reverse_init_iterator(end_node_stack,
|
|
end_actual_data,
|
|
end_next_element,win,
|
|
iterator_element,
|
|
end_offset))
|
|
valid = true;
|
|
else
|
|
valid = false;
|
|
r_tree->root->get(r_tree->rootlevel,r_tree->rootpthis);
|
|
}
|
|
else
|
|
valid = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(intersection_type == 1)
|
|
{
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "ENCLOSING ITERATOR\n";
|
|
)
|
|
if(is_start)
|
|
{
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "iterator 2\n";
|
|
)
|
|
if (r_tree->traits.include(r_tree->root->bounding_box(),v_win))
|
|
{
|
|
if (r_tree->root->init_encl_iterator(node_stack,
|
|
actual_data,
|
|
next_element,
|
|
win,
|
|
iterator_element,
|
|
offset))
|
|
valid = true;
|
|
else
|
|
valid = false;
|
|
CGAL_DOGN_Search(
|
|
std::cerr <<
|
|
std::cerr<< "-------------Test actual data:\n";
|
|
rtree->root->test_actual_data(actual_data);
|
|
std::cerr << "------------end\n";
|
|
)
|
|
}
|
|
else
|
|
valid = false;
|
|
r_tree->root->get(r_tree->rootlevel,r_tree->rootpthis);
|
|
}
|
|
else
|
|
{
|
|
if (r_tree->traits.include(r_tree->root->bounding_box(),v_win))
|
|
{
|
|
if(r_tree->root->reverse_init_encl_iterator(end_node_stack,
|
|
end_actual_data,
|
|
end_next_element,
|
|
win,
|
|
iterator_element,
|
|
end_offset))
|
|
valid = true;
|
|
else
|
|
valid = false;
|
|
r_tree->root->get(r_tree->rootlevel,r_tree->rootpthis);
|
|
}
|
|
else
|
|
valid = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(intersection_type == 2)
|
|
{
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "COMPARE ITERATOR\n";
|
|
)
|
|
if(is_start)
|
|
{
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "iterator 2\n";
|
|
)
|
|
if (r_tree->traits.compare(r_tree->root->bounding_box(),
|
|
v_win))
|
|
{
|
|
if (r_tree->root->init_compare_iterator(node_stack,
|
|
actual_data,
|
|
next_element,
|
|
win,
|
|
iterator_element,
|
|
offset))
|
|
valid = true;
|
|
else
|
|
valid = false;
|
|
}
|
|
else
|
|
valid = false;
|
|
r_tree->root->get(r_tree->rootlevel,r_tree->rootpthis);
|
|
}
|
|
else
|
|
{
|
|
if (r_tree->traits.compare(r_tree->root->bounding_box(),
|
|
v_win))
|
|
{
|
|
if(r_tree->root->reverse_init_compare_iterator(
|
|
end_node_stack,
|
|
end_actual_data,
|
|
end_next_element,win,
|
|
iterator_element,
|
|
end_offset))
|
|
valid = true;
|
|
else
|
|
valid = false;
|
|
r_tree->root->get(r_tree->rootlevel,
|
|
r_tree->rootpthis);
|
|
}
|
|
else
|
|
valid = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
CGAL_DOGN_Search(
|
|
print_node_infos(node_stack);
|
|
)
|
|
}
|
|
|
|
bool operator==(const iterator& x) const
|
|
{
|
|
if(valid && x.valid){
|
|
if(past_the_end == x.past_the_end)
|
|
{
|
|
rtree->root->get(rtree->rootlevel,rtree->rootpthis);
|
|
if(rtree->traits.equal_key(rtree->traits.build(
|
|
x.iterator_element),rtree->traits.build(iterator_element)))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
if(!valid && !x.valid){
|
|
if(rtree->traits.equal_key(win,x.win))
|
|
return true;
|
|
return false;
|
|
}
|
|
if(!valid){
|
|
if(!past_the_end && x.past_the_end)
|
|
if(rtree->traits.equal_key(win,x.win))
|
|
return true;
|
|
return false;
|
|
}
|
|
else
|
|
if(past_the_end && !x.past_the_end)
|
|
if(rtree->traits.equal_key(win,x.win))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
bool operator!=(const iterator& x) const
|
|
{
|
|
return !(*this==x);
|
|
}
|
|
|
|
iterator& operator=(const iterator& x)
|
|
{
|
|
rtree->root->get(rtree->rootlevel,rtree->rootpthis);
|
|
if (&x==this)
|
|
return *this;
|
|
iterator_compare_type=x.iterator_compare_type;
|
|
Node_info *ni;
|
|
while(!node_stack.empty()){
|
|
ni=(*node_stack.begin());
|
|
node_stack.erase(node_stack.begin());
|
|
delete ni;
|
|
}
|
|
std::list<Node_info *>::const_iterator node_it= x.node_stack.begin();
|
|
for(;node_it!=x.node_stack.end();node_it++){
|
|
ni=new Node_info;
|
|
ni->level=(*node_it)->level;
|
|
ni->pnext=(*node_it)->pnext;
|
|
node_stack.push_back(ni);
|
|
}
|
|
while(!end_node_stack.empty()){
|
|
ni=(*end_node_stack.begin());
|
|
end_node_stack.erase(end_node_stack.begin());
|
|
delete ni;
|
|
}
|
|
node_it= x.end_node_stack.begin();
|
|
for(;node_it!=x.end_node_stack.end();node_it++){
|
|
ni=new Node_info;
|
|
ni->level=(*node_it)->level;
|
|
ni->pnext=(*node_it)->pnext;
|
|
end_node_stack.push_back(ni);
|
|
}
|
|
next_element=x.next_element;
|
|
offset=x.offset;
|
|
iterator_element=x.iterator_element;
|
|
win=x.win;
|
|
for(int i=0;i<IO_page_size;i++)
|
|
actual_data.raw_data[i]=x.actual_data.raw_data[i];
|
|
actual_data.eles=x.actual_data.eles;
|
|
rtree=x.rtree;
|
|
valid = x.valid;
|
|
past_the_end = x.past_the_end;
|
|
return *this;
|
|
}
|
|
|
|
Data operator*() const
|
|
{
|
|
return iterator_element;
|
|
}
|
|
|
|
bool is_valid()
|
|
{
|
|
return valid;
|
|
}
|
|
|
|
iterator& operator++(){
|
|
if(past_the_end)
|
|
{
|
|
valid=false;
|
|
return *this;
|
|
}
|
|
rtree->root->get(rtree->rootlevel,rtree->rootpthis);
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "++++++operator\n";
|
|
std::cerr<< "-------------Test actual data:\n";
|
|
rtree->root->test_actual_data(actual_data);
|
|
std::cerr << "------------end\n";
|
|
print_node_infos(node_stack);
|
|
)
|
|
rtree->root->get(rtree->rootlevel,rtree->rootpthis);
|
|
if(iterator_compare_type==0) //intersection iterator
|
|
{
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "INTERSECTION ITERATOR\n";
|
|
)
|
|
if(rtree->root->next_element(node_stack, actual_data, next_element,
|
|
win, iterator_element, offset))
|
|
valid=true;
|
|
else
|
|
valid=false;
|
|
}
|
|
else
|
|
{
|
|
if(iterator_compare_type==1) //enclosing iterator
|
|
{
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "ENCLOSE ITERATOR\n";
|
|
)
|
|
if(rtree->root->next_encl_element(node_stack, actual_data,
|
|
next_element,
|
|
win, iterator_element, offset))
|
|
valid=true;
|
|
else
|
|
valid=false;
|
|
}
|
|
else
|
|
{
|
|
if(iterator_compare_type==2) //compare iterator
|
|
{
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "COMPARE ITERATOR\n";
|
|
)
|
|
if(rtree->root->next_compare_element(node_stack, actual_data,
|
|
next_element,
|
|
win, iterator_element,
|
|
offset))
|
|
valid=true;
|
|
else
|
|
valid=false;
|
|
}
|
|
}
|
|
}
|
|
CGAL_DOGN_Search(
|
|
std::cerr << "nach operator++\n";
|
|
std::cerr<< "-------------Test actual data:\n";
|
|
rtree->root->test_actual_data(actual_data);
|
|
std::cerr << "------------end\n";
|
|
)
|
|
return *this;
|
|
}
|
|
|
|
// iterator operator++(int) {
|
|
// iterator tmp = *this;
|
|
// ++*this;
|
|
// return tmp;
|
|
// }
|
|
};
|
|
};
|
|
|
|
|
|
CGAL_END_NAMESPACE
|
|
|
|
#endif
|
|
|