Files
ViewDesignEngine/include/vde/core/aabb.h
T

136 lines
3.5 KiB
C++
Raw Normal View History

#pragma once
#include "vde/core/point.h"
#include <algorithm>
#include <limits>
namespace vde::core {
/**
* @brief 轴对齐包围盒(AABB
*
* 用最小/最大两个角点表示的三维轴对齐包围盒。
* 支持增量扩展、包含/相交测试、几何属性查询。
*
* @tparam T 标量类型(通常为 double 或 float
*
* @note 初始状态为空(min = +∞, max = -∞),需要通过 expand() 初始化
*
* @ingroup core
*/
template <typename T>
class AABB {
public:
/**
* @brief 构造空包围盒
*
* min 初始化为 T 最大值,max 初始化为 T 最小值,
* 表示"无内容"的空状态。
*/
AABB() : min_(Point3D::Constant(std::numeric_limits<T>::max())),
max_(Point3D::Constant(std::numeric_limits<T>::lowest())) {}
/**
* @brief 从两个角点构造包围盒
*
* @param min 最小角点
* @param max 最大角点
*
* @pre min 的各分量 ≤ max 的各分量
*/
AABB(const Point3D& min, const Point3D& max) : min_(min), max_(max) {}
/**
* @brief 扩展包围盒以包含给定点
*
* 逐分量取 min/max,保证包围盒包含该点。
* 若包围盒为空,此调用等效于初始化为包含该点的退化盒。
*
* @param p 要包含的点
*
* @code{.cpp}
* AABB3D box;
* for (auto& p : points) box.expand(p);
* @endcode
*/
void expand(const Point3D& p) {
min_ = min_.cwiseMin(p);
max_ = max_.cwiseMax(p);
}
/**
* @brief 扩展包围盒以包含另一个 AABB
*
* @param other 另一个包围盒
*/
void expand(const AABB& other) {
min_ = min_.cwiseMin(other.min_);
max_ = max_.cwiseMax(other.max_);
}
/**
* @brief 包围盒中心点
* @return (min + max) / 2
*/
[[nodiscard]] Point3D center() const { return (min_ + max_) * 0.5; }
/**
* @brief 包围盒对角线向量(从 min 到 max)
* @return max - min
*/
[[nodiscard]] Vector3D extent() const { return max_ - min_; }
/**
* @brief 包围盒表面积
* @return 2 * (dx*dy + dy*dz + dz*dx)
*/
[[nodiscard]] T surface_area() const {
Vector3D e = extent();
return 2.0 * (e.x() * e.y() + e.y() * e.z() + e.z() * e.x());
}
/**
* @brief 包围盒体积
* @return dx * dy * dz
*/
[[nodiscard]] T volume() const {
Vector3D e = extent();
return e.x() * e.y() * e.z();
}
/**
* @brief 测试点是否在包围盒内部(含边界)
*
* @param p 测试点
* @return true 若 min ≤ p ≤ max(各分量)
*/
[[nodiscard]] bool contains(const Point3D& p) const {
return (p.array() >= min_.array()).all() && (p.array() <= max_.array()).all();
}
/**
* @brief 测试两个包围盒是否相交(含边界接触)
*
* @param other 另一个包围盒
* @return true 若存在交集
*/
[[nodiscard]] bool intersects(const AABB& other) const {
return (min_.array() <= other.max_.array()).all()
&& (max_.array() >= other.min_.array()).all();
}
/// 获取最小角点
[[nodiscard]] const Point3D& min() const { return min_; }
/// 获取最大角点
[[nodiscard]] const Point3D& max() const { return max_; }
private:
Point3D min_, max_;
};
/// 双精度三维包围盒
using AABB3D = AABB<double>;
/// 单精度三维包围盒
using AABB3f = AABB<float>;
} // namespace vde::core