MOAB: Mesh Oriented datABase  (version 5.3.0)
OrientedBox.hpp
Go to the documentation of this file.
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 <iosfwd>
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, double ax2_len,
00044                                double ax3_len );  //!< orders the box axes by the given lengths for each axis
00045 
00046   public:
00047     CartVect center;  //!< Box center
00048     Matrix3 axes;     //!< Box axes, unit vectors sorted by extent of box along axis
00049 #if MB_ORIENTED_BOX_UNIT_VECTORS
00050     CartVect length;  //!< distance from center to plane along each axis
00051 #endif
00052 #if MB_ORIENTED_BOX_OUTER_RADIUS
00053     double radius;  //!< outer radius (1/2 diagonal length) of box
00054 #endif
00055 
00056     inline OrientedBox() : radius( 0.0 ) {}
00057 
00058     OrientedBox( const Matrix3& axes_mat, const CartVect& center );
00059     OrientedBox( const CartVect axes_in[3], const CartVect& center );
00060 
00061     inline double inner_radius() const;  //!< radius of inscribed sphere
00062     inline double outer_radius() const;  //!< radius of circumscribed sphere
00063     inline double outer_radius_squared(
00064         const double reps ) const;  //!< square of (radius+at least epsilon) of circumsphere
00065     inline double inner_radius_squared( const double reps ) const;  //!< square of (radius-epsilon) of inscribed sphere
00066     inline double volume() const;                                   //!< volume of box
00067     inline CartVect dimensions() const;                             //!< number of dimensions for which box is not flat
00068     inline double area() const;                                     //!< largest side area
00069     inline CartVect axis( int index ) const;                        //!< get unit vector in direction of axis
00070     inline CartVect scaled_axis( int index ) const;  //!< get vector in direction of axis, scaled to its true length
00071 
00072     /** Test if point is contained in box */
00073     bool contained( const CartVect& point, double tolerance ) const;
00074 
00075     // bool contained( const OrientedBox& other, double tolerance ) const;
00076 
00077     /**\brief get tag handle for storing oriented box
00078      *
00079      * Get the handle for the tag with the specified name and
00080      * check that the tag is appropriate for storing instances
00081      * of OrientedBox.  The resulting tag may be used to store
00082      * instances of OrientedBox directly.
00083      *
00084      *\param handle_out  The TagHandle, passed back to caller
00085      *\param name        The tag name
00086      *\param create      If true, tag will be created if it does not exist
00087      */
00088     static ErrorCode tag_handle( Tag& handle_out, Interface* instance, const char* name );
00089 
00090     /**\brief Calculate an oriented box from a set of vertices */
00091     static ErrorCode compute_from_vertices( OrientedBox& result, Interface* instance, const Range& vertices );
00092 
00093     /**\brief Calculate an oriented box from a set of 2D elements */
00094     static ErrorCode compute_from_2d_cells( OrientedBox& result, Interface* instance, const Range& elements );
00095 
00096     /** Structure to hold temporary accumulated triangle data for
00097      *  calculating box orientation.  See box_from_covariance_data
00098      *  to see how this is used to calculate the final covariance matrix
00099      *  and resulting box orientation.
00100      */
00101     struct CovarienceData
00102     {
00103         CovarienceData() : area( 0.0 ) {}
00104         CovarienceData( const Matrix3& m, const CartVect& c, double a ) : matrix( m ), center( c ), area( a ) {}
00105         Matrix3 matrix;   //!< Running sum for covariance matrix
00106         CartVect center;  //!< Sum of triangle centroids weighted by 2*triangle area
00107         double area;      //!< 2x the sum of the triangle areas
00108     };
00109 
00110     /** Calculate a CovarienceData struct from a list of triangles */
00111     static ErrorCode covariance_data_from_tris( CovarienceData& result, Interface* moab_instance,
00112                                                 const Range& elements );
00113 
00114     /** Calculate an OrientedBox given an array of CovarienceData and
00115      *  the list  of vertices the box is to bound.
00116      */
00117     static ErrorCode compute_from_covariance_data( OrientedBox& result, Interface* moab_instance,
00118                                                    const CovarienceData* orient_array, unsigned orient_array_length,
00119                                                    const Range& vertices );
00120 
00121     /** Test for intersection of a ray (or line segment) with this box.
00122      *  Ray length limits are used to optimize Monte Carlo particle tracking.
00123      *\param ray_start_point     The base point of the ray
00124      *\param ray_unit_direction  The direction of the ray (must be unit length)
00125      *\param distance_tolerance  Tolerance to use in intersection checks
00126      *\param nonnegative_ray_len Optional length of ray in forward direction
00127      *\param negative_ray_len    Optional length of ray in reverse direction
00128      */
00129     bool intersect_ray( const CartVect& ray_start_point, const CartVect& ray_unit_direction,
00130                         const double distance_tolerance, const double* nonnegatve_ray_len = 0,
00131                         const double* negative_ray_len = 0 ) const;
00132 
00133     /**\brief Find closest position on/within box to input position.
00134      *
00135      * Find the closest position in the solid box to the input position.
00136      * If the input position is on or within the box, then the output
00137      * position will be the same as the input position.  If the input
00138      * position is outside the box, the outside position will be the
00139      * closest point on the box boundary to the input position.
00140      */
00141     void closest_location_in_box( const CartVect& input_position, CartVect& output_position ) const;
00142 
00143     //! Construct a hexahedral element with the same shape as this box.
00144     ErrorCode make_hex( EntityHandle& hex, Interface* instance );
00145 
00146     /** Calculate an OrientedBox given a CovarienceData struct and
00147      *  the list of points the box is to bound.
00148      */
00149     static ErrorCode compute_from_covariance_data( OrientedBox& result, Interface* moab_instance,
00150                                                    CovarienceData& orientation_data, const Range& vertices );
00151 };
00152 
00153 std::ostream& operator<<( std::ostream&, const OrientedBox& );
00154 
00155 double OrientedBox::inner_radius() const
00156 {
00157 #if MB_ORIENTED_BOX_UNIT_VECTORS
00158     return length[0];
00159 #else
00160     return axes.col( 0 ).length();
00161 #endif
00162 }
00163 
00164 double OrientedBox::outer_radius() const
00165 {
00166 #if MB_ORIENTED_BOX_OUTER_RADIUS
00167     return radius;
00168 #elif MB_ORIENTED_BOX_UNIT_VECTORS
00169     return length.length();
00170 #else
00171     return ( axes.col( 0 ) + axes.col( 1 ) + axes.col( 2 ) ).length();
00172 #endif
00173 }
00174 
00175 // Add at least epsilon to the radius, before squaring it.
00176 double OrientedBox::outer_radius_squared( const double reps ) const
00177 {
00178 #if MB_ORIENTED_BOX_OUTER_RADIUS
00179     return ( radius + reps ) * ( radius + reps );
00180 #elif MB_ORIENTED_BOX_UNIT_VECTORS
00181     CartVect tmp( length[0] + reps, length[1] + reps, length[2] + reps );
00182     return tmp % tmp;
00183 #else
00184     CartVect half_diag = axes.col( 0 ) + axes.col( 1 ) + axes.col( 2 );
00185     half_diag += CartVect( reps, reps, reps );
00186     return half_diag % half_diag;
00187 #endif
00188 }
00189 
00190 // Subtract epsilon from the length of the shortest axis, before squaring it.
00191 double OrientedBox::inner_radius_squared( const double reps ) const
00192 {
00193 #if MB_ORIENTED_BOX_UNIT_VECTORS
00194     return ( length[0] - reps ) * ( length[0] - reps );
00195 #else
00196     CartVect tmp = axes.col( 0 );
00197     tmp -= CartVect( reps, reps, reps );
00198     return ( tmp % tmp );
00199 #endif
00200 }
00201 
00202 double OrientedBox::volume() const
00203 {
00204 #if MB_ORIENTED_BOX_UNIT_VECTORS
00205     return 8 * length[0] * length[1] * length[2];
00206 #else
00207     return fabs( 8 * axes.col( 0 ) % ( axes.col( 1 ) * axes.col( 2 ) ) );
00208 #endif
00209 }
00210 
00211 CartVect OrientedBox::dimensions() const
00212 {
00213 #if MB_ORIENTED_BOX_UNIT_VECTORS
00214     return 2.0 * length;
00215 #else
00216     return 2.0 * CartVect( axes.col( 0 ).length(), axes.col( 1 ).length(), axes.col( 2 ).length() );
00217 #endif
00218 }
00219 
00220 double OrientedBox::area() const
00221 {
00222 #if MB_ORIENTED_BOX_UNIT_VECTORS
00223     return 4 * length[1] * length[2];
00224 #else
00225     return 4 * ( axes.col( 1 ) * axes.col( 2 ) ).length();
00226 #endif
00227 }
00228 
00229 CartVect OrientedBox::axis( int index ) const
00230 {
00231     return axes.col( index );
00232 }
00233 
00234 CartVect OrientedBox::scaled_axis( int index ) const
00235 {
00236 #if MB_ORIENTED_BOX_UNIT_VECTORS
00237     return length[index] * axes.col( index );
00238 #else
00239     return axes.col( index );
00240 #endif
00241 }
00242 
00243 }  // namespace moab
00244 
00245 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines