cgma
RTreeNode.hpp
Go to the documentation of this file.
00001 //---------------------------------------------------------------------------
00002 // Class Name:  RTreeNode
00003 // Description: Node of Rectangle tree.  Contians many of the
00004 //              required functions for building the tree and traversing it.
00005 // The algorithm was taken from the following paper:
00006 //        Guttman, A., "R-Trees: A Dynamic Index Structure for
00007 //              Spatial Searching", Proceedings of the SIGMOD
00008 //              Conference, Boston, June 1984, p. 47-57.
00009 // Creation Date: 3/13/02
00010 // Owner:  David R. White
00011 //---------------------------------------------------------------------------
00012 #ifndef RTREENODE_HPP
00013 #define RTREENODE_HPP
00014 
00015 #include "CubitDefines.h"
00016 #include "GeometryDefines.h"
00017 #include "CubitBox.hpp"
00018 
00019 template <class X> class DLIList;
00020 const int UNSET_RNODE = -1;
00021 const int DATA_RNODE = 0;
00022 const int LEAF_RNODE = 1;
00023 
00024 template <class Y> class RTreeNode 
00025 {
00026 private:
00027     //Data.
00028   IttyBit markedFlag : 1;
00029   IttyBit distIsBox : 1;
00030     //Generic mark flag.
00031   RTreeNode<Y>** myChildrenNodes;
00032   int nextChildIndex;
00033   CubitBox *myBoundingBox;
00034   Y myData;
00035   int maxChildren, minChildren; //max/min number of children.
00036   RTreeNode<Y> *myParent;
00037   int myLevel; //Level of node
00038     //Level 0 equals data level.
00039     //Level 1 equals leaf node level.
00040     //Higher levels are non-leaf node levels.
00041   double myDist; //used for nearest neigbhor searches...
00042   
00043 
00044     //Functions.
00045   RTreeNode<Y>* choose_leaf( RTreeNode<Y> *n, RTreeNode<Y> *e );
00046     //- Select a leaf node in which to place
00047     //- a new index entry e.  Recursive search the subtrees of n
00048     //- until n is a leaf node.
00049 
00050   CubitStatus adjust_tree(RTreeNode<Y> *l, RTreeNode<Y> *ll,
00051                           RTreeNode<Y> *root_node,
00052                           RTreeNode<Y> *&new_root);
00053     //- Ascend from a leaf node L to the root, adjusting covering
00054     //- bounding boxes and propagating nodes splits as necesary.
00055 
00056   CubitStatus quadratic_split_node( RTreeNode<Y> *l,
00057                                     RTreeNode<Y> *e,
00058                                     RTreeNode<Y> *&ll );
00059     //- Since element e won't fit into l, split l into two groups, l and ll.
00060     //- For the RTree, this is where most of the variations
00061     //- on implementations have occured.  The best method proposed by Guttman
00062     //- was a quadratic split, which I'll implement here.  The Rstar tree
00063     //- did some slightly more complicated things which I might try later.
00064   
00065   
00066   double calc_enlargement( RTreeNode<Y> *current, RTreeNode<Y> *add_to );
00067   double calc_enlargement( CubitBox &current,
00068                            CubitBox &add_to );
00069     //- Calculate the enlargement required for increasing
00070     //- the bounding box of current so that it would encapsulate
00071     //- the bounding box of add_to.
00072 
00073   CubitStatus pick_seeds(RTreeNode<Y> **input_list,
00074                          const int input_list_size,
00075                          RTreeNode<Y> *&seed_1,
00076                          RTreeNode<Y> *&seed_2);
00077     //- Picks the two starting children of the input list that
00078     //- are best for creating the two new groups of quadratic_split_node.
00079 
00080   CubitStatus pick_next(DLIList <RTreeNode<Y>*> &remaining_nodes,
00081                         RTreeNode<Y>* group_1,
00082                         RTreeNode<Y>* group_2,
00083                         RTreeNode<Y>*& next,
00084                         CubitBoolean &add_to_group_1);
00085     //- picks one remainng entry for classification in a group.  Also
00086     //- indicates which group that should be by the add_to_group_1 flag.
00087   
00088   CubitStatus find_leaf( Y e,
00089                          CubitBox &e_box,
00090                          RTreeNode<Y> *t,
00091                          RTreeNode<Y> *&l );
00092     //- find the entry e in the tree t.  l
00093     //- is the entry that contains e. (e is a data member of l).
00094     //- The parent of l, is the leaf node containing it.
00095 
00096   CubitStatus condense_tree(RTreeNode<Y> *l,
00097                             RTreeNode<Y> *root,
00098                             RTreeNode<Y> *&new_root );
00099   //-  Given a leaf node l from which an entry has been deleted, eliminate
00100   //-  the node if it has too few entries and relocate its entries.  Propagate
00101   //-  node elimination upaward as necessary.  Adjust all covering rectangles
00102   //-  on the path to the root, making them smaller if possible.
00103     
00104   
00105   double volume(CubitBox &box);
00106   //- Calculate the volume of the box.
00107   double volume(RTreeNode<Y>* curr);
00108   //- Calculate the volume of the RTreeNode.
00109 
00110 
00111 public:
00112   RTreeNode(Y data, double tol, int max_children, int min_children );
00113   RTreeNode(CubitBox &bounding_box, int max_children, int min_children);
00114   
00115   ~RTreeNode();
00116     //- Constructor/Destructor
00117 
00118   CubitStatus insert(RTreeNode<Y> *e, RTreeNode<Y> *&new_root);
00119     //- Inserts the node e into the proper position of this.  Assumeing
00120     //- this is the root.  Sometimes the root will need to be split,
00121     //- so a new root may be returned.  If the new_root is not null,
00122     //- then the new_root must take the place of this...
00123 
00124   void set_leaf_level(int r_type)
00125   {myLevel = r_type;}
00126     //- Set the type of level of the node.
00127   int get_leaf_level()
00128     {return myLevel;}
00129     //- get the level of the node.
00130 
00131   CubitBoolean is_leaf()
00132     {return (myLevel == LEAF_RNODE)? CUBIT_TRUE : CUBIT_FALSE;}
00133     //- Determine if the RTreeNode is a leaf node.
00134 
00135   CubitBoolean is_data()
00136     {return (myLevel == DATA_RNODE)? CUBIT_TRUE : CUBIT_FALSE;}
00137     //- Determine if the RTreeNode is a leaf node.
00138 
00139   Y get_data()
00140     {return myData;}
00141     //- Determine if the RTreeNode is a leaf node.
00142   
00143   void add_child(RTreeNode<Y>* child_node, CubitBoolean recalc_b_box);
00144     //- Add the child to the myChildrenNodes' list. Adds
00145     //- it to the next availabel spot.  Won't add if overflow will
00146     //- occur.
00147   
00148   CubitBoolean can_add();
00149     //- Tests if there is any space in the myChildrenNodes' list.
00150 
00151   int space_left();
00152     //- Returns the number of positions left in the myChildrenNode's list.
00153 
00154   int num_children()
00155     {return nextChildIndex;}
00156     //- Returns the number of children in the myChildrenNode's array.
00157 
00158   RTreeNode<Y>* get_child(int i)
00159     {return ((i < nextChildIndex) ? myChildrenNodes[i] : (RTreeNode<Y>*)NULL) ;}
00160   
00161     
00162   void flush(CubitBox &new_box);
00163     //- Clears out the myChildrenNodes by setting the array values
00164     //- to null.  Resets the counters and sets the range as the new_box.
00165   
00166   void recalc_b_box();
00167     //- recalculates the bounding box for the node. (won't do it if
00168     //- this is a data node...
00169   
00170   RTreeNode<Y> *get_parent()
00171     {return myParent;}
00172   void set_parent(RTreeNode<Y> *parent)
00173     {myParent = parent;}
00174 
00175   CubitBoolean remove_child(RTreeNode<Y> *child);
00176     //- removes the child from the myChildrenNodes array and condenses
00177     //- the array.  decrements the number of children or increments the
00178     //- num positions available.
00179 
00180   CubitBoolean remove(Y e, RTreeNode<Y> *&new_root, CubitBoolean &delete_root);
00181     //- removes the data e from the tree and cleans up the tree.  A new
00182     //- root node could be found from this.  Assume the root node is
00183     //- calling this function...
00184 
00185   CubitBox& bounding_box()
00186     {return *myBoundingBox;}
00187     //- Returns the bounding box of this node.
00188 
00189   double get_dist();
00190   void set_dist(double dis);
00191 
00192   int dist_is_box();
00193   void set_dist_is_box(int val);
00194   
00195       
00196 };
00197 template <class Y> inline int RTreeNode<Y>::dist_is_box()
00198 {
00199   return distIsBox;
00200 }
00201 template <class Y> inline void RTreeNode<Y>::set_dist_is_box(int val)
00202 {
00203   if ( val )
00204     distIsBox = 1;
00205   else
00206     distIsBox = 0;
00207 }
00208 
00209 template <class Y> inline double RTreeNode<Y>::get_dist()
00210 {
00211   return myDist;
00212 }
00213 template <class Y> inline void RTreeNode<Y>::set_dist(double dist)
00214 {
00215   myDist = dist;
00216 }
00217 
00218 //Calculate the volume of the box.
00219 template <class Y> inline double RTreeNode<Y>::volume(CubitBox &box)
00220 {
00221   return box.x_range()*box.y_range()*box.z_range();
00222 }
00223 //Calculate the volume of the RTreeNode.
00224 template <class Y> inline double RTreeNode<Y>::volume(RTreeNode<Y>* curr)
00225 {
00226   CubitBox box = curr->bounding_box();
00227   return box.x_range()*box.y_range()*box.z_range();
00228 }
00229 
00230 #include "RTreeNode.cpp"
00231 
00232 #endif
00233 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines