![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
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 Corporation, 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
00016 /**\file OrientedBox.hpp
00017 *\author Jason Kraftcheck (kraftche@cae.wisc.edu)
00018 *\date 2006-07-18
00019 */
00020
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
00029
00030 namespace moab
00031 {
00032
00033 #define MB_ORIENTED_BOX_UNIT_VECTORS 1
00034 #define MB_ORIENTED_BOX_OUTER_RADIUS 1
00035
00036 class Range;
00037
00038 /**\brief Oriented bounding box
00039 */
00040 class OrientedBox
00041 {
00042 private:
00043 void order_axes_by_length( double ax1_len,
00044 double ax2_len,
00045 double ax3_len ); //!< orders the box axes by the given lengths for each axis
00046
00047 public:
00048 CartVect center; //!< Box center
00049 Matrix3 axes; //!< Box axes, unit vectors sorted by extent of box along axis
00050 #if MB_ORIENTED_BOX_UNIT_VECTORS
00051 CartVect length; //!< distance from center to plane along each axis
00052 #endif
00053 #if MB_ORIENTED_BOX_OUTER_RADIUS
00054 double radius; //!< outer radius (1/2 diagonal length) of box
00055 #endif
00056
00057 inline OrientedBox() : radius( 0.0 ) {}
00058
00059 OrientedBox( const Matrix3& axes_mat, const CartVect& center );
00060 OrientedBox( const CartVect axes_in[3], const CartVect& center );
00061
00062 inline double inner_radius() const; //!< radius of inscribed sphere
00063 inline double outer_radius() const; //!< radius of circumscribed sphere
00064 inline double outer_radius_squared(
00065 const double reps ) const; //!< square of (radius+at least epsilon) of circumsphere
00066 inline double inner_radius_squared( const double reps ) const; //!< square of (radius-epsilon) of inscribed sphere
00067 inline double volume() const; //!< volume of box
00068 inline CartVect dimensions() const; //!< number of dimensions for which box is not flat
00069 inline double area() const; //!< largest side area
00070 inline CartVect axis( int index ) const; //!< get unit vector in direction of axis
00071 inline CartVect scaled_axis( int index ) const; //!< get vector in direction of axis, scaled to its true length
00072
00073 /** Test if point is contained in box */
00074 bool contained( const CartVect& point, double tolerance ) const;
00075
00076 // bool contained( const OrientedBox& other, double tolerance ) const;
00077
00078 /**\brief get tag handle for storing oriented box
00079 *
00080 * Get the handle for the tag with the specified name and
00081 * check that the tag is appropriate for storing instances
00082 * of OrientedBox. The resulting tag may be used to store
00083 * instances of OrientedBox directly.
00084 *
00085 *\param handle_out The TagHandle, passed back to caller
00086 *\param name The tag name
00087 *\param create If true, tag will be created if it does not exist
00088 */
00089 static ErrorCode tag_handle( Tag& handle_out, Interface* instance, const char* name );
00090
00091 /**\brief Calculate an oriented box from a set of vertices */
00092 static ErrorCode compute_from_vertices( OrientedBox& result, Interface* instance, const Range& vertices );
00093
00094 /**\brief Calculate an oriented box from a set of 2D elements */
00095 static ErrorCode compute_from_2d_cells( OrientedBox& result, Interface* instance, const Range& elements );
00096
00097 /** Structure to hold temporary accumulated triangle data for
00098 * calculating box orientation. See box_from_covariance_data
00099 * to see how this is used to calculate the final covariance matrix
00100 * and resulting box orientation.
00101 */
00102 struct CovarienceData
00103 {
00104 CovarienceData() : area( 0.0 ) {}
00105 CovarienceData( const Matrix3& m, const CartVect& c, double a ) : matrix( m ), center( c ), area( a ) {}
00106 Matrix3 matrix; //!< Running sum for covariance matrix
00107 CartVect center; //!< Sum of triangle centroids weighted by 2*triangle area
00108 double area; //!< 2x the sum of the triangle areas
00109 };
00110
00111 /** Calculate a CovarienceData struct from a list of triangles */
00112 static ErrorCode covariance_data_from_tris( CovarienceData& result,
00113 Interface* moab_instance,
00114 const Range& elements );
00115
00116 /** Calculate an OrientedBox given an array of CovarienceData and
00117 * the list of vertices the box is to bound.
00118 */
00119 static ErrorCode compute_from_covariance_data( OrientedBox& result,
00120 Interface* moab_instance,
00121 const CovarienceData* orient_array,
00122 unsigned orient_array_length,
00123 const Range& vertices );
00124
00125 /** Test for intersection of a ray (or line segment) with this box.
00126 * Ray length limits are used to optimize Monte Carlo particle tracking.
00127 *\param ray_start_point The base point of the ray
00128 *\param ray_unit_direction The direction of the ray (must be unit length)
00129 *\param distance_tolerance Tolerance to use in intersection checks
00130 *\param nonnegative_ray_len Optional length of ray in forward direction
00131 *\param negative_ray_len Optional length of ray in reverse direction
00132 */
00133 bool intersect_ray( const CartVect& ray_start_point,
00134 const CartVect& ray_unit_direction,
00135 const double distance_tolerance,
00136 const double* nonnegatve_ray_len = 0,
00137 const double* negative_ray_len = 0 ) const;
00138
00139 /**\brief Find closest position on/within box to input position.
00140 *
00141 * Find the closest position in the solid box to the input position.
00142 * If the input position is on or within the box, then the output
00143 * position will be the same as the input position. If the input
00144 * position is outside the box, the outside position will be the
00145 * closest point on the box boundary to the input position.
00146 */
00147 void closest_location_in_box( const CartVect& input_position, CartVect& output_position ) const;
00148
00149 //! Construct a hexahedral element with the same shape as this box.
00150 ErrorCode make_hex( EntityHandle& hex, Interface* instance );
00151
00152 /** Calculate an OrientedBox given a CovarienceData struct and
00153 * the list of points the box is to bound.
00154 */
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 axes.col( 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 ( axes.col( 0 ) + axes.col( 1 ) + axes.col( 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 = axes.col( 0 ) + axes.col( 1 ) + axes.col( 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 = axes.col( 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 * axes.col( 0 ) % ( axes.col( 1 ) * axes.col( 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( axes.col( 0 ).length(), axes.col( 1 ).length(), axes.col( 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 * ( axes.col( 1 ) * axes.col( 2 ) ).length();
00234 #endif
00235 }
00236
00237 CartVect OrientedBox::axis( int index ) const
00238 {
00239 return axes.col( index );
00240 }
00241
00242 CartVect OrientedBox::scaled_axis( int index ) const
00243 {
00244 #if MB_ORIENTED_BOX_UNIT_VECTORS
00245 return length[index] * axes.col( index );
00246 #else
00247 return axes.col( index );
00248 #endif
00249 }
00250
00251 } // namespace moab
00252
00253 #endif