aeb29ab87c
VDE-019 (Fixed): make_box/make_cylinder/make_sphere 添加 Point3D center 参数 VDE-020 (Fixed): 新增 make_cone(r1,r2,height) 和 make_torus(rMajor,rMinor) 基本体 VDE-022 (Partially Fixed): 添加 get_edge_index_by_position / get_face_index_by_position / fillet_by_position / chamfer_by_position VDE-026 (Fixed): Triangle3D 添加 int id 字段,BVH::build() 自动赋值索引,HitResult 添加 tri_index VDE-021/023/024/025 (Acknowledged): mesh→NURBS 转换等复杂几何算法,需求已记录 反馈来自 ViewDesign feat/viewdesign-engine 分支
113 lines
3.1 KiB
C++
113 lines
3.1 KiB
C++
#pragma once
|
||
#include "vde/core/point.h"
|
||
#include <array>
|
||
|
||
namespace vde::core {
|
||
|
||
/**
|
||
* @brief 三维三角形
|
||
*
|
||
* 由三个顶点定义的平面三角形面片。
|
||
* 支持面积、法线、质心、重心坐标包含测试。
|
||
*
|
||
* @tparam T 标量类型(通常为 double)
|
||
*
|
||
* @ingroup core
|
||
*/
|
||
template <typename T>
|
||
class Triangle {
|
||
public:
|
||
/// 默认构造:三个顶点均在原点(退化三角形)
|
||
Triangle() = default;
|
||
|
||
/**
|
||
* @brief 从三个顶点构造三角形
|
||
*
|
||
* @param v0 第一个顶点
|
||
* @param v1 第二个顶点
|
||
* @param v2 第三个顶点
|
||
*/
|
||
Triangle(const Point3D& v0, const Point3D& v1, const Point3D& v2)
|
||
: v_{v0, v1, v2} {}
|
||
|
||
/**
|
||
* @brief 获取第 i 个顶点
|
||
*
|
||
* @param i 顶点索引(0, 1, 2)
|
||
* @return 顶点引用
|
||
*/
|
||
[[nodiscard]] const Point3D& v(int i) const { return v_[i]; }
|
||
|
||
/// 获取所有顶点数组
|
||
[[nodiscard]] const std::array<Point3D, 3>& vertices() const { return v_; }
|
||
|
||
/**
|
||
* @brief 三角形单位法向量
|
||
*
|
||
* 使用 (v1 - v0) × (v2 - v0) 的归一化结果。
|
||
* 依右手定则方向。
|
||
*
|
||
* @return 单位法向量
|
||
*
|
||
* @note 若三角形退化(面积为零),返回零向量
|
||
*/
|
||
[[nodiscard]] Vector3D normal() const {
|
||
return (v_[1] - v_[0]).cross(v_[2] - v_[0]).normalized();
|
||
}
|
||
|
||
/**
|
||
* @brief 三角形面积
|
||
* @return 0.5 * ||(v1 - v0) × (v2 - v0)||
|
||
*/
|
||
[[nodiscard]] T area() const {
|
||
return (v_[1] - v_[0]).cross(v_[2] - v_[0]).norm() * 0.5;
|
||
}
|
||
|
||
/**
|
||
* @brief 三角形质心(几何中心)
|
||
* @return (v0 + v1 + v2) / 3
|
||
*/
|
||
[[nodiscard]] Point3D centroid() const {
|
||
return (v_[0] + v_[1] + v_[2]) / 3.0;
|
||
}
|
||
|
||
/**
|
||
* @brief 重心坐标包含测试
|
||
*
|
||
* 将点 p 正交投影到三角形平面上,计算重心坐标并判断是否在三角形内。
|
||
*
|
||
* @param p 测试点(三维空间中的任意点)
|
||
* @return true 若投影点在三角形内部或边界上
|
||
*
|
||
* @note 该测试等效于三维点在三角形上的包含测试(先投影再测试)
|
||
*
|
||
* @code{.cpp}
|
||
* Triangle3D tri({0,0,0}, {1,0,0}, {0,1,0});
|
||
* bool in1 = tri.contains(Point3D(0.2, 0.2, 0)); // true
|
||
* bool in2 = tri.contains(Point3D(0.2, 0.2, 5)); // true (投影后判断)
|
||
* @endcode
|
||
*/
|
||
[[nodiscard]] bool contains(const Point3D& p) const {
|
||
Vector3D v0 = v_[2] - v_[0], v1 = v_[1] - v_[0], v2 = p - v_[0];
|
||
T d00 = v0.dot(v0), d01 = v0.dot(v1), d11 = v1.dot(v1);
|
||
T d20 = v2.dot(v0), d21 = v2.dot(v1);
|
||
T denom = d00 * d11 - d01 * d01;
|
||
T v = (d11 * d20 - d01 * d21) / denom;
|
||
T w = (d00 * d21 - d01 * d20) / denom;
|
||
return v >= 0 && w >= 0 && v + w <= 1;
|
||
}
|
||
|
||
/// 用户定义的三角形索引(BVH 构建时自动赋值,默认为 -1 表示未设置)
|
||
int id = -1;
|
||
|
||
private:
|
||
std::array<Point3D, 3> v_{};
|
||
};
|
||
|
||
/// 双精度三维三角形
|
||
using Triangle3D = Triangle<double>;
|
||
/// 单精度三维三角形
|
||
using Triangle3f = Triangle<float>;
|
||
|
||
} // namespace vde::core
|