00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00028 #ifndef pddgeom_OctTree_hpp
00029 #define pddgeom_OctTree_hpp
00030
00031 #include <limits>
00032 #include <iosfwd>
00033 #include <util/Basics.hpp>
00034 #include <util/SimpleArrayOps.hpp>
00035
00036 namespace phdmesh {
00037
00038 class OctTreeKey ;
00039
00040 }
00041
00042 namespace std {
00043
00044 ostream & operator << ( ostream & , const phdmesh::OctTreeKey & );
00045
00046 }
00047
00048 namespace phdmesh {
00049
00050 class OctTreeKey {
00051 public:
00052 typedef unsigned value_type ;
00053 enum { MaxDepth = 16 };
00054 enum { MaskIndex = 0x0f };
00055 enum { BitsPerIndex = 4 };
00056 enum { BitsPerWord = std::numeric_limits<value_type>::digits };
00057 enum { IndexPerWord = BitsPerWord / BitsPerIndex };
00058 enum { NWord = MaxDepth / IndexPerWord };
00059 enum { OKBits = StaticAssert< 0 == BitsPerWord % BitsPerIndex >::OK };
00060 enum { OKWord = StaticAssert< 0 == MaxDepth % IndexPerWord >::OK };
00061 private:
00062 value_type m_value[ NWord ];
00063 public:
00064
00065 OctTreeKey()
00066 { Copy<NWord>( m_value , 0u ); }
00067
00068 OctTreeKey( const OctTreeKey & k )
00069 { Copy<NWord>( m_value , k.m_value ); }
00070
00071 OctTreeKey & operator = ( const OctTreeKey & k )
00072 { Copy<NWord>( m_value , k.m_value ); return *this ; }
00073
00074 bool operator == ( const OctTreeKey & k ) const
00075 { return Equal<NWord>( m_value , k.m_value ); }
00076
00077 bool operator != ( const OctTreeKey & k ) const
00078 { return Equal<NWord>( m_value , k.m_value ); }
00079
00080 bool operator < ( const OctTreeKey & k ) const
00081 { return Less<NWord>( m_value , k.m_value ); }
00082
00084 unsigned depth() const ;
00085
00089 template<unsigned Depth> unsigned index() const ;
00090
00092 unsigned index( const unsigned Depth ) const ;
00093
00095 template<unsigned D> OctTreeKey & clear_index() ;
00096
00098 OctTreeKey & clear_index( const unsigned Depth );
00099
00101 template<unsigned D> OctTreeKey & set_index( const unsigned );
00102
00104 OctTreeKey & set_index( const unsigned Depth , const unsigned );
00105
00107 OctTreeKey & clear();
00108
00110 OctTreeKey & set_maximum();
00111
00113 const value_type * value() const { return m_value ; }
00114
00116 OctTreeKey & set_value( const value_type * );
00117
00119 bool intersect( const OctTreeKey & k ) const ;
00120
00121 private:
00122 void throw_depth( const unsigned ) const ;
00123 void throw_index( const unsigned , const unsigned ) const ;
00124 };
00125
00126
00127
00130 OctTreeKey hsfc3d( const unsigned Depth , const unsigned * const coord );
00131
00132
00133
00134
00135 template<unsigned Depth> struct OctTreeSize ;
00136
00137 template<>
00138 struct OctTreeSize<0>
00139 { enum { value = 1 }; };
00140
00141 template<unsigned Depth>
00142 struct OctTreeSize
00143 {
00144 enum { MaxDepth = 10 , N = Depth };
00145
00146 enum { OK = StaticAssert< N <= MaxDepth >::OK };
00147
00148 enum { value = 1 + 8 * OctTreeSize<Depth-1>::value };
00149 };
00150
00151 unsigned oct_tree_size( const unsigned Depth );
00152
00154 unsigned oct_tree_offset( const unsigned Depth , const OctTreeKey & );
00155
00156 template<unsigned Depth>
00157 inline
00158 unsigned oct_tree_offset( const OctTreeKey & k )
00159 { return oct_tree_offset( Depth , k ); }
00160
00161 }
00162
00163
00164
00165
00166 namespace phdmesh {
00167
00168 template<unsigned Depth>
00169 inline
00170 unsigned OctTreeKey::index() const
00171 {
00172 enum { OK = StaticAssert< 0 < Depth && Depth <= MaxDepth >::OK };
00173 enum { which = ( Depth - 1 ) / IndexPerWord };
00174 enum { shift = BitsPerWord - BitsPerIndex * ( Depth % IndexPerWord ) };
00175
00176 return ( m_value[ which ] >> shift ) & MaskIndex ;
00177 }
00178
00179 template<unsigned Depth>
00180 inline
00181 OctTreeKey & OctTreeKey::clear_index()
00182 {
00183 enum { OK = StaticAssert< 0 < Depth && Depth <= MaxDepth >::OK };
00184 enum { which = ( Depth - 1 ) / IndexPerWord };
00185 enum { shift = BitsPerWord - BitsPerIndex * ( Depth % IndexPerWord ) };
00186
00187 const value_type m = MaskIndex ;
00188
00189 m_value[ which ] &= ~( m << shift );
00190
00191 return *this ;
00192 }
00193
00194 template<unsigned Depth>
00195 inline
00196 OctTreeKey & OctTreeKey::set_index( const unsigned Index )
00197 {
00198 enum { OK = StaticAssert< 0 < Depth && Depth <= MaxDepth >::OK };
00199 enum { which = ( Depth - 1 ) / IndexPerWord };
00200 enum { shift = BitsPerWord - BitsPerIndex * ( Depth % IndexPerWord ) };
00201
00202 if ( 8 < Index ) { throw_index( Depth , Index ); }
00203
00204 const value_type m = MaskIndex ;
00205
00206 ( m_value[which] &= ~( m << shift ) ) |= Index << shift ;
00207
00208 return *this ;
00209 }
00210
00211 }
00212
00213 #endif
00214