OpenWalnut
1.4.0
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #ifndef WBOUNDINGBOX_H 00026 #define WBOUNDINGBOX_H 00027 00028 #include <ostream> 00029 #include <iomanip> // for setprecision 00030 #include <cmath> // std::sqrt 00031 00032 #include <osg/BoundingBox> 00033 00034 #include "exceptions/WInvalidBoundingBox.h" 00035 //#include "math/linearAlgebra/WLinearAlgebra.h" 00036 00037 /** 00038 * Represents a \e axis \e parallel bounding box and provides some useful operations with them. 00039 * 00040 * \note Reason for subclassing: We don't want \c _min and \c _max member variables to be public. 00041 * \note Reason for not having a \e private osg::BoundingBox member is, we don't have to wrap many 00042 * member functions and can make use of the using directive. A downside on this is, we cannot 00043 * automatical cast to osg::BoundingBox even if we provide a cast operator! Hence when we need this 00044 * we will provide a toOsgBB() member function. 00045 */ 00046 template< class VT > 00047 class WBoundingBoxImpl : private osg::BoundingBoxImpl< VT > 00048 { 00049 public: 00050 /** 00051 * Vertex type for min and max positions of this box. 00052 */ 00053 typedef typename osg::BoundingBoxImpl< VT >::vec_type vec_type; 00054 00055 /** 00056 * Value type of the vertex type for example double, float, etc. 00057 */ 00058 typedef typename osg::BoundingBoxImpl< VT >::value_type value_type; 00059 00060 /** 00061 * Default constructor. 00062 */ 00063 WBoundingBoxImpl(); 00064 00065 /** 00066 * Wrapps the component wise bounding box constructor from osg::BoundingBox. 00067 * 00068 * \param xmin Minimal x coordinate 00069 * \param ymin Minimal y coordinate 00070 * \param zmin Minimal z coordinate 00071 * \param xmax Maximal x coordinate 00072 * \param ymax Maximal y coordinate 00073 * \param zmax Maximal z coordinate 00074 */ 00075 WBoundingBoxImpl( value_type xmin, value_type ymin, value_type zmin, value_type xmax, value_type ymax, value_type zmax ); 00076 00077 /** 00078 * Constructs a bounding box by min and max positions. 00079 * 00080 * \param min Position containing minx miny and minz coordinates. 00081 * \param max Position containing maxx maxy and maxz coordinates. 00082 */ 00083 WBoundingBoxImpl( const vec_type& min, const vec_type& max ); 00084 00085 /** 00086 * Copy construct using a given bounding box 00087 * 00088 * \param bb the source bb 00089 */ 00090 WBoundingBoxImpl( const WBoundingBoxImpl& bb ); 00091 00092 /** 00093 * Create BoundinmgBox using a given sphere. 00094 * 00095 * \param bs the sphere 00096 */ 00097 explicit WBoundingBoxImpl( const osg::BoundingSphereImpl< VT >& bs ); 00098 00099 /** 00100 * Destructs this instance. 00101 */ 00102 virtual ~WBoundingBoxImpl(); 00103 00104 /** 00105 * Resets this box to an initial state where max is FLT_MIN and min FLT_MAX. 00106 * 00107 * \note This is a wrapper call to osg::BoundingBoxImpl< VT >::init() 00108 */ 00109 void reset(); 00110 00111 using osg::BoundingBoxImpl< VT >::valid; 00112 using osg::BoundingBoxImpl< VT >::set; 00113 using osg::BoundingBoxImpl< VT >::xMin; 00114 using osg::BoundingBoxImpl< VT >::yMin; 00115 using osg::BoundingBoxImpl< VT >::zMin; 00116 using osg::BoundingBoxImpl< VT >::xMax; 00117 using osg::BoundingBoxImpl< VT >::yMax; 00118 using osg::BoundingBoxImpl< VT >::zMax; 00119 using osg::BoundingBoxImpl< VT >::center; 00120 using osg::BoundingBoxImpl< VT >::radius; 00121 00122 /** 00123 * Calculates and returns the squared length of the bounding box radius. 00124 * 00125 * \note This is a wrapper call to osg::BoundingBoxImpl< VT >::radius2() 00126 * 00127 * \return squared bbox radius 00128 */ 00129 value_type radiusSquare() const; 00130 00131 using osg::BoundingBoxImpl< VT >::corner; 00132 00133 /** 00134 * Explicit type conversion function to use a WBoundingBox as osg::BoundingBox. 00135 * 00136 * \return A copy of this bounding box as osg::BoundingBox. 00137 */ 00138 osg::BoundingBox toOSGBB() const; 00139 00140 using osg::BoundingBoxImpl< VT >::expandBy; 00141 00142 /** 00143 * Expands this bounding box to include the given bounding box. 00144 * 00145 * \param bb The other bounding box. 00146 */ 00147 void expandBy( const WBoundingBoxImpl< VT > &bb ); 00148 00149 /** 00150 * Checks for intersection of this bounding box with the specified bounding box. 00151 * 00152 * \param bb The other bouding box to tetst with. 00153 * 00154 * \return True if they intersect, false otherwise. 00155 */ 00156 bool intersects( const WBoundingBoxImpl< VT > &bb ) const; 00157 00158 /** 00159 * Computes the minimal distance of tow axis parallel bounding boxes. 00160 * 00161 * \param bb The other bounding box. 00162 * 00163 * \return Zero if they intersect, otherwise their minimal distance. 00164 */ 00165 value_type minDistance( const WBoundingBoxImpl< VT > &bb ) const; 00166 00167 using osg::BoundingBoxImpl< VT >::contains; 00168 00169 /** 00170 * Gives the front lower left aka minimum corner. 00171 * 00172 * \return Minimum corner. 00173 */ 00174 const vec_type& getMin() const; 00175 00176 /** 00177 * Gives the back upper right aka maximum corner. 00178 * 00179 * \return Maximum corner. 00180 */ 00181 const vec_type& getMax() const; 00182 00183 protected: 00184 private: 00185 /** 00186 * Checks if the two given intervals intersect and computes the distance between them. 00187 * 00188 * \param a0 lower bound of the first interval 00189 * \param a1 upper bound of the first interval 00190 * \param b0 lower bound of the second interval 00191 * \param b1 upper bound if the second interval 00192 * 00193 * \return The distance between those intervals if they don't overlap, zero otherwise 00194 */ 00195 double intervalDistance( double a0, double a1, double b0, double b1 ) const; 00196 }; 00197 00198 template< class VT > 00199 inline WBoundingBoxImpl< VT >::WBoundingBoxImpl() 00200 : osg::BoundingBoxImpl< VT >() 00201 { 00202 } 00203 00204 template< class VT > 00205 inline WBoundingBoxImpl< VT >::WBoundingBoxImpl( value_type xmin, value_type ymin, value_type zmin, value_type xmax, value_type ymax, value_type zmax ) // NOLINT line length 00206 : osg::BoundingBoxImpl< VT >( xmin, ymin, zmin, xmax, ymax, zmax ) 00207 { 00208 } 00209 00210 template< class VT > 00211 inline WBoundingBoxImpl< VT >::WBoundingBoxImpl( const vec_type& min, const vec_type& max ) 00212 : osg::BoundingBoxImpl< VT >( min, max ) 00213 { 00214 } 00215 00216 template< class VT > 00217 inline WBoundingBoxImpl< VT >::WBoundingBoxImpl( const osg::BoundingSphereImpl< VT >& bs ) 00218 : osg::BoundingBoxImpl< VT >( bs.center() - VT( bs.radius(), bs.radius(), bs.radius() ) , 00219 bs.center() + VT( bs.radius(), bs.radius(), bs.radius() ) ) 00220 { 00221 } 00222 00223 template< class VT > 00224 inline WBoundingBoxImpl< VT >::WBoundingBoxImpl( const WBoundingBoxImpl< VT >& bb ) 00225 : osg::BoundingBoxImpl< VT >( bb ) 00226 { 00227 } 00228 00229 template< class VT > 00230 inline WBoundingBoxImpl< VT >::~WBoundingBoxImpl() 00231 { 00232 } 00233 00234 template< class VT > 00235 inline void WBoundingBoxImpl< VT >::reset() 00236 { 00237 this->init(); 00238 } 00239 00240 template< class VT > 00241 inline typename WBoundingBoxImpl< VT >::value_type WBoundingBoxImpl< VT >::radiusSquare() const 00242 { 00243 return this->radius2(); 00244 } 00245 00246 template< class VT > 00247 inline osg::BoundingBox WBoundingBoxImpl< VT >::toOSGBB() const 00248 { 00249 return osg::BoundingBox( osg::BoundingBoxImpl< VT >::_min, osg::BoundingBoxImpl< VT >::_max ); 00250 } 00251 00252 template< class VT > 00253 inline void WBoundingBoxImpl< VT >::expandBy( const WBoundingBoxImpl< VT > &bb ) 00254 { 00255 osg::BoundingBoxImpl< VT >::expandBy( bb ); 00256 } 00257 00258 template< class VT > 00259 inline bool WBoundingBoxImpl< VT >::intersects( const WBoundingBoxImpl< VT > &bb ) const 00260 { 00261 return osg::BoundingBoxImpl< VT >::intersects( bb ); 00262 } 00263 00264 template< class VT > 00265 inline double WBoundingBoxImpl< VT >::intervalDistance( double a0, double a1, double b0, double b1 ) const 00266 { 00267 if( a1 < b0 ) 00268 { 00269 return b0 - a1; 00270 } 00271 else if( b1 < a0 ) 00272 { 00273 return a0 - b1; 00274 } 00275 return 0.0; 00276 } 00277 00278 template< class VT > 00279 inline typename WBoundingBoxImpl< VT >::value_type WBoundingBoxImpl< VT >::minDistance( const WBoundingBoxImpl< VT > &bb ) const 00280 { 00281 // test if they are valid 00282 if( !valid() || !bb.valid() ) 00283 { 00284 throw WInvalidBoundingBox( "One of the both bounding boxes inside minDistance computation is not valid." ); 00285 } 00286 00287 double dx = intervalDistance( xMin(), xMax(), bb.xMin(), bb.xMax() ); 00288 double dy = intervalDistance( yMin(), yMax(), bb.yMin(), bb.yMax() ); 00289 double dz = intervalDistance( zMin(), zMax(), bb.zMin(), bb.zMax() ); 00290 if( dx == 0.0 && dy == 0.0 && dz == 0.0 ) 00291 { 00292 return 0.0; 00293 } 00294 return std::sqrt( dx * dx + dy * dy + dz * dz ); 00295 } 00296 00297 /** 00298 * Output operator for the WBoundingBoxImpl class. 00299 * 00300 * \param out Output stream operator 00301 * \param bb The box which should be streamed out 00302 * 00303 * \return reference to the output stream 00304 */ 00305 template< class VT > 00306 inline std::ostream& operator<<( std::ostream& out, const WBoundingBoxImpl< VT >& bb ) 00307 { 00308 out << std::scientific << std::setprecision( 16 ); 00309 out << "AABB( min: " << bb.xMin() << ", " << bb.yMin() << ", " << bb.zMin(); 00310 out << " max: " << bb.xMax() << ", " << bb.yMax() << ", " << bb.zMax() << " )"; 00311 return out; 00312 } 00313 00314 template< class VT > 00315 inline const typename WBoundingBoxImpl< VT >::vec_type& WBoundingBoxImpl< VT >::getMin() const 00316 { 00317 return osg::BoundingBoxImpl< VT >::_min; 00318 } 00319 00320 template< class VT > 00321 inline const typename WBoundingBoxImpl< VT >::vec_type& WBoundingBoxImpl< VT >::getMax() const 00322 { 00323 return osg::BoundingBoxImpl< VT >::_max; 00324 } 00325 00326 typedef WBoundingBoxImpl< osg::Vec3 > WBoundingBox; 00327 00328 #endif // WBOUNDINGBOX_H