moab
|
00001 /* 00002 * MOAB, a Mesh-Oriented datABase, is a software component for creating, 00003 * storing and accessing finite element mesh data. 00004 * 00005 * Copyright 2004 Sandia Corporation. Under the terms of Contract 00006 * DE-AC04-94AL85000 with Sandia Coroporation, the U.S. Government 00007 * retains certain rights in this software. 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 */ 00015 00021 #ifndef MB_ORIENTED_BOX_HPP 00022 #define MB_ORIENTED_BOX_HPP 00023 00024 #include "moab/Forward.hpp" 00025 #include "moab/CartVect.hpp" 00026 #include "moab/Matrix3.hpp" 00027 00028 #include <iosfwd> 00029 00030 namespace moab { 00031 00032 #define MB_ORIENTED_BOX_UNIT_VECTORS 1 00033 #define MB_ORIENTED_BOX_OUTER_RADIUS 1 00034 00035 class Range; 00036 00037 00040 class OrientedBox 00041 { 00042 public: 00043 CartVect center; 00044 CartVect axis[3]; 00045 #if MB_ORIENTED_BOX_UNIT_VECTORS 00046 CartVect length; 00047 #endif 00048 #if MB_ORIENTED_BOX_OUTER_RADIUS 00049 double radius; 00050 #endif 00051 00052 inline OrientedBox() {} 00053 00054 OrientedBox( const CartVect axis[3], const CartVect& center ); 00055 00056 inline double inner_radius() const; 00057 inline double outer_radius() const; 00058 inline double outer_radius_squared(const double reps) const; 00059 inline double inner_radius_squared(const double reps) const; 00060 inline double volume() const; 00061 inline CartVect dimensions() const; 00062 inline double area() const; 00063 inline CartVect scaled_axis( int index ) const; 00064 00066 bool contained( const CartVect& point, double tolerance ) const; 00067 00068 //bool contained( const OrientedBox& other, double tolerance ) const; 00069 00081 static ErrorCode tag_handle( Tag& handle_out, 00082 Interface* instance, 00083 const char* name); 00084 00086 static ErrorCode compute_from_vertices( OrientedBox& result, 00087 Interface* instance, 00088 const Range& vertices ); 00089 00091 static ErrorCode compute_from_2d_cells( OrientedBox& result, 00092 Interface* instance, 00093 const Range& elements ); 00094 00100 struct CovarienceData { 00101 CovarienceData() {} 00102 CovarienceData( const Matrix3& m, const CartVect& c, double a) 00103 : matrix(m), center(c), area(a) {} 00104 Matrix3 matrix; 00105 CartVect center; 00106 double area; 00107 }; 00108 00110 static ErrorCode covariance_data_from_tris( CovarienceData& result, 00111 Interface* moab_instance, 00112 const Range& elements ); 00113 00117 static ErrorCode compute_from_covariance_data( OrientedBox& result, 00118 Interface* moab_instance, 00119 const CovarienceData* orient_array, 00120 unsigned orient_array_length, 00121 const Range& vertices ); 00122 00131 bool intersect_ray( const CartVect& ray_start_point, 00132 const CartVect& ray_unit_direction, 00133 const double distance_tolerance, 00134 const double* nonnegatve_ray_len = 0, 00135 const double* negative_ray_len = 0 ) const; 00136 00145 void closest_location_in_box( const CartVect& input_position, 00146 CartVect& output_position ) const; 00147 00149 ErrorCode make_hex( EntityHandle& hex, Interface* instance ); 00150 00151 00155 static ErrorCode compute_from_covariance_data( OrientedBox& result, 00156 Interface* moab_instance, 00157 CovarienceData& orientation_data, 00158 const Range& vertices ); 00159 }; 00160 00161 std::ostream& operator<<( std::ostream&, const OrientedBox& ); 00162 00163 double OrientedBox::inner_radius() const 00164 { 00165 #if MB_ORIENTED_BOX_UNIT_VECTORS 00166 return length[0]; 00167 #else 00168 return axis[0].length(); 00169 #endif 00170 } 00171 00172 double OrientedBox::outer_radius() const 00173 { 00174 #if MB_ORIENTED_BOX_OUTER_RADIUS 00175 return radius; 00176 #elif MB_ORIENTED_BOX_UNIT_VECTORS 00177 return length.length(); 00178 #else 00179 return (axis[0] + axis[1] + axis[2]).length(); 00180 #endif 00181 } 00182 00183 // Add at least epsilon to the radius, before squaring it. 00184 double OrientedBox::outer_radius_squared(const double reps) const 00185 { 00186 #if MB_ORIENTED_BOX_OUTER_RADIUS 00187 return (radius+reps)*(radius+reps); 00188 #elif MB_ORIENTED_BOX_UNIT_VECTORS 00189 CartVect tmp(length[0]+reps,length[1]+reps,length[2]+reps); 00190 return tmp % tmp; 00191 #else 00192 CartVect half_diag = axis[0] + axis[1] + axis[2]; 00193 half_diag += CartVect(reps,reps,reps); 00194 return half_diag % half_diag; 00195 #endif 00196 } 00197 00198 // Subtract epsilon from the length of the shortest axis, before squaring it. 00199 double OrientedBox::inner_radius_squared(const double reps) const 00200 { 00201 #if MB_ORIENTED_BOX_UNIT_VECTORS 00202 return (length[0]-reps) * (length[0]-reps); 00203 #else 00204 CartVect tmp = axis[0]; 00205 tmp -= CartVect(reps,reps,reps); 00206 return (tmp % tmp); 00207 #endif 00208 } 00209 00210 double OrientedBox::volume() const 00211 { 00212 #if MB_ORIENTED_BOX_UNIT_VECTORS 00213 return 8 * length[0] * length[1] * length[2]; 00214 #else 00215 return fabs(8 * axis[0] % (axis[1] * axis[2])); 00216 #endif 00217 } 00218 00219 CartVect OrientedBox::dimensions() const 00220 { 00221 #if MB_ORIENTED_BOX_UNIT_VECTORS 00222 return 2.0 * length; 00223 #else 00224 return 2.0 * CartVect( axis[0].length(), axis[1].length(), axis[2].length() ); 00225 #endif 00226 } 00227 00228 double OrientedBox::area() const 00229 { 00230 #if MB_ORIENTED_BOX_UNIT_VECTORS 00231 return 4 * length[1] * length[2]; 00232 #else 00233 return 4 * (axis[1] * axis[2]).length(); 00234 #endif 00235 } 00236 00237 CartVect OrientedBox::scaled_axis( int index ) const 00238 { 00239 #if MB_ORIENTED_BOX_UNIT_VECTORS 00240 return length[index] * axis[index]; 00241 #else 00242 return axis[index]; 00243 #endif 00244 } 00245 00246 } // namespace moab 00247 00248 #endif