// 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 #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 #include #include #include #include #include #include #include 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_stack) { std::list::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 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 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 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 node_entry : public abstract_node_entry { 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 class data_entry : public abstract_node_entry { 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 // D: R_Tree_data_type // 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 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 v_type; typedef R_tree_leaf_data d_type; Traits traits; //definition of the inner node type depending on the template parameters typedef node_entry Node_entry; //definition of the leaf node type typedef data_entry 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 *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(XX)) delete dynamic_cast(XX); else if(dynamic_cast(XX)) delete dynamic_cast(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(XX)){ if ((*leaf_data).get(num,data_space)) (*(dynamic_cast(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(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(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(XX)),0,0); std::cerr << "GET a data entry -- end \n"; ) } else{ if(dynamic_cast(XX)){ if((*tree).get(num, node_space)) (*(dynamic_cast(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(XX); XX = new Node_entry(); if((*tree).get(num,node_space)) (*(dynamic_cast(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(XX)) { if (XX->pthis > -1) { (*(dynamic_cast(XX))).write(data_space); (*leaf_data).update(XX->pthis,data_space); } else { //set the number where the data is positioned (*(dynamic_cast(XX))).pthis = (*leaf_data).get_pos(); CGAL_DOGN_Storage( std::cerr << "New pos: " << XX->pthis << std::endl; ) (*(dynamic_cast(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(XX)) { if (XX->pthis > -1) { (*(dynamic_cast(XX))).write(node_space); (*tree).update(XX->pthis, node_space); (*(dynamic_cast(XX))).read(node_space); //test } else { XX->pthis = (*tree).get_pos(); CGAL_DOGN_Storage( std::cerr << "New pos: " << XX->pthis << std::endl; ) (*(dynamic_cast(XX))).write(node_space); (*tree).insert(XX->pthis,node_space); (*(dynamic_cast(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 &children, std::vector &root_children, std::vector& Reinsert, int MaxLevel, std::pair< int,long> *LevelPthis) { CGAL_DOGN_Insert( std::cerr << "Insert_star\n"; if(dynamic_cast(XX)) dump((* dynamic_cast(XX)),0,0); if(dynamic_cast(XX)) dump_this_node((* dynamic_cast(XX)),0,0); ) if (XX->level==0) // leaf insertion { if(dynamic_cast(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::iterator i; long XXpthis=XX->pthis; int XXlevel=XX->level; CGAL_DOGN_Insert( std::cerr << "pthis: " << XX->pthis << std::endl; ) if(dynamic_cast(XX)) { Node_entry YY=*(dynamic_cast(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 p(pos,XXpthis); LevelPthis[XXlevel]=p; (*(dynamic_cast(XX))).ele[pos].key= traits.unify( (*(dynamic_cast(XX))).ele[pos].key, v.key); put(); // decent the tree, call the insertion routine for the chosen subtree get(XX->level-1,(*(dynamic_cast(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(XX))).ele[pos]= (*children.begin()); children.erase(children.begin()); if(dynamic_cast(XX)){ for (i = children.begin(); i != children.end(); ++i) // the children are simply put into the vertex insert_star((*i), *(dynamic_cast(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 &children, std::vector &root_children, int OnLevel, std::vector& Reinsert, int MaxLevel, std::pair< int,long> *LevelPthis) { CGAL_DOGN_Insert( std::cerr << "FORCED REINSERT NODE\n"; dump_this_node((* dynamic_cast(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(XX)) insert_star(v,(* dynamic_cast(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::iterator i; if(dynamic_cast(XX)) { Node_entry YY=*(dynamic_cast(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(XX))).ele[pos].key= traits.unify((*(dynamic_cast(XX))).ele[pos].key, v.key); put(); get(XX->level-1,(*(dynamic_cast(XX))).ele[pos].pnext); if(dynamic_cast(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(XX))).ele[pos]= (*children.begin()); children.erase(children.begin()); if(dynamic_cast(XX)){ for (i = children.begin(); i != children.end(); ++i) // the children are simply put into the vertex insert_star((*i), *(dynamic_cast(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& root_children, int OnLevel, std::vector& Reinsert, int MaxLevel, std::pair< int,long> *LevelPthis) { CGAL_DOGN_Insert( std::cerr << "ROOT FORCED REINSERT NODE\n"; dump_this_node((* dynamic_cast(XX)),0,0); std::cerr << "Rootpthis is:" << LevelPthis[MaxLevel].second << std::endl; ) std::vector 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(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(XX)) { Node_entry YY=*(dynamic_cast(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(XX))).ele[pos].key= traits.unify((*(dynamic_cast(XX))).ele[pos].key, v.key); put(); get(XX->level-1,(*(dynamic_cast(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(XX))).ele[pos]=(*root_children.begin()); root_children.erase(root_children.begin()); while(XX->eles < IO_max_cap_nodes && !root_children.empty()) { (*(dynamic_cast(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 > to_reinsert) { std::vector new_elements; std::vector::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& root_children, int OnLevel, std::vector& Reinsert, int MaxLevel, std::pair< int,long> *LevelPthis) { std::vector to_reinsert; std::vector::iterator reIt; Key knew; CGAL_DOGN_Insert( std::cerr << "REINSERT NODE\n"; dump_this_node((* dynamic_cast(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(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 &to_reinsert) { CGAL_DOGN_Insert( std::cerr << "Reinsert data split\n"; dump((* dynamic_cast(XX)),0,0); ) Data element; int i,offset=0; std::vector 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;ikey; 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& root_children, int OnLevel, std::vector& Reinsert, int MaxLevel, std::pair< int,long> *LevelPthis) { std::vector to_reinsert; std::vector::iterator reIt; CGAL_DOGN_Insert( std::cerr << "REINSERT DATA\n"; dump((* dynamic_cast(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(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 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(XX)) { Node_entry YY=*(dynamic_cast(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(XX))).ele[pos].key= traits.unify((*(dynamic_cast(XX))).ele[pos].key, v.key); put(); get(XX->level-1,(*(dynamic_cast(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(XX)) { (*(dynamic_cast(XX))).ele[pos]= *(root_children.begin()); root_children.erase(root_children.begin()); while(XX->eles < IO_max_cap_nodes && !root_children.empty()) { (*(dynamic_cast(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 &children, std::vector &root_children, std::vector& 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(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& children, std::vector& root_children, Data_entry& YY,std::vector& Reinsert, int MaxLevel, std::pair< int,long> *LevelPthis) { CGAL_DOGN_Insert( std::cerr << "Must Be Reinserted\n"; dump((* dynamic_cast(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 V; std::vector 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;ikey; 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& children, std::vector& root_children, std::vector& 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(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 &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(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(XX)),0,0); get(XXLeft->level,XXLeft->pthis); dump_this_node((*dynamic_cast(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( i0) { *ff=YY.raw_data + offset; traits.read(ff, element); key=traits.build(element); offset += traits.written_size(element); } for(i=1;ilevel; long act_pthis=XX->pthis; int pos=0; long pnext=0; while(get_next_pos(a, pos,pnext,*(dynamic_cast(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(XX)) return find_key_data(a, *(dynamic_cast(XX))); if(dynamic_cast(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;ilevel; long act_pthis=XX->pthis; long k=0; long pnext; int pos=0; while(get_next_pos(a, pos,pnext,*(dynamic_cast(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(XX)) return search_data(a, *(dynamic_cast(XX))); if(dynamic_cast(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(XX)) return find_key_include_data(a, *(dynamic_cast(XX))); if(dynamic_cast(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;ilevel; long act_pthis=XX->pthis; int pos=0, pnext; while(get_next_pos_include(a,pos,pnext,*(dynamic_cast(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;ilevel; long act_pthis=XX->pthis; while(get_next_pos_inter(a, pos,pnext,*(dynamic_cast(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(XX)) return find_key_intersect_data(a, *(dynamic_cast(XX))); if(dynamic_cast(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_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_stack, Key k){ int i; Node_info *n; for (i = 0; ilevel=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_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& node_stack, Data_entry &actual_data, int& next_element, Key k, Data &next_data, int& element_offset) { if(!found_init_iterator_data((*dynamic_cast(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_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& 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(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_stack, Data_entry &actual_data, int& next_element, Key k, Data &next_data, int& element_offset) { Node_info *ni; collect_node_infos((*dynamic_cast(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_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(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_stack, Data_entry &actual_data, int& next_element, Key k, Data &next_data, int& element_offset) { if(dynamic_cast(XX)) return init_iterator_data(node_stack, actual_data,next_element,k,next_data,element_offset); if(dynamic_cast(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_stack, Data_entry& actual_data, int& next_element, Key k, Data& next_data, int& element_offset) { if(dynamic_cast(XX)) return reverse_init_iterator_data(node_stack, actual_data,next_element,k,next_data, element_offset); if(dynamic_cast(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_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_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_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_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& 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(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_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& 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(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_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(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_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(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_stack, Data_entry &actual_data, int& next_element, Key k, Data &next_data, int& element_offset) { if(dynamic_cast(XX)) return init_encl_iterator_data(node_stack, actual_data,next_element,k,next_data, element_offset); if(dynamic_cast(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_stack, Data_entry& actual_data, int& next_element, Key k, Data& next_data, int& element_offset) { if(dynamic_cast(XX)) return reverse_init_encl_iterator_data(node_stack, actual_data,next_element,k,next_data, element_offset); if(dynamic_cast(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_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_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_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_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& 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(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_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& 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(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_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(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_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(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_stack, Data_entry &actual_data, int& next_element, Key k, Data &next_data, int& element_offset) { if(dynamic_cast(XX)) return init_compare_iterator_data(node_stack, actual_data,next_element,k,next_data, element_offset); if(dynamic_cast(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_stack, Data_entry& actual_data, int& next_element, Key k, Data& next_data, int& element_offset) { if(dynamic_cast(XX)) return reverse_init_compare_iterator_data(node_stack, actual_data,next_element,k,next_data, element_offset); if(dynamic_cast(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_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 > search_intersect(Key& a, Data_entry& YY, std::back_insert_iterator >& result) { Data element; Key key; int i, offset=0; for(i=0;i(XX)) return bounding_box(*(dynamic_cast(XX))); if(dynamic_cast(XX)) return bounding_box(*(dynamic_cast(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(XX)) dump((* dynamic_cast(XX)),0,0); if(dynamic_cast(XX)) dump_this_node((* dynamic_cast(XX)),0,0); ) if(level<=MaxLevel) { get(level,LevelPthis[level].second); (*(dynamic_cast(XX))).ele[LevelPthis[level].first].key=k; put(); k = build(*(dynamic_cast(XX))); adapt_parent_keys(LevelPthis,k,level+1,MaxLevel); } } void adapt_parent_keys(std::pair< int,long>* LevelPthis, int level, int MaxLevel,std::vector& root_children, std::vector& Reinsert) { CGAL_DOGN_Insert( std::cerr << "ADAPT PARENT KEYS\n"; if(dynamic_cast(XX)) dump((* dynamic_cast(XX)),0,0); if(dynamic_cast(XX)) dump_this_node((* dynamic_cast(XX)),0,0); ) if(level<=MaxLevel) { get(level,LevelPthis[level].second); (*(dynamic_cast(XX))).ele[LevelPthis[level].first].deleted= true; XX->eles--; reorder_keys(*(dynamic_cast(XX)),LevelPthis[level].first); put(); CGAL_DOGN_Insert( dump_this_node((* dynamic_cast(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;jeles;j++) { CGAL_DOGN_Insert( dump_this_node((* dynamic_cast(XX)), 0,0); ) v_type v=((*dynamic_cast(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(XX))); CGAL_DOGN_Insert( traits.dump(k); dump_this_node((* dynamic_cast(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& Reinsert, int MaxLevel, std::vector& children) { bool found=false; CGAL_DOGN_Delete( std::cerr << "XXdelete_key_data\n"; if(dynamic_cast(XX)) dump((* dynamic_cast(XX)),0,0); if(dynamic_cast(XX)) dump_this_node((* dynamic_cast(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 to_del; i=0; while(i(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(XX))).delete_key(offset, traits.written_size(element)); put(); CGAL_DOGN_Delete( dump((* dynamic_cast(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(XX)),0,0); ) Data element; std::vector act_children; v_type v; int j,offset=0; num_eles=XX->eles; for(j=0;j(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(XX)) { int pos=LevelPthis[MaxLevel].first; //the changed index (*(dynamic_cast(XX))).ele[pos]=* (children.begin()); children.erase(children.begin()); while(XX->eles < IO_max_cap_nodes && !children.empty()) { (*(dynamic_cast(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(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(XX)),1,0); std::cerr << "\n\n"; ) } return found; } bool delete_key(Key& a, Data & result, std::pair< int,long> *LevelPthis, std::vector& Reinsert, int MaxLevel, std::vector& children) { bool found=false; CGAL_DOGN_Delete( std::cerr << "Delete Key\n"; if(dynamic_cast(XX)) dump((* dynamic_cast(XX)),0,0); if(dynamic_cast(XX)) dump_this_node((* dynamic_cast(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(XX))).ele[i].deleted) { // true if key includes a if (traits.include((*(dynamic_cast(XX))).ele[i].key,a)) { std::pair< int,long> p(i,act_pthis); LevelPthis[act_level]=p; child_pthis=(*(dynamic_cast(XX))).ele[i].pnext; get(act_level-1,child_pthis); if(dynamic_cast(XX)) found = delete_key(a, result, LevelPthis ,Reinsert, MaxLevel, children); if(dynamic_cast(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& children, Node_entry& YY, Node_entry& ZZ, std::vector& 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;iele[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(XX)),0,0); get(XXLeft->level,XXLeft->pthis); dump_this_node((*dynamic_cast(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& children, Data_entry& YY, Data_entry& ZZ, std::vector& Reinsert) { if (YY.available_space(YY.leaf_offset) V; std::vector 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;ikey; 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;ilevel; long act_pthis=XX->pthis; dump_this_node(*(dynamic_cast(XX)), levelX, indent); std::cerr << std::endl; std::cerr << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"; std::cerr << "Dump of children: \n"; int l=0; while (leles) { std::cerr << "parent has number: " << act_pthis << std::endl; for(j=0;j(XX))).ele[l].key); std::cerr << "going down: " << act_pthis << std::endl; std::cerr << "level: " << act_level-1 << " pnext: " << (*(dynamic_cast(XX))).ele[l].pnext << std::endl; if(get(act_level-1,(*(dynamic_cast(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(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(XX)) dump(*(dynamic_cast(XX)), levelX, indent); if(dynamic_cast(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;ilevel; 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;ieles;i++) { pnext=(*(dynamic_cast(XX))).ele[i].pnext; std::cerr << "Adress is " << pnext << std::endl; if (pnext >= 0) { get(act_level-1,pnext); if(dynamic_cast(XX)) elem = build(*(dynamic_cast(XX))); if(dynamic_cast(XX)) elem = build( *(dynamic_cast(XX))); get(act_level,act_pthis); if (!(traits.equal_key(elem, (*(dynamic_cast(XX))).ele[i].key))) { if (speach > 0) { std::cerr << "!!! Error !!! Invalid parent key "; traits.dump((*(dynamic_cast(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(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(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(XX))).ele[j].deleted) get(act_level-1, (*(dynamic_cast(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(XX)) dump_vertex(*(dynamic_cast(XX)), ok, levelX, speach); if(dynamic_cast(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 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 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 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 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(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 children, root_children; std::pair< int,long> *IndexPthis= new std::pair< int,long>[rootlevel+1]; typename std::vector::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(root->XX)) root->dump_vertex_simple(*(dynamic_cast(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(root->XX)){ root->XX->pthis = tree.get_pos(); (*(dynamic_cast(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(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(root->XX)) { for (i = children.begin(); i != children.end(); i++){ root->insert_star((*i), *(dynamic_cast(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(root->XX)) root->dump_vertex_simple(*(dynamic_cast(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 children; std::vector::iterator i; root->get(rootlevel,rootpthis); if(dynamic_cast(root->XX)) found = root->XXdelete_key_data(a,result,IndexPthis,Reinsert,rootlevel, children); else if(dynamic_cast(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(root->XX)){ root->XX->pthis=tree.get_pos(); (*(dynamic_cast(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(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(root->XX)) { for (i = children.begin(); i != children.end(); i++){ root->insert_star((*i), *(dynamic_cast(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(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(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(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_stack; std::list 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::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;iroot->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