Loading [MathJax]/extensions/tex2jax.js
Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OrientedBox.hpp
Go to the documentation of this file.
1 /* 2  * MOAB, a Mesh-Oriented datABase, is a software component for creating, 3  * storing and accessing finite element mesh data. 4  * 5  * Copyright 2004 Sandia Corporation. Under the terms of Contract 6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 7  * retains certain rights in this software. 8  * 9  * This library is free software; you can redistribute it and/or 10  * modify it under the terms of the GNU Lesser General Public 11  * License as published by the Free Software Foundation; either 12  * version 2.1 of the License, or (at your option) any later version. 13  * 14  */ 15  16 /**\file OrientedBox.hpp 17  *\author Jason Kraftcheck (kraftche@cae.wisc.edu) 18  *\date 2006-07-18 19  */ 20  21 #ifndef MB_ORIENTED_BOX_HPP 22 #define MB_ORIENTED_BOX_HPP 23  24 #include "moab/Forward.hpp" 25 #include "moab/CartVect.hpp" 26 #include "moab/Matrix3.hpp" 27  28 #include <iosfwd> 29  30 namespace moab 31 { 32  33 #define MB_ORIENTED_BOX_UNIT_VECTORS 1 34 #define MB_ORIENTED_BOX_OUTER_RADIUS 1 35  36 class Range; 37  38 /**\brief Oriented bounding box 39  */ 40 class OrientedBox 41 { 42  private: 43  void order_axes_by_length( double ax1_len, 44  double ax2_len, 45  double ax3_len ); //!< orders the box axes by the given lengths for each axis 46  47  public: 48  CartVect center; //!< Box center 49  Matrix3 axes; //!< Box axes, unit vectors sorted by extent of box along axis 50 #if MB_ORIENTED_BOX_UNIT_VECTORS 51  CartVect length; //!< distance from center to plane along each axis 52 #endif 53 #if MB_ORIENTED_BOX_OUTER_RADIUS 54  double radius; //!< outer radius (1/2 diagonal length) of box 55 #endif 56  57  inline OrientedBox() : radius( 0.0 ) {} 58  59  OrientedBox( const Matrix3& axes_mat, const CartVect& center ); 60  OrientedBox( const CartVect axes_in[3], const CartVect& center ); 61  62  inline double inner_radius() const; //!< radius of inscribed sphere 63  inline double outer_radius() const; //!< radius of circumscribed sphere 64  inline double outer_radius_squared( 65  const double reps ) const; //!< square of (radius+at least epsilon) of circumsphere 66  inline double inner_radius_squared( const double reps ) const; //!< square of (radius-epsilon) of inscribed sphere 67  inline double volume() const; //!< volume of box 68  inline CartVect dimensions() const; //!< number of dimensions for which box is not flat 69  inline double area() const; //!< largest side area 70  inline CartVect axis( int index ) const; //!< get unit vector in direction of axis 71  inline CartVect scaled_axis( int index ) const; //!< get vector in direction of axis, scaled to its true length 72  73  /** Test if point is contained in box */ 74  bool contained( const CartVect& point, double tolerance ) const; 75  76  // bool contained( const OrientedBox& other, double tolerance ) const; 77  78  /**\brief get tag handle for storing oriented box 79  * 80  * Get the handle for the tag with the specified name and 81  * check that the tag is appropriate for storing instances 82  * of OrientedBox. The resulting tag may be used to store 83  * instances of OrientedBox directly. 84  * 85  *\param handle_out The TagHandle, passed back to caller 86  *\param name The tag name 87  *\param create If true, tag will be created if it does not exist 88  */ 89  static ErrorCode tag_handle( Tag& handle_out, Interface* instance, const char* name ); 90  91  /**\brief Calculate an oriented box from a set of vertices */ 92  static ErrorCode compute_from_vertices( OrientedBox& result, Interface* instance, const Range& vertices ); 93  94  /**\brief Calculate an oriented box from a set of 2D elements */ 95  static ErrorCode compute_from_2d_cells( OrientedBox& result, Interface* instance, const Range& elements ); 96  97  /** Structure to hold temporary accumulated triangle data for 98  * calculating box orientation. See box_from_covariance_data 99  * to see how this is used to calculate the final covariance matrix 100  * and resulting box orientation. 101  */ 102  struct CovarienceData 103  { 104  CovarienceData() : area( 0.0 ) {} 105  CovarienceData( const Matrix3& m, const CartVect& c, double a ) : matrix( m ), center( c ), area( a ) {} 106  Matrix3 matrix; //!< Running sum for covariance matrix 107  CartVect center; //!< Sum of triangle centroids weighted by 2*triangle area 108  double area; //!< 2x the sum of the triangle areas 109  }; 110  111  /** Calculate a CovarienceData struct from a list of triangles */ 112  static ErrorCode covariance_data_from_tris( CovarienceData& result, 113  Interface* moab_instance, 114  const Range& elements ); 115  116  /** Calculate an OrientedBox given an array of CovarienceData and 117  * the list of vertices the box is to bound. 118  */ 119  static ErrorCode compute_from_covariance_data( OrientedBox& result, 120  Interface* moab_instance, 121  const CovarienceData* orient_array, 122  unsigned orient_array_length, 123  const Range& vertices ); 124  125  /** Test for intersection of a ray (or line segment) with this box. 126  * Ray length limits are used to optimize Monte Carlo particle tracking. 127  *\param ray_start_point The base point of the ray 128  *\param ray_unit_direction The direction of the ray (must be unit length) 129  *\param distance_tolerance Tolerance to use in intersection checks 130  *\param nonnegative_ray_len Optional length of ray in forward direction 131  *\param negative_ray_len Optional length of ray in reverse direction 132  */ 133  bool intersect_ray( const CartVect& ray_start_point, 134  const CartVect& ray_unit_direction, 135  const double distance_tolerance, 136  const double* nonnegatve_ray_len = 0, 137  const double* negative_ray_len = 0 ) const; 138  139  /**\brief Find closest position on/within box to input position. 140  * 141  * Find the closest position in the solid box to the input position. 142  * If the input position is on or within the box, then the output 143  * position will be the same as the input position. If the input 144  * position is outside the box, the outside position will be the 145  * closest point on the box boundary to the input position. 146  */ 147  void closest_location_in_box( const CartVect& input_position, CartVect& output_position ) const; 148  149  //! Construct a hexahedral element with the same shape as this box. 150  ErrorCode make_hex( EntityHandle& hex, Interface* instance ); 151  152  /** Calculate an OrientedBox given a CovarienceData struct and 153  * the list of points the box is to bound. 154  */ 155  static ErrorCode compute_from_covariance_data( OrientedBox& result, 156  Interface* moab_instance, 157  CovarienceData& orientation_data, 158  const Range& vertices ); 159 }; 160  161 std::ostream& operator<<( std::ostream&, const OrientedBox& ); 162  163 double OrientedBox::inner_radius() const 164 { 165 #if MB_ORIENTED_BOX_UNIT_VECTORS 166  return length[0]; 167 #else 168  return axes.col( 0 ).length(); 169 #endif 170 } 171  172 double OrientedBox::outer_radius() const 173 { 174 #if MB_ORIENTED_BOX_OUTER_RADIUS 175  return radius; 176 #elif MB_ORIENTED_BOX_UNIT_VECTORS 177  return length.length(); 178 #else 179  return ( axes.col( 0 ) + axes.col( 1 ) + axes.col( 2 ) ).length(); 180 #endif 181 } 182  183 // Add at least epsilon to the radius, before squaring it. 184 double OrientedBox::outer_radius_squared( const double reps ) const 185 { 186 #if MB_ORIENTED_BOX_OUTER_RADIUS 187  return ( radius + reps ) * ( radius + reps ); 188 #elif MB_ORIENTED_BOX_UNIT_VECTORS 189  CartVect tmp( length[0] + reps, length[1] + reps, length[2] + reps ); 190  return tmp % tmp; 191 #else 192  CartVect half_diag = axes.col( 0 ) + axes.col( 1 ) + axes.col( 2 ); 193  half_diag += CartVect( reps, reps, reps ); 194  return half_diag % half_diag; 195 #endif 196 } 197  198 // Subtract epsilon from the length of the shortest axis, before squaring it. 199 double OrientedBox::inner_radius_squared( const double reps ) const 200 { 201 #if MB_ORIENTED_BOX_UNIT_VECTORS 202  return ( length[0] - reps ) * ( length[0] - reps ); 203 #else 204  CartVect tmp = axes.col( 0 ); 205  tmp -= CartVect( reps, reps, reps ); 206  return ( tmp % tmp ); 207 #endif 208 } 209  210 double OrientedBox::volume() const 211 { 212 #if MB_ORIENTED_BOX_UNIT_VECTORS 213  return 8 * length[0] * length[1] * length[2]; 214 #else 215  return fabs( 8 * axes.col( 0 ) % ( axes.col( 1 ) * axes.col( 2 ) ) ); 216 #endif 217 } 218  219 CartVect OrientedBox::dimensions() const 220 { 221 #if MB_ORIENTED_BOX_UNIT_VECTORS 222  return 2.0 * length; 223 #else 224  return 2.0 * CartVect( axes.col( 0 ).length(), axes.col( 1 ).length(), axes.col( 2 ).length() ); 225 #endif 226 } 227  228 double OrientedBox::area() const 229 { 230 #if MB_ORIENTED_BOX_UNIT_VECTORS 231  return 4 * length[1] * length[2]; 232 #else 233  return 4 * ( axes.col( 1 ) * axes.col( 2 ) ).length(); 234 #endif 235 } 236  237 CartVect OrientedBox::axis( int index ) const 238 { 239  return axes.col( index ); 240 } 241  242 CartVect OrientedBox::scaled_axis( int index ) const 243 { 244 #if MB_ORIENTED_BOX_UNIT_VECTORS 245  return length[index] * axes.col( index ); 246 #else 247  return axes.col( index ); 248 #endif 249 } 250  251 } // namespace moab 252  253 #endif