cgma
|
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 ¤t, 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