//////////////////////////////////////////////////////////////////// // AABB.inl // // Copyright 2007 cDc@seacave // Distributed under the Boost Software License, Version 1.0 // (See http://www.boost.org/LICENSE_1_0.txt) // D E F I N E S /////////////////////////////////////////////////// // S T R U C T S /////////////////////////////////////////////////// template inline TAABB::TAABB(bool) : ptMin(POINT::Constant(std::numeric_limits::max())), ptMax(POINT::Constant(std::numeric_limits::lowest())) { } template inline TAABB::TAABB(const POINT& _pt) : ptMin(_pt), ptMax(_pt) { } template inline TAABB::TAABB(const POINT& _ptMin, const POINT& _ptMax) : ptMin(_ptMin), ptMax(_ptMax) { } template inline TAABB::TAABB(const POINT& center, const TYPE& radius) : ptMin(center-POINT::Constant(radius)), ptMax(center+POINT::Constant(radius)) { } template template inline TAABB::TAABB(const TPoint* pts, size_t n) { Set(pts, n); } // constructor template template inline TAABB::TAABB(const TAABB& rhs) : ptMin(rhs.ptMin.template cast()), ptMax(rhs.ptMax.template cast()) { } // copy constructor /*----------------------------------------------------------------*/ template inline void TAABB::Reset() { ptMin = POINT::Constant(std::numeric_limits::max()); ptMax = POINT::Constant(std::numeric_limits::lowest()); } template inline void TAABB::Set(const POINT& _pt) { ptMin = ptMax = _pt; } template inline void TAABB::Set(const POINT& _ptMin, const POINT& _ptMax) { ptMin = _ptMin; ptMax = _ptMax; } template inline void TAABB::Set(const POINT& center, const TYPE& radius) { ptMin = center-POINT::Constant(radius); ptMax = center+POINT::Constant(radius); } template template inline void TAABB::Set(const TPoint* pts, size_t n) { ASSERT(n > 0); ptMin = ptMax = pts[0]; for (size_t i=1; i inline bool TAABB::IsEmpty() const { for (int i=0; i= ptMax[i]) return true; return false; } // IsEmpty /*----------------------------------------------------------------*/ template inline TAABB& TAABB::Enlarge(TYPE x) { ptMin.array() -= x; ptMax.array() += x; return *this; } template inline TAABB& TAABB::EnlargePercent(TYPE x) { const POINT ptSizeDelta(GetSize() * (x - TYPE(1)) / TYPE(2)); ptMin -= ptSizeDelta; ptMax += ptSizeDelta; return *this; } // Enlarge /*----------------------------------------------------------------*/ template inline typename TAABB::POINT TAABB::GetCenter() const { return (ptMax + ptMin) * TYPE(0.5); } template inline void TAABB::GetCenter(POINT& ptCenter) const { ptCenter = (ptMax + ptMin) * TYPE(0.5); } // GetCenter /*----------------------------------------------------------------*/ template inline typename TAABB::POINT TAABB::GetSize() const { return ptMax - ptMin; } template inline void TAABB::GetSize(POINT& ptSize) const { ptSize = ptMax - ptMin; } // GetSize /*----------------------------------------------------------------*/ template inline void TAABB::GetCorner(BYTE i, POINT& ptCorner) const { ASSERT(i inline typename TAABB::POINT TAABB::GetCorner(BYTE i) const { POINT ptCorner; GetCorner(i, ptCorner); return ptCorner; } // GetCorner template inline void TAABB::GetCorners(POINT pts[numCorners]) const { for (BYTE i=0; i inline void TAABB::Translate(const POINT& d) { ptMin += d; ptMax += d; } /*----------------------------------------------------------------*/ // Update the box by the given transform. template inline void TAABB::Transform(const MATRIX& m) { ptMin = m * ptMin; ptMax = m * ptMax; } /*----------------------------------------------------------------*/ // Update the box such that it contains the given point. template void TAABB::InsertFull(const POINT& pt) { if (ptMin[0] > pt[0]) ptMin[0] = pt[0]; if (ptMax[0] < pt[0]) ptMax[0] = pt[0]; if (DIMS > 1) { if (ptMin[1] > pt[1]) ptMin[1] = pt[1]; if (ptMax[1] < pt[1]) ptMax[1] = pt[1]; } if (DIMS > 2) { if (ptMin[2] > pt[2]) ptMin[2] = pt[2]; if (ptMax[2] < pt[2]) ptMax[2] = pt[2]; } } // same as above, but for the initialized case template void TAABB::Insert(const POINT& pt) { if (ptMin[0] > pt[0]) ptMin[0] = pt[0]; else if (ptMax[0] < pt[0]) ptMax[0] = pt[0]; if (DIMS > 1) { if (ptMin[1] > pt[1]) ptMin[1] = pt[1]; else if (ptMax[1] < pt[1]) ptMax[1] = pt[1]; } if (DIMS > 2) { if (ptMin[2] > pt[2]) ptMin[2] = pt[2]; else if (ptMax[2] < pt[2]) ptMax[2] = pt[2]; } } /*----------------------------------------------------------------*/ // Update the box such that it contains the given bounding box. template void TAABB::Insert(const TAABB& aabb) { if (ptMin[0] > aabb.ptMin[0]) ptMin[0] = aabb.ptMin[0]; if (ptMax[0] < aabb.ptMax[0]) ptMax[0] = aabb.ptMax[0]; if (DIMS > 1) { if (ptMin[1] > aabb.ptMin[1]) ptMin[1] = aabb.ptMin[1]; if (ptMax[1] < aabb.ptMax[1]) ptMax[1] = aabb.ptMax[1]; } if (DIMS > 2) { if (ptMin[2] > aabb.ptMin[2]) ptMin[2] = aabb.ptMin[2]; if (ptMax[2] < aabb.ptMax[2]) ptMax[2] = aabb.ptMax[2]; } } /*----------------------------------------------------------------*/ // Update the box such that it does not exceed the given bounding box. template void TAABB::BoundBy(const TAABB& aabb) { if (ptMin[0] < aabb.ptMin[0]) ptMin[0] = aabb.ptMin[0]; if (ptMax[0] > aabb.ptMax[0]) ptMax[0] = aabb.ptMax[0]; if (DIMS > 1) { if (ptMin[1] < aabb.ptMin[1]) ptMin[1] = aabb.ptMin[1]; if (ptMax[1] > aabb.ptMax[1]) ptMax[1] = aabb.ptMax[1]; } if (DIMS > 2) { if (ptMin[2] < aabb.ptMin[2]) ptMin[2] = aabb.ptMin[2]; if (ptMax[2] > aabb.ptMax[2]) ptMax[2] = aabb.ptMax[2]; } } /*----------------------------------------------------------------*/ // intersection between two AABBs template bool TAABB::Intersects(const TAABB& aabb) const { if (aabb.ptMax[0] < ptMin[0]) return false; if (aabb.ptMin[0] >= ptMax[0]) return false; if (DIMS > 1) { if (aabb.ptMax[1] < ptMin[1]) return false; if (aabb.ptMin[1] >= ptMax[1]) return false; } if (DIMS > 2) { if (aabb.ptMax[2] < ptMin[2]) return false; if (aabb.ptMin[2] >= ptMax[2]) return false; } return true; } template bool TAABB::IntersectsComplete(const TAABB& aabb, TYPE tolerance) const { if (aabb.ptMax[0]+tolerance < ptMin[0]) return false; if (aabb.ptMin[0] > ptMax[0]+tolerance) return false; if (DIMS > 1) { if (aabb.ptMax[1]+tolerance < ptMin[1]) return false; if (aabb.ptMin[1] > ptMax[1]+tolerance) return false; } if (DIMS > 2) { if (aabb.ptMax[2]+tolerance < ptMin[2]) return false; if (aabb.ptMin[2] > ptMax[2]+tolerance) return false; } return true; } template bool TAABB::IntersectsComplete(const TAABB& aabb) const { return IntersectsComplete(aabb, ZEROTOLERANCE()); } // Intersects(TAABB) /*----------------------------------------------------------------*/ // does TAABB contain the given point template bool TAABB::Intersects(const POINT& pt) const { if (pt[0] < ptMin[0]) return false; if (pt[0] >= ptMax[0]) return false; if (DIMS > 1) { if (pt[1] < ptMin[1]) return false; if (pt[1] >= ptMax[1]) return false; } if (DIMS > 2) { if (pt[2] < ptMin[2]) return false; if (pt[2] >= ptMax[2]) return false; } return true; } template bool TAABB::IntersectsComplete(const POINT& pt, TYPE tolerance) const { if (pt[0]+tolerance < ptMin[0]) return false; if (pt[0] > ptMax[0]+tolerance) return false; if (DIMS > 1) { if (pt[1]+tolerance < ptMin[1]) return false; if (pt[1] > ptMax[1]+tolerance) return false; } if (DIMS > 2) { if (pt[2]+tolerance < ptMin[2]) return false; if (pt[2] > ptMax[2]+tolerance) return false; } return true; } template bool TAABB::IntersectsComplete(const POINT& pt) const { return IntersectsComplete(pt, ZEROTOLERANCE()); } // Intersects(point) /*----------------------------------------------------------------*/ // split this TAABB by the given axis // returns number of children (0 or 2) template unsigned TAABB::SplitBy(TYPE d, int a, TAABB child[2]) const { ASSERT(a < DIMS); if (d >= ptMin[a] && d < ptMax[a]) { TAABB& child0 = child[0]; child0.Set(ptMin, ptMax); TAABB& child1 = child[1]; child1.Set(ptMin, ptMax); child0.ptMax[a] = child1.ptMin[a] = d; return 2; } return 0; } // SplitBy(axis) /*----------------------------------------------------------------*/ // split this TAABB by the given point // returns number of children (0 - numScalar) // idxFirst returns the index of the first aabb template unsigned TAABB::SplitBy(const POINT& pt, TAABB child[numChildren], unsigned& idxFirst) const { idxFirst = 0; unsigned size; int a = 0; do { size = SplitBy(pt[a], a, child); if (++a == DIMS) return size; } while (size == 0); do { unsigned n = 0; for (unsigned b=0; b