v0.1.0: 初始工程骨架 — 7模块 40头文件 32源文件 17文档 Apache-2.0
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
# 核心算法设计
|
||||
|
||||
## 目录
|
||||
|
||||
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 Metrics(Garland & 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. 支持任意多边形(含自交、带孔)
|
||||
```
|
||||
Reference in New Issue
Block a user