/*
 *  BoundingBox.hpp
 *
 *  Created by Thant on 10/19/2011
 *  Copyright 2011 TeleNav Inc. All rights reserved.
 *
 *  Implements axis-aligned bounding boxes.
 *
 */

#ifndef Foundation_Math_BoundingBox_INCLUDED
#define Foundation_Math_BoundingBox_INCLUDED

#include <assert.h>
#include <foundation/Math/Point.hpp>
#include <foundation/Math/Vec.hpp>

namespace Tn {

namespace math {

template <typename T>
struct BoundingBox
{
    BoundingBox(Point<3,T> const & center, T width, T height, T depth);
    BoundingBox(Point<3,T> const & lower_left_far, Point<3,T> const & upper_right_near);

    Point<3,T> center;
    Vec<3,T> dim;

    // [0-7] eight corners
    Point<3,T> corner(int i) const;
};


typedef BoundingBox<float> BoundingBoxf;
typedef BoundingBox<double> BoundingBoxd;


template <typename T>
BoundingBox<T>::BoundingBox(Point<3,T> const & center_, T width, T height, T depth) :
    center(center_)
{
    dim[0] = width;
    dim[1] = height;
    dim[2] = depth;
}


template <typename T>
BoundingBox<T>::BoundingBox(Point<3,T> const & llf, Point<3,T> const & urn)
    : center(Point3<T>((llf[0]+urn[0])/T(2),
                       (llf[1]+urn[1])/T(2),
                       (llf[2]+urn[2])/T(2)))
{
    T width  = urn[0] - llf[0];
    T height = urn[1] - llf[1];
    T depth  = urn[2] - llf[2];

    dim[0] = width;
    dim[1] = height;
    dim[2] = depth;
}


template <typename T>
Point<3,T> BoundingBox<T>::corner(int i) const
{
    assert((i>=0) && (i<8));

    T x = ((i & (0x1 << 0)) ? dim[0] : -dim[0])/T(2);
    T y = ((i & (0x1 << 1)) ? dim[1] : -dim[1])/T(2);
    T z = ((i & (0x1 << 2)) ? dim[2] : -dim[2])/T(2);

    return center + Vec3<T>(x, y, z);
}


template <typename T>
bool collide(BoundingBox<T> const & a, BoundingBox<T> const & b)
{
    return 
        (tnabs(a.center[0] - b.center[0]) < ((a.dim[0] + b.dim[0]) / T(2))) &&
        (tnabs(a.center[1] - b.center[1]) < ((a.dim[1] + b.dim[1]) / T(2))) &&
        (tnabs(a.center[2] - b.center[2]) < ((a.dim[2] + b.dim[2]) / T(2)));
}

} // namespace Tn

} // namespace math

#endif

