cgma
|
00001 //------------------------------------------------------------------------- 00002 // Filename : WeightedOctree.hpp 00003 // 00004 // Purpose : Class for O(ln n) search for nodes within a specified 00005 // tolerance of a specified position. 00006 // 00007 // 00008 // Creator : Corey McBride 00009 // 00010 // Creation Date : 02/18/10 00011 //------------------------------------------------------------------------- 00012 00013 #ifndef WEIGHTEDOCT_TREE_HPP 00014 #define WEIGHTEDOCT_TREE_HPP 00015 00016 #include "CubitVector.hpp" 00017 #include <vector> 00018 #include <map> 00019 00020 00021 template <class X> class DefaultWeightedNodeQuery 00022 { 00023 public: 00024 static inline CubitVector coordinates(const X& x) 00025 { 00026 return x.coordinates(); 00027 } 00028 static inline int weight(const X& x) 00029 { 00030 return x.weight(); 00031 } 00032 00033 template<class C> 00034 static inline void setLastCell( X& x,C* c) 00035 { 00036 x.setLastCell(c); 00037 } 00038 00039 }; 00040 struct DefaultOctreeCell 00041 { 00042 }; 00043 00044 00045 template < class X, class C = DefaultOctreeCell, class E = DefaultWeightedNodeQuery<X> > 00046 class WeightedOctree 00047 { 00048 public: 00049 class Cell: public C 00050 { 00051 00052 public: 00053 Cell(); 00054 00055 00056 bool removeNode(const X& node); 00057 void addNode( const X& node ); 00058 // asserts if not a leaf node. 00059 00060 bool leaf(); 00061 // Is this box a leaf in the tree? 00062 00063 void appendNodes( std::vector<X>& list ); 00064 const std::vector<X>& nodes() const { return Nodes; } 00065 00066 // If this node is a leaf node, append all contained CubitNodes 00067 00068 00069 int nodeCount() { return Nodes.size(); } 00070 00071 void setWeight(int w); 00072 void addWeight(int w); 00073 int weight(); 00074 00075 void setCenter(double& x,double& y,double& z); 00076 void setCenter(CubitVector& center); 00077 CubitVector& center() {return Center;} 00078 00079 void removeAllNodes(); 00080 00081 00082 00083 enum { 00084 X_MIN = 0, 00085 Y_MIN = 0, 00086 Z_MIN = 0, 00087 X_MAX = 1, 00088 Y_MAX = 2, 00089 Z_MAX = 4 00090 }; 00091 // Constants for selecting one of 8 child boxes. 00092 // Can be either bitwise-or'ed (|) or added (+). 00093 // MAX values take precedence over MIN values 00094 // if both are specified. (MIN is just the 00095 // absense of MAX). 00096 // 00097 Cell* child( int quadrant ) 00098 { 00099 assert( quadrant >= 0 && quadrant < 8); 00100 return this->Children[quadrant]; 00101 } 00102 // quadrant should be a bitwise OR (or sum) of 00103 // the constants above. If both a MIN and MAX 00104 // value is specified for a given principal 00105 // direction, the M : children_(0), 00106 00107 void setChild(int quadrant,Cell* c); 00108 00109 void setParent(Cell*); 00110 Cell* parent() {return this->Parent;} 00111 00112 void appendAllNodes( std::vector<X>& list ); 00113 // If this node is a leaf node, append all contained CubitNodes. 00114 // Otherwise descend oct-tree getting CubitNodes contained in 00115 // all child leaf nodes. 00116 00117 00118 protected: 00119 Cell* Parent; 00120 Cell* Children[8]; 00121 00122 std::vector<X> Nodes; 00123 int TotalWeight; 00124 CubitVector Center; 00125 bool IsLeaf; 00126 00127 }; 00128 00129 00130 00131 public: 00132 00133 WeightedOctree(int max_weight_per_box,double tolerance=1e-6); 00134 //- Constructor 00135 //- tolerance - tolerance for comparison of node positions 00136 //- max_weight_per_box - subdivide box if total weight exceeds this 00137 //- min_box_dimension - don't subdivide boxes in tree if 00138 //- all three dimensions are less than this 00139 00140 ~WeightedOctree(); 00141 // - Destructor 00142 00143 bool initilizeTree(std::vector<X>& nodes,std::vector<Cell*>& newCells); 00144 void clear(); 00145 00146 bool addNode(const X& node, 00147 std::vector<Cell*>& oldCells, 00148 std::vector<Cell*>& newCells, 00149 std::vector<Cell*>& modifiedCells); 00150 bool removeNode(X& node, 00151 std::vector<Cell*>& oldCells, 00152 std::vector<Cell*>& newCells, 00153 std::vector<Cell*>& modifiedCells); 00154 00155 00156 00157 protected: 00158 bool calculateCellCenter(Cell* cell); 00159 00160 void mergeCellChildren(Cell* cell,std::vector<Cell*>& oldLeafs); 00161 00162 bool splitCell(Cell* cell,std::vector<Cell*>& newLeafs); 00163 // Change from leaf cell to non-leaf. Splits nodes amongst 8 new 00164 // cell boxes using the value of centroid of the cell 00165 00166 00167 bool rebalanceBranch(Cell* cell, 00168 std::vector<Cell*>& oldLeafs, 00169 std::vector<Cell*>& newLeafs); 00170 00171 bool recursiveSplitCell(Cell* cell, 00172 std::vector<Cell*>& newLeafs); 00173 00174 00175 00176 int MaxBoxWeight; 00177 // values passed to constructor 00178 00179 Cell* Root; 00180 // root of oct-tree 00181 00182 int TotalWeight; 00183 00184 std::map<X,Cell*> NodeToCellMap; 00185 00186 double Tolerance; 00187 double ToleranceSquared; 00188 00189 00190 00191 00192 }; 00193 00194 #include "WeightedOctree.cpp" 00195 00196 #endif 00197