Skip to content

Instantly share code, notes, and snippets.

@vittorioromeo
Created December 31, 2013 18:03
Show Gist options
  • Save vittorioromeo/8200297 to your computer and use it in GitHub Desktop.
Save vittorioromeo/8200297 to your computer and use it in GitHub Desktop.
template<typename T> class AABBImpl
{
public:
using VecT = Vec2<T>;
private:
VecT position, halfSize;
public:
struct TagFromPosition { };
struct TagFromHalfSize { };
struct TagFromSize { };
struct TagFromPositionAndHalfSize { };
struct TagFromPositionAndSize { };
struct TagFromMinMax { };
struct TagFromLeftRightTopBottom { };
inline AABBImpl() = default;
inline AABBImpl(TagFromPosition, const VecT& mPosition) noexcept : position{mPosition} { }
inline AABBImpl(TagFromHalfSize, const VecT& mHalfSize) noexcept : halfSize{mHalfSize} { }
inline AABBImpl(TagFromSize, const VecT& mSize) noexcept : AABBImpl{TagFromHalfSize{}, mSize / T(2)} { }
inline AABBImpl(TagFromPositionAndHalfSize, const VecT& mPosition, const VecT& mHalfSize) noexcept : position{mPosition}, halfSize{mHalfSize} { }
inline AABBImpl(TagFromPositionAndSize, const VecT& mPosition, const VecT& mSize) noexcept : AABBImpl{TagFromPositionAndHalfSize{}, mPosition, mSize / T(2)} { }
inline AABBImpl(TagFromMinMax, const VecT& mMin, const VecT& mMax) noexcept : AABBImpl{TagFromPositionAndHalfSize{}, ssvs::getCenter(mMin, mMax), ssvs::getHalfSize(mMin, mMax)} { }
inline AABBImpl(TagFromLeftRightTopBottom, T mLeft, T mRight, T mTop, T mBottom) noexcept : AABBImpl{TagFromMinMax{}, VecT{mLeft, mTop}, VecT{mRight, mBottom}} { }
inline void setPosition(const VecT& mPosition) noexcept { position = mPosition; }
inline void setX(T mX) noexcept { position.x = mX; }
inline void setY(T mY) noexcept { position.y = mY; }
inline void setHalfSize(const VecT& mHalfSize) noexcept { halfSize = mHalfSize; }
inline void setSize(const VecT& mSize) noexcept { halfSize = mSize / 2; }
inline void setWidth(T mWidth) noexcept { halfSize.x = mWidth / 2; }
inline void setHeight(T mHeight) noexcept { halfSize.y = mHeight / 2; }
inline const VecT& getPosition() const noexcept { return position; }
inline T getX() const noexcept { return position.x; }
inline T getY() const noexcept { return position.y; }
inline T getLeft() const noexcept { return position.x - halfSize.x; }
inline T getRight() const noexcept { return position.x + halfSize.x; }
inline T getTop() const noexcept { return position.y - halfSize.y; }
inline T getBottom() const noexcept { return position.y + halfSize.y; }
inline const VecT& getHalfSize() const noexcept { return halfSize; }
inline T getHalfWidth() const noexcept { return halfSize.x; }
inline T getHalfHeight() const noexcept { return halfSize.y; }
inline VecT getSize() const noexcept { return halfSize * T(2); }
inline T getWidth() const noexcept { return halfSize.x * T(2); }
inline T getHeight() const noexcept { return halfSize.y * T(2); }
};
template<typename T = int, template<typename> class TImpl = AABBImpl> struct AABB : public TImpl<T>
{
private:
struct TagFromImpl { };
template<typename... TArgs> inline AABB(TagFromImpl, TArgs&&... mArgs) noexcept : TImpl<T>{std::forward<TArgs>(mArgs)...} { }
template<typename... TArgs> inline static AABB fromImpl(TArgs&&... mArgs) noexcept { return AABB{TagFromImpl{}, std::forward<TArgs>(mArgs)...}; }
public:
using VecT = typename TImpl<T>::VecT;
inline AABB() = default;
inline static AABB fromPosition(const VecT& mPosition) noexcept { return fromImpl(TImpl<T>::TagFromPosition, mPosition); }
inline static AABB fromHalfSize(const VecT& mHalfSize) noexcept { return fromImpl(TImpl<T>::TagFromHalfSize, mHalfSize); }
inline static AABB fromSize(const VecT& mSize) noexcept { return fromImpl(TImpl<T>::TagFromSize, mSize); }
inline static AABB fromPositionAndHalfSize(const VecT& mPosition, const VecT& mHalfSize) noexcept { return fromImpl(TImpl<T>::TagFromPositionAndHalfSize, mPosition, mHalfSize); }
inline static AABB fromPositionAndSize(const VecT& mPosition, const VecT& mSize) noexcept { return fromImpl(TImpl<T>::TagFromPositionAndSize, mPosition, mSize); }
inline static AABB fromMinMax(const VecT& mMin, const VecT& mMax) noexcept { return fromImpl(TImpl<T>::TagFromMinMax, mMin, mMax); }
inline static AABB fromMinMax(T mLeft, T mRight, T mTop, T mBottom) noexcept { return fromImpl(TImpl<T>::TagFromLeftRightTopBottom, mLeft, mRight, mTop, mBottom); }
inline bool operator==(const AABB& mOther) const noexcept { return this->getPosition() == mOther.getPosition() && this->getHalfSize() == mOther.getHalfSize(); }
inline bool operator!=(const AABB& mOther) const noexcept { return !(*this == mOther); }
inline void move(const Vec2i& mOffset) noexcept { this->setPosition(this->getPosition() + mOffset); }
template<typename TT = T> inline Vec2<TT> getVertexNW() const noexcept { return Vec2<TT>(this->getLeft(), this->getTop()); }
template<typename TT = T> inline Vec2<TT> getVertexNE() const noexcept { return Vec2<TT>(this->getRight(), this->getTop()); }
template<typename TT = T> inline Vec2<TT> getVertexSW() const noexcept { return Vec2<TT>(this->getLeft(), this->getBottom()); }
template<typename TT = T> inline Vec2<TT> getVertexSE() const noexcept { return Vec2<TT>(this->getRight(), this->getBottom()); }
template<typename TT = T> inline Segment<TT> getSegmentLeft() const noexcept { return {getVertexNW<TT>(), getVertexSW<TT>()}; }
template<typename TT = T> inline Segment<TT> getSegmentRight() const noexcept { return {getVertexNE<TT>(), getVertexSE<TT>()}; }
template<typename TT = T> inline Segment<TT> getSegmentTop() const noexcept { return {getVertexNW<TT>(), getVertexNE<TT>()}; }
template<typename TT = T> inline Segment<TT> getSegmentBottom() const noexcept { return {getVertexSW<TT>(), getVertexSE<TT>()}; }
template<typename TShape> inline bool isLeftOf(const TShape& mShape) const noexcept { return this->getRight() <= mShape.getLeft(); }
template<typename TShape> inline bool isRightOf(const TShape& mShape) const noexcept { return this->getLeft() >= mShape.getRight(); }
template<typename TShape> inline bool isAbove(const TShape& mShape) const noexcept { return this->getBottom() <= mShape.getTop(); }
template<typename TShape> inline bool isBelow(const TShape& mShape) const noexcept { return this->getTop() >= mShape.getBottom(); }
template<> inline bool isOverlapping(const VecT& mPoint) const noexcept { return mPoint.x >= this->getLeft() && mPoint.x < this->getRight() && mPoint.y >= this->getTop() && mPoint.y < this->getBottom(); }
inline bool isOverlapping(const Segment<T>& mSegment) const noexcept { return Utils::isSegmentInsersecting(mSegment, getSegmentLeft<T>()) || Utils::isSegmentInsersecting(mSegment, getSegmentRight<T>()) || Utils::isSegmentInsersecting(mSegment, getSegmentTop<T>()) || Utils::isSegmentInsersecting(mSegment, getSegmentBottom<T>()); }
inline bool isOverlapping(const AABB& mAABB) const noexcept { return !isLeftOf(mAABB) && !isRightOf(mAABB) && !isAbove(mAABB) && !isBelow(mAABB); }
inline bool contains(const VecT& mPoint) const noexcept { return isOverlapping(mPoint); }
inline bool contains(const Segment<T>& mSegment) const noexcept { return contains(mSegment.start) && contains(mSegment.end); }
inline bool contains(const AABB& mAABB) const noexcept { return mAABB.getLeft() >= this->getLeft() && mAABB.getRight() < this->getRight() && mAABB.getTop() >= this->getTop() && mAABB.getBottom() < this->getBottom(); }
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment