#pragma once /** * @file ffd_deformation.h * @brief Freeform Deformation (FFD) — 自由变形 * * FFD 是一种基于控制格 (lattice) 的体积变形技术,可以将任意 * B-Rep 实体或网格进行拉伸、压缩、扭转等自由变形,保持拓扑不变。 * * ## 核心概念 * * - **FFD Lattice**: nx×ny×nz 的 Bézier 体积控制点网格。 * - **参数空间映射**: 将世界坐标点映射到 lattice 的 (s,t,u) 参数空间。 * - **Bernstein 多项式**: 用 Bernstein 基函数计算变形后的位置。 * * ## FFD 类型 * * | 类型 | 描述 | * |--------------|----------------------------------------| * | Lattice-based | 规则矩形网格,参数空间 [0,1]³ | * | Cage-based | 任意包围多面体,自动生成 lattice 控制点 | * * ## 使用示例 * * @code{.cpp} * auto box = make_box(10, 5, 3); * auto bbox = box.bounds(); * auto lattice = create_lattice(bbox, 3, 3, 3); // 3×3×3 控制点 * * // 拉伸:移动顶面控制点 * std::vector displacements(27); * for (int i = 0; i < 3; ++i) * for (int j = 0; j < 3; ++j) * displacements[i*9 + j*3 + 2] = Vector3D(0, 0, 3.0); // z方向位移 * * auto deformed = deform_brep(box, lattice, displacements); * @endcode * * @ingroup brep */ #include "vde/core/point.h" #include "vde/core/aabb.h" #include "vde/brep/brep.h" #include "vde/mesh/halfedge_mesh.h" #include namespace vde::brep { using core::Point3D; using core::Vector3D; using core::AABB3D; // ═══════════════════════════════════════════════ // FFD Lattice // ═══════════════════════════════════════════════ /** * @brief FFD 控制格结构 * * 一个 nx×ny×nz 的 Bézier 体积控制点网格。 * 控制点存储在 control_points 中,按 k-major、j-major、i-minor 排列: * index = (k * ny + j) * nx + i * * bbox 定义了 lattice 在世界空间中的边界,用于世界坐标 → 参数空间的映射。 */ struct FFDLattice { int nx = 0; ///< X 方向控制点数 int ny = 0; ///< Y 方向控制点数 int nz = 0; ///< Z 方向控制点数 std::vector control_points; ///< 控制点坐标 [nx*ny*nz] AABB3D bbox; ///< 世界空间包围盒 /** * @brief 总控制点数 */ [[nodiscard]] size_t num_points() const { return control_points.size(); } /** * @brief 获取控制点 * @param i X 索引 (0..nx-1) * @param j Y 索引 (0..ny-1) * @param k Z 索引 (0..nz-1) */ [[nodiscard]] const Point3D& control_point(int i, int j, int k) const { return control_points[(k * ny + j) * nx + i]; } /** @brief 检查 lattice 是否有效 */ [[nodiscard]] bool is_valid() const { return nx >= 2 && ny >= 2 && nz >= 2 && control_points.size() == static_cast(nx * ny * nz); } }; /** * @brief 创建规则格子 lattice * * 在给定包围盒内生成 nx×ny×nz 均匀分布的控制点网格。 * * @param bbox 世界空间包围盒 * @param nx X 方向控制点数(≥ 2) * @param ny Y 方向控制点数(≥ 2) * @param nz Z 方向控制点数(≥ 2) * @return FFDLattice 均匀控制格 */ [[nodiscard]] FFDLattice create_lattice(const AABB3D& bbox, int nx, int ny, int nz); /** * @brief 从包围多面体生成 lattice (Cage-based FFD) * * 从一组顶点(包围多面体/cage 的顶点)计算包围盒, * 生成 resolution 大小的均匀控制格。 * * @param cage_vertices 包围多面体的顶点坐标 * @param nx X 方向分辨率(≥ 2) * @param ny Y 方向分辨率(≥ 2) * @param nz Z 方向分辨率(≥ 2) * @return FFDLattice 包围多面体的控制格 */ [[nodiscard]] FFDLattice create_cage_lattice(const std::vector& cage_vertices, int nx, int ny, int nz); // ═══════════════════════════════════════════════ // Deformation API // ═══════════════════════════════════════════════ /** * @brief 对 B-Rep 实体进行 FFD 变形 * * 将 B-Rep 的所有顶点映射到 lattice 参数空间,使用 Bernstein 多项式 * 计算变形后的位置。拓扑结构和面/边/壳关系保持不变。 * * 算法: * 1. 复制 BrepModel(保留拓扑结构) * 2. 对每个顶点: * a. 映射世界坐标到 lattice 参数空间 (s,t,u) ∈ [0,1]³ * b. 用 Bernstein 基函数求值,计算变形位移 * c. 应用位移到顶点位置 * 3. 返回变形后的 BrepModel * * @param body 输入 B-Rep 实体 * @param lattice FFD 控制格 * @param displacements 每个控制点的位移向量 [nx*ny*nz] * @return 变形后的 B-Rep 实体(拓扑不变) * * @pre displacements.size() == lattice.num_points() * @pre lattice.is_valid() */ [[nodiscard]] BrepModel deform_brep(const BrepModel& body, const FFDLattice& lattice, const std::vector& displacements); /** * @brief 对三角网格进行 FFD 变形 * * 将网格的所有顶点映射到 lattice 参数空间,用 Bernstein 多项式 * 计算变形后的新位置。 * * @param mesh 输入三角网格 * @param lattice FFD 控制格 * @param displacements 每个控制点的位移向量 [nx*ny*nz] * @return 变形后的网格(拓扑不变) * * @pre displacements.size() == lattice.num_points() * @pre lattice.is_valid() */ [[nodiscard]] mesh::HalfedgeMesh deform_mesh(const mesh::HalfedgeMesh& mesh, const FFDLattice& lattice, const std::vector& displacements); // ═══════════════════════════════════════════════ // Internal: Bernstein evaluation // ═══════════════════════════════════════════════ /** * @brief Bernstein 基函数 B_{i,n}(t) * * B_{i,n}(t) = C(n,i) * t^i * (1-t)^{n-i} * * @param i 基函数索引 (0..n) * @param n 多项式阶数 * @param t 参数值 ∈ [0,1] * @return 基函数值 */ [[nodiscard]] double bernstein(int i, int n, double t); /** * @brief 用 FFD lattice 对单个点进行变形计算 * * 将世界坐标点映射到 lattice 参数空间,计算变形位移并应用。 * * @param point 输入世界坐标点 * @param lattice FFD 控制格 * @param displacements 控制点位移向量 * @return 变形后的点坐标 */ [[nodiscard]] Point3D deform_point(const Point3D& point, const FFDLattice& lattice, const std::vector& displacements); } // namespace vde::brep