OpenWalnut  1.4.0
WBoundingBox.h
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