WBoundingBox.h 9.54 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------

#ifndef WBOUNDINGBOX_H
#define WBOUNDINGBOX_H

28
#include <ostream>
29
#include <iomanip> // for setprecision
30
#include <cmath>   // std::sqrt
31

32 33
#include <osg/BoundingBox>

34
#include "exceptions/WInvalidBoundingBox.h"
35
//#include "math/linearAlgebra/WLinearAlgebra.h"
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

/**
 * Represents a \e axis \e parallel bounding box and provides some useful operations with them.
 *
 * \note Reason for subclassing: We don't want \c _min and \c _max member variables to be public.
 * \note Reason for not having a \e private osg::BoundingBox member is, we don't have to wrap many
 * member functions and can make use of the using directive. A downside on this is, we cannot
 * automatical cast to osg::BoundingBox even if we provide a cast operator! Hence when we need this
 * we will provide a toOsgBB() member function.
 */
template< class VT >
class WBoundingBoxImpl : private osg::BoundingBoxImpl< VT >
{
public:
    /**
     * Vertex type for min and max positions of this box.
     */
    typedef typename osg::BoundingBoxImpl< VT >::vec_type vec_type;

    /**
     * Value type of the vertex type for example double, float, etc.
     */
    typedef typename osg::BoundingBoxImpl< VT >::value_type value_type;

    /**
     * Default constructor.
     */
    WBoundingBoxImpl();

    /**
     * Wrapps the component wise bounding box constructor from osg::BoundingBox.
     *
     * \param xmin Minimal x coordinate
     * \param ymin Minimal y coordinate
     * \param zmin Minimal z coordinate
     * \param xmax Maximal x coordinate
     * \param ymax Maximal y coordinate
     * \param zmax Maximal z coordinate
     */
    WBoundingBoxImpl( value_type xmin, value_type ymin, value_type zmin, value_type xmax, value_type ymax, value_type zmax );

    /**
     * Constructs a bounding box by min and max positions.
     *
     * \param min Position containing minx miny and minz coordinates.
     * \param max Position containing maxx maxy and maxz coordinates.
     */
    WBoundingBoxImpl( const vec_type& min, const vec_type& max );

85 86 87 88 89
    /**
     * Create BoundinmgBox using a given sphere.
     *
     * \param bs the sphere
     */
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
90
    explicit WBoundingBoxImpl( const osg::BoundingSphereImpl< VT >& bs );
91

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
    /**
     * Destructs this instance.
     */
    virtual ~WBoundingBoxImpl();

    /**
     * Resets this box to an initial state where max is FLT_MIN and min FLT_MAX.
     *
     * \note This is a wrapper call to osg::BoundingBoxImpl< VT >::init()
     */
    void reset();

    using osg::BoundingBoxImpl< VT >::valid;
    using osg::BoundingBoxImpl< VT >::set;
    using osg::BoundingBoxImpl< VT >::xMin;
    using osg::BoundingBoxImpl< VT >::yMin;
    using osg::BoundingBoxImpl< VT >::zMin;
    using osg::BoundingBoxImpl< VT >::xMax;
    using osg::BoundingBoxImpl< VT >::yMax;
    using osg::BoundingBoxImpl< VT >::zMax;
    using osg::BoundingBoxImpl< VT >::center;
    using osg::BoundingBoxImpl< VT >::radius;

    /**
     * Calculates and returns the squared length of the bounding box radius.
     *
     * \note This is a wrapper call to osg::BoundingBoxImpl< VT >::radius2()
119 120
     *
     * \return squared bbox radius
121 122 123 124 125 126
     */
    value_type radiusSquare() const;

    using osg::BoundingBoxImpl< VT >::corner;

    /**
127
     * Explicit type conversion function to use a WBoundingBox as osg::BoundingBox.
128
     *
129
     * \return A copy of this bounding box as osg::BoundingBox.
130
     */
131
    osg::BoundingBox toOSGBB() const;
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161

    using osg::BoundingBoxImpl< VT >::expandBy;

    /**
     * Expands this bounding box to include the given bounding box.
     *
     * \param bb The other bounding box.
     */
    void expandBy( const WBoundingBoxImpl< VT > &bb );

    /**
     * Checks for intersection of this bounding box with the specified bounding box.
     *
     * \param bb The other bouding box to tetst with.
     *
     * \return True if they intersect, false otherwise.
     */
    bool intersects( const WBoundingBoxImpl< VT > &bb ) const;

    /**
     * Computes the minimal distance of tow axis parallel bounding boxes.
     *
     * \param bb The other bounding box.
     *
     * \return Zero if they intersect, otherwise their minimal distance.
     */
    value_type minDistance( const WBoundingBoxImpl< VT > &bb ) const;

    using osg::BoundingBoxImpl< VT >::contains;

162 163 164 165 166 167 168 169 170 171 172 173 174
    /**
     * Gives the front lower left aka minimum corner.
     *
     * \return Minimum corner.
     */
    const vec_type& getMin() const;

    /**
     * Gives the back upper right aka maximum corner.
     *
     * \return Maximum corner.
     */
    const vec_type& getMax() const;
175

176 177
protected:
private:
178 179 180 181 182 183 184 185 186 187 188
    /**
     * Checks if the two given intervals intersect and computes the distance between them.
     *
     * \param a0 lower bound of the first interval
     * \param a1 upper bound of the first interval
     * \param b0 lower bound of the second interval
     * \param b1 upper bound if the second interval
     *
     * \return The distance between those intervals if they don't overlap, zero otherwise
     */
    double intervalDistance( double a0, double a1, double b0, double b1 ) const;
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
};

template< class VT >
inline WBoundingBoxImpl< VT >::WBoundingBoxImpl()
    : osg::BoundingBoxImpl< VT >()
{
}

template< class VT >
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
    : osg::BoundingBoxImpl< VT >( xmin, ymin, zmin, xmax, ymax, zmax )
{
}

template< class VT >
inline WBoundingBoxImpl< VT >::WBoundingBoxImpl( const vec_type& min, const vec_type& max )
    : osg::BoundingBoxImpl< VT >( min, max )
{
}

209 210 211 212 213 214 215
template< class VT >
inline WBoundingBoxImpl< VT >::WBoundingBoxImpl( const osg::BoundingSphereImpl< VT >& bs )
    : osg::BoundingBoxImpl< VT >( bs.center() - VT( bs.radius(), bs.radius(), bs.radius() ) ,
                                  bs.center() + VT( bs.radius(), bs.radius(), bs.radius() ) )
{
}

216 217 218 219 220 221 222 223 224 225 226 227 228 229
template< class VT >
inline WBoundingBoxImpl< VT >::~WBoundingBoxImpl()
{
}

template< class VT >
inline void WBoundingBoxImpl< VT >::reset()
{
    this->init();
}

template< class VT >
inline typename WBoundingBoxImpl< VT >::value_type WBoundingBoxImpl< VT >::radiusSquare() const
{
230
    return this->radius2();
231 232 233
}

template< class VT >
234
inline osg::BoundingBox WBoundingBoxImpl< VT >::toOSGBB() const
235
{
236
    return osg::BoundingBox( osg::BoundingBoxImpl< VT >::_min, osg::BoundingBoxImpl< VT >::_max );
237 238 239 240 241 242 243 244 245 246 247 248 249 250
}

template< class VT >
inline void WBoundingBoxImpl< VT >::expandBy( const WBoundingBoxImpl< VT > &bb )
{
    osg::BoundingBoxImpl< VT >::expandBy( bb );
}

template< class VT >
inline bool WBoundingBoxImpl< VT >::intersects( const WBoundingBoxImpl< VT > &bb ) const
{
    return osg::BoundingBoxImpl< VT >::intersects( bb );
}

251 252
template< class VT >
inline double WBoundingBoxImpl< VT >::intervalDistance( double a0, double a1, double b0, double b1 ) const
253
{
254
    if( a1 < b0 )
255
    {
256 257 258 259 260
        return b0 - a1;
    }
    else if( b1 < a0 )
    {
        return a0 - b1;
261
    }
262
    return 0.0;
263 264
}

265 266 267
template< class VT >
inline typename WBoundingBoxImpl< VT >::value_type WBoundingBoxImpl< VT >::minDistance( const WBoundingBoxImpl< VT > &bb ) const
{
268 269 270 271 272
    // test if they are valid
    if( !valid() || !bb.valid() )
    {
        throw WInvalidBoundingBox( "One of the both bounding boxes inside minDistance computation is not valid." );
    }
273

274 275 276 277 278 279 280 281
    double dx = intervalDistance( xMin(), xMax(), bb.xMin(), bb.xMax() );
    double dy = intervalDistance( yMin(), yMax(), bb.yMin(), bb.yMax() );
    double dz = intervalDistance( zMin(), zMax(), bb.zMin(), bb.zMax() );
    if( dx == 0.0 && dy == 0.0 && dz == 0.0 )
    {
        return 0.0;
    }
    return std::sqrt( dx * dx + dy * dy + dz * dz );
282 283
}

284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
/**
 * Output operator for the WBoundingBoxImpl class.
 *
 * \param out Output stream operator
 * \param bb The box which should be streamed out
 *
 * \return reference to the output stream
 */
template< class VT >
inline std::ostream& operator<<( std::ostream& out, const WBoundingBoxImpl< VT >& bb )
{
    out << std::scientific << std::setprecision( 16 );
    out << "AABB( min: " << bb.xMin() << ", " << bb.yMin() << ", " << bb.zMin();
    out << " max: " << bb.xMax() << ", " << bb.yMax() << ", " << bb.zMax() << " )";
    return out;
}

301 302 303 304 305 306 307 308 309 310 311 312
template< class VT >
inline const typename WBoundingBoxImpl< VT >::vec_type& WBoundingBoxImpl< VT >::getMin() const
{
    return  osg::BoundingBoxImpl< VT >::_min;
}

template< class VT >
inline const typename WBoundingBoxImpl< VT >::vec_type& WBoundingBoxImpl< VT >::getMax() const
{
    return  osg::BoundingBoxImpl< VT >::_max;
}

313
typedef WBoundingBoxImpl< osg::Vec3 > WBoundingBox;
314 315

#endif  // WBOUNDINGBOX_H