Files
ViewDesignEngine/docs/03-详细设计/02-核心算法设计.md
T

142 lines
3.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 核心算法设计
## 目录
1. [Delaunay 三角剖分(2D](#1-delaunay-三角剖分2d)
2. [NURBS 曲线求值](#2-nurbs-曲线求值)
3. [GJK 碰撞检测](#3-gjk-碰撞检测)
4. [网格简化(QEM](#4-网格简化qem)
5. [BVH 构建(SAH](#5-bvh-构建sah)
6. [2D 多边形布尔运算](#6-2d-多边形布尔运算)
---
## 1. Delaunay 三角剖分(2D
**算法**Bowyer-Watson 增量算法
**复杂度**O(n log n) 期望,O(n²) 最坏
```
算法步骤:
1. 构造一个覆盖所有输入点的超级三角形
2. 逐点插入:
a. 找到外接圆包含新点的所有"坏"三角形
b. 提取坏三角形的边界边(只保留不重复的边)
c. 删除坏三角形
d. 用新点与每条边界边连接,形成新三角形
3. 删除包含超级三角形顶点的三角形
```
**关键实现细节**
- 三角形预存外接圆圆心和半径,加速包含判断
- 用哈希集合高效提取边界边(出现两次的边=内部边,删除;出现一次的边=边界边,保留)
---
## 2. NURBS 曲线求值
**算法**Cox-de Boor 递推公式
```
求值步骤:
1. find_span(t):二分查找 t 所在的节点区间
2. basis_functions(t, span):递推计算基函数 N_{i,p}
3. 加权组合:P(t) = Σ N_i·w_i·cp_i / Σ N_i·w_i
```
**基函数递推**
```
N_{i,0}(t) = 1 若 knots[i] ≤ t < knots[i+1],否则 0
N_{i,p}(t) = (t - knots[i]) / (knots[i+p] - knots[i]) · N_{i,p-1}(t)
+ (knots[i+p+1] - t) / (knots[i+p+1] - knots[i+1]) · N_{i+1,p-1}(t)
```
**复杂度**O(p²)p 为阶数
---
## 3. GJK 碰撞检测
**算法**Gilbert-Johnson-Keerthi
**用途**:检测两个凸体是否相交
```
核心思想:
1. 定义 Minkowski 差:C = A ⊖ B = {a - b | a∈A, b∈B}
2. A 与 B 相交 ⇔ C 包含原点
3. 迭代构建包含原点的单纯形(点→线→三角形→四面体)
4. 每步使用 support 函数在 Minkowski 差上采样
5. 3D 中最多约 40 次迭代即可得到结果
```
**Minkowski 差的 support 函数**
```
support(d) = support_A(d) - support_B(-d)
```
---
## 4. 网格简化(QEM
**算法**Quadric Error MetricsGarland & Heckbert, SIGGRAPH 1997
```
算法步骤:
1. 计算每个顶点的二次误差矩阵 Q(v)
2. 计算每条边的收缩代价:cost(e) = v_opt^T · (Q_v1 + Q_v2) · v_opt
3. 将所有边按代价放入最小堆
4. 贪心循环:
a. 弹出代价最小的边
b. 收缩该边到最优位置(或中点)
c. 更新所有受影响边的代价
5. 重复直到达到目标面数
```
**Q 矩阵定义**:对每个顶点 v,其 Q 矩阵为相邻面平面方程的外积和:
```
Q(v) = Σ K_p^T · K_p,其中 K_p = [a b c d]ax+by+cz+d=0
```
---
## 5. BVH 构建(SAH
**算法**:表面积启发式(Surface Area Heuristic
```
SAH 代价函数:
C = C_trav + (n_L·area_L + n_R·area_R) / area_total · C_isect
构建过程:
1. 对当前节点计算包围盒
2. 若图元数 ≤ leaf_size 或深度 ≥ max_depth → 创建叶节点
3. 否则:
a. 沿最长轴排序图元(按质心坐标)
b. 尝试多个分割位置,计算 SAH 代价
c. 选择代价最低的分割
d. 如果分割代价 ≥ 不分割的代价 → 创建叶节点
e. 否则递归构建左右子树
```
---
## 6. 2D 多边形布尔运算
**算法**Sutherland-Hodgman 裁剪(当前实现)
**目标算法**:Vatti 扫描线算法(对标 Clipper2
```
当前实现(S-H):
1. 以裁剪多边形为窗口
2. 对主题多边形的每条边逐一裁剪
3. 时间复杂度 O(n·m)
规划实现(Vatti):
1. 扫描线遍历所有边交点
2. 边分割与标记(内部/外部)
3. 提取结果轮廓
4. 支持任意多边形(含自交、带孔)
```