NavisworksTransport/doc/design/2026/geometry3Sharp空间数据结构集成方案.md
tian b05bb727c6 refactor: 完成 DataBindingPerformanceMonitor 功能的完整删除
- 删除 DataBindingPerformanceMonitor.cs 文件
- 从 NavisworksTransportPlugin.csproj 移除编译引用
- 清理 ViewModelBase.cs 中的所有性能监控代码
- 清理 ThreadSafeObservableCollection.cs 中的性能监控集成
- 清理 SmartDataBindingOptimizer.cs 中的性能监控使用
- 清理 BindingExpressionOptimizer.cs 中的性能监控调用

该功能不再需要,移除后简化了代码结构
2025-10-14 15:01:26 +08:00

1196 lines
34 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

# geometry3Sharp 空间数据结构集成方案
## 1. 背景与动机
### 1.1 当前碰撞检测的性能瓶颈
NavisworksTransport 项目在物流路径动画中实现了碰撞检测功能,但存在以下性能问题:
**当前实现的问题**
```csharp
// ClashDetectiveIntegration.cs - DetectCollisions()
// 线性遍历所有几何对象O(n) 复杂度
foreach (var item in allGeometryItems)
{
if (IsColliding(animatedObject, item))
{
collisions.Add(item);
}
}
```
**性能数据**(来自实际日志):
- 场景对象总数290 个
- 潜在碰撞对象108 个(经过路径包围盒预过滤)
- 每帧碰撞检测:遍历 108 个对象
- 动画总帧数300 帧
- **总计算量**300 × 108 = 32,400 次包围盒检测
**优化空间**
1. 空间查询仍然是线性遍历(即使经过预过滤)
2. 包围盒距离计算不精确AABB vs 实际几何距离)
3. 没有层次化空间索引加速
4. 动态查询效率低(物体移动时重新遍历)
### 1.2 空间数据结构的必要性
**需求场景**
1. **动画碰撞检测**:物体每帧移动,需要快速查询"当前位置附近有哪些障碍物"
2. **潜在碰撞对象过滤**:在路径规划前,快速找到路径沿途的所有可能碰撞物体
3. **精确距离计算**:计算物体到障碍物的真实距离(不是包围盒距离)
4. **路径可达性验证**:检查两点间的直线是否被障碍物阻挡
**理想的解决方案特征**
- ✅ O(log n) 或 O(1) 平均查询复杂度
- ✅ 支持动态位置的范围查询
- ✅ 精确的几何距离计算
- ✅ 商业友好的许可证
- ✅ 与 .NET Framework 4.8 兼容
---
## 2. geometry3Sharp 库概述
### 2.1 基本信息
**项目信息**
- **官方名称**geometry3Sharp (本项目使用的是 fork: geometry4Sharp)
- **GitHub**<https://github.com/gradientspace/geometry3Sharp> (原版)
- **GitHub**<https://github.com/NewWheelTech/geometry4Sharp> (fork)
- **许可证**Boost Software License 1.0(商业友好,无需开源衍生代码)
- **维护状态**原版活跃度降低2019后fork 有维护
- **平台兼容**.NET Standard 2.0, .NET Framework 4.8, .NET 6.0
- **语言**:纯 C#,无 C++ 互操作
**代码来源**
- 核心算法移植自 David Eberly 的 WildMagic5 和 GTEngine几何计算领域的经典库
- MeshSignedDistanceGrid 基于 Christopher Batty 的 SDFGen C++ 代码
- 经过多年实战验证,代码质量高
### 2.2 与体素网格方案的关系
**重要说明**geometry3Sharp 不是替代体素网格方案,而是**互补关系**。
| 模块 | 用途 | 应用场景 |
|------|------|---------|
| **体素网格 (MeshSignedDistanceGrid, Bitmap3, DSparseGrid3)** | 3D 空间离散化,路径规划 | 生成可通行网格3D A* 路径规划 |
| **空间索引 (DMeshAABBTree3, PointHashGrid3d)** | 快速空间查询,碰撞检测 | 动画碰撞检测,范围查询优化 |
| **距离查询 (DistPoint3Triangle3)** | 精确几何距离 | 碰撞容差计算,最近点查询 |
| **相交查询 (IntrRay3Triangle3)** | 射线-几何相交 | 路径可达性验证,视线检测 |
**集成策略**
- 体素网格用于**路径规划**(已在 `体素网格路径规划方案.md` 中详细设计)
- 空间索引用于**碰撞检测加速**(本文档重点)
- 两者共用 geometry3Sharp 的基础数学类型Vector3d, AxisAlignedBox3d 等)
---
## 3. 高价值模块详细分析
### 3.1 DMeshAABBTree3 - 层次化 AABB 树
#### 功能描述
`DMeshAABBTree3` 是三角网格的层次化轴对齐包围盒树,提供 O(log n) 复杂度的空间查询。
**核心特性**
- 自底向上或自顶向下构建策略(可选)
- 支持三角形级别的精确相交测试
- 多种空间查询接口
- 泛型遍历接口DoTraversal
**可用查询**
```csharp
// 1. 最近三角形查找
int FindNearestTriangle(Point3d point, double maxDistance);
// 2. 射线-网格最近命中
int FindNearestHitTriangle(Ray3d ray, double maxDistance);
// 3. 射线-网格所有命中
List<int> FindAllHitTriangles(Ray3d ray, double maxDistance);
// 4. 三角形相交测试
bool TestIntersection(Triangle3d triangle);
// 5. 树-树相交测试
bool TestIntersection(DMeshAABBTree3 otherTree);
// 6. 树-树所有相交
List<Tuple<int,int>> FindAllIntersections(DMeshAABBTree3 otherTree);
// 7. 树-树范围内最近三角形
List<Tuple<int,int>> FindNearestTriangles(DMeshAABBTree3 otherTree, double maxDist);
// 8. 点包含测试
bool IsInside(Point3d point);
// 9. 缠绕数Winding Number
double WindingNumber(Point3d point);
```
#### 应用场景
场景 1优化 GetPotentialColliders()**
当前实现(线性遍历):
```csharp
// PathAnimationManager.cs - GetPotentialColliders()
foreach (var item in allGeometryItems)
{
double distance = CalculateDistance(pathCenter, item);
if (distance <= detectionGap)
{
potentialColliders.Add(item);
}
}
```
使用 AABB 树优化(对数查询):
```csharp
// 1. 预构建场景的 AABB 树(一次性)
var sceneTree = BuildSceneAABBTree(allGeometryItems);
// 2. 快速范围查询
var potentialColliders = sceneTree.FindNearestTriangles(
animatedObjectTree,
detectionGap
);
```
**性能提升预估**
- 当前O(n) = 290 次包围盒测试
- 优化后O(log n) ≈ log₂(290) ≈ 8 次树节点遍历
- **加速比**:约 36 倍
场景 2精确碰撞检测**
替代简单包围盒检测,使用三角形级别的精确相交:
```csharp
// 检查动画对象是否与场景相交
bool hasCollision = animatedObjectTree.TestIntersection(sceneTree);
// 获取所有相交的三角形对
var intersections = animatedObjectTree.FindAllIntersections(sceneTree);
```
#### 构建策略选择
```csharp
public enum BuildStrategy
{
TopDownMidpoint, // 最快(默认)
BottomUpFromOneRings, // 平衡但慢 2.5 倍
TopDownMedian // 更平衡但慢 2-4 倍
}
// 推荐:快速构建 + 大量查询场景
var tree = new DMeshAABBTree3(mesh, autoBuild: false);
tree.Build(BuildStrategy.TopDownMidpoint);
```
#### 技术挑战
挑战 1Navisworks Geometry → DMesh3 转换
Navisworks 的 `ModelItem` 不直接暴露三角网格,需要通过几何提取:
```csharp
// 方案 A使用 GeometryExtractor项目已有
// 需要扩展为输出 geometry3Sharp 的 DMesh3 格式
// 方案 B使用包围盒代替精确网格简化版
// 优点:实现简单,性能好
// 缺点:精度降低(但对预过滤足够)
```
**推荐方案**:渐进式实现
1. **Phase 1**:使用包围盒近似(快速验证)
2. **Phase 2**:实现精确几何提取(提升精度)
---
### 3.2 PointHashGrid3d - 空间哈希网格
#### 功能描述
`PointHashGrid3d<T>` 是泛型的 3D 空间哈希表,提供 O(1) 平均时间复杂度的范围查询。
**核心特性**
- 基于网格单元的哈希索引
- 支持动态插入/删除/更新
- 线程安全SpinLock
- 泛型设计,可存储任意类型
**关键方法**
```csharp
// 初始化cellSize = 查询半径的 1-2 倍)
var grid = new PointHashGrid3d<ModelItem>(cellSize: 2.0, invalidValue: null);
// 插入点(线程安全)
grid.InsertPoint(modelItem, position);
// 删除点
grid.RemovePoint(modelItem, position);
// 更新点(移动)
grid.UpdatePoint(modelItem, oldPosition, newPosition);
// 范围查询(核心功能)
var nearby = grid.FindNearestInRadius(
queryPosition,
radius,
distanceFunc: (item) => Distance(queryPosition, item.Position)
);
// 批量查询
List<T> FindPointsInBox(AxisAlignedBox3d box);
```
#### 应用场景
场景 1加速动画碰撞检测
当前问题:
- 动画每帧都要遍历 108 个潜在碰撞对象
- 300 帧 × 108 对象 = 32,400 次检测
使用空间哈希优化:
```csharp
// === 初始化阶段(动画开始前)===
var spatialGrid = new PointHashGrid3d<ModelItem>(
cellSize: vehicleRadius * 2, // 格子大小 = 车辆直径
invalidValue: null
);
// 索引所有障碍物(一次性)
foreach (var obstacle in potentialColliders)
{
spatialGrid.InsertPoint(obstacle, obstacle.BoundingBox().Center);
}
// === 动画每帧 ===
// 快速查询当前位置附近的障碍物
var nearbyObstacles = spatialGrid.FindNearestInRadius(
currentPosition,
vehicleRadius + safetyMargin,
(item) => Vector3d.Distance(item.Position, currentPosition)
);
// 只检测附近的对象(通常 < 10 个)
foreach (var obstacle in nearbyObstacles)
{
if (IsColliding(animatedObject, obstacle))
{
collisions.Add(obstacle);
}
}
```
**性能提升预估**
- 当前:每帧检测 108 个对象
- 优化后:每帧检测 5-15 个对象(仅邻近格子)
- **加速比**:约 7-20 倍
场景 2动态场景更新
支持障碍物动态添加/移动:
```csharp
// 添加新障碍物
spatialGrid.InsertPoint(newObstacle, newObstacle.Position);
// 移动障碍物
spatialGrid.UpdatePoint(movingObstacle, oldPosition, newPosition);
// 删除障碍物
spatialGrid.RemovePoint(removedObstacle, removedObstacle.Position);
```
#### 格子大小选择
**原则**cellSize 应该接近查询半径
```csharp
// 推荐设置
double vehicleRadius = 0.3; // 米
double safetyMargin = 0.1; // 米
double detectionRadius = vehicleRadius + safetyMargin;
// cellSize = 查询半径 * 1.5
double cellSize = detectionRadius * 1.5; // 约 0.6 米
var spatialGrid = new PointHashGrid3d<ModelItem>(cellSize, null);
```
**权衡**
- cellSize 过小 → 格子太多,内存和查询开销大
- cellSize 过大 → 每个格子对象太多,退化为线性查询
---
### 3.3 DistPoint3Triangle3 - 精确距离查询
#### 功能描述
计算点到三角形的最短距离及最近点位置。
**核心方法**
```csharp
var query = new DistPoint3Triangle3(point, triangle);
double distance = query.Get(); // 最短距离
Vector3d closestPoint = query.TriangleClosest; // 三角形上最近点
int closestType = query.TriangleClosestType; // 最近点类型(顶点/边/面)
```
**相关类**
```csharp
DistPoint3Circle3 // 点到圆的距离
DistPoint3Cylinder3 // 点到圆柱的距离(带符号)
DistLine3Triangle3 // 线段到三角形的距离
DistSegment3Triangle3 // 线段到三角形的距离
DistTriangle3Triangle3 // 三角形到三角形的距离
```
#### 应用场景
场景 1精确碰撞容差
当前问题:
```csharp
// BoundingBoxGeometryUtils.cs - CalculateDistance()
// 只计算包围盒中心的距离,不精确
double distance = Vector3.Distance(bbox1.Center, bbox2.Center);
```
使用精确距离:
```csharp
// 计算物体表面到障碍物表面的真实距离
foreach (var triangle1 in animatedObjectMesh.Triangles)
{
foreach (var triangle2 in obstacleMesh.Triangles)
{
var query = new DistTriangle3Triangle3(triangle1, triangle2);
double distance = query.Get();
if (distance < collisionThreshold)
{
// 记录碰撞,包含精确距离和接触点
collisions.Add(new CollisionInfo
{
Distance = distance,
ContactPoint1 = query.Triangle1Closest,
ContactPoint2 = query.Triangle2Closest
});
}
}
}
```
场景 2碰撞报告增强
在碰撞报告中显示:
- 精确的间隙距离(而非包围盒距离)
- 最近接触点的 3D 坐标
- 可视化最短距离向量
---
### 3.4 IntrRay3Triangle3 - 射线相交查询
#### 功能描述
计算射线/线段与三角形的相交。
**核心方法**
```csharp
// 射线-三角形相交
var query = new IntrRay3Triangle3(ray, triangle);
bool intersects = query.Find(); // 是否相交
double rayParameter = query.RayParameter; // 射线参数 t (交点 = ray.Origin + t * ray.Direction)
Vector3d intersectionPoint = ray.PointAt(rayParameter);
// 线段-三角形相交
var segmentQuery = new IntrSegment3Triangle3(segment, triangle);
bool intersects = segmentQuery.Find();
```
**相关类**
```csharp
IntrLine2Line2 // 2D 直线相交
IntrSegment2Segment2 // 2D 线段相交
IntrTriangle3Triangle3 // 3D 三角形相交
IntrRay3Box3 // 射线-AABB 相交
IntrRay3AxisAlignedBox3 // 射线-轴对齐盒相交
```
#### 应用场景
场景 1路径可达性验证
检查两点间的直线路径是否被障碍物阻挡:
```csharp
/// <summary>
/// 检查直线路径是否可达(无障碍物阻挡)
/// </summary>
public bool IsPathClear(Point3D start, Point3D end, IEnumerable<DMesh3> obstacles)
{
Vector3d direction = (end - start).Normalized;
double distance = Vector3d.Distance(start, end);
var ray = new Ray3d(start, direction);
foreach (var obstacleMesh in obstacles)
{
foreach (var triangleId in obstacleMesh.TriangleIndices())
{
var triangle = GetTriangle(obstacleMesh, triangleId);
var query = new IntrRay3Triangle3(ray, triangle);
if (query.Find() && query.RayParameter < distance)
{
// 射线在到达终点前与障碍物相交
return false;
}
}
}
return true; // 路径畅通
}
```
场景 2视线检测
判断两个物体之间是否有遮挡:
```csharp
// 检查从起重机到目标物体的视线是否被遮挡
bool hasLineOfSight = IsPathClear(crane.Position, targetObject.Position, obstacles);
```
**场景 3改进 A* 路径规划**
在 A* 算法中增加射线检测,避免规划出会穿模的路径:
```csharp
// 生成路径后,后处理优化
var optimizedPath = new List<Point3D>();
optimizedPath.Add(path[0]);
for (int i = 0; i < path.Count - 1; i++)
{
// 尝试直接连接当前点和后续点
for (int j = path.Count - 1; j > i + 1; j--)
{
if (IsPathClear(path[i], path[j], obstacles))
{
optimizedPath.Add(path[j]);
i = j - 1;
break;
}
}
}
```
---
## 4. 中等价值模块(可选)
### 4.1 Polygon2d - 2D 多边形操作
**功能**
- 点在多边形内测试Contains
- 多边形简化Simplify
- 多边形裁剪
- 多边形布尔运算
**应用场景**
- 楼层区域判断(路径点是否在楼层边界内)
- 2D 路径规划(作为 3D 规划的补充)
### 4.2 ConvexHull2 - 2D 凸包
**功能**
- 计算点集的 2D 凸包
**应用场景**
- 楼层边界自动识别
- 路径覆盖区域计算
### 4.3 MeshPlaneCut - 网格平面切割
**功能**
- 用平面切割三角网格
- 返回切割边界EdgeLoop
**应用场景**
- 楼层切片(按高度切分建筑模型)
- 断面分析(生成路径断面视图)
---
## 5. 集成架构设计
### 5.1 整体架构
```graph
┌─────────────────────────────────────────────────────────────┐
│ Navisworks API │
│ (ModelItem, BoundingBox3D, Geometry) │
└────────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ NavisworksGeometryAdapter (新) │
│ - ModelItem → DMesh3 │
│ - Point3D ↔ Vector3d │
│ - BoundingBox3D ↔ AxisAlignedBox3d │
└────────────────────────┬────────────────────────────────────┘
┌────────────┴────────────┐
▼ ▼
┌─────────────────────┐ ┌─────────────────────┐
│ SpatialIndexCache │ │ CollisionQueryHelper│
│ (新) │ │ (新) │
│ │ │ │
│ - SceneAABBTree │ │ - DistanceQuery │
│ - ObstacleHashGrid │ │ - IntersectionQuery │
│ - 缓存管理 │ │ - 精确碰撞检测 │
└──────────┬──────────┘ └──────────┬──────────┘
│ │
│ ┌─────────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ ClashDetectiveIntegration (改进) │
│ - GetPotentialColliders() → 使用 SpatialIndexCache │
│ - DetectCollisions() → 使用 CollisionQueryHelper │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ PathAnimationManager (无需修改) │
└─────────────────────────────────────────────────────────────┘
```
### 5.2 核心类设计
#### 5.2.1 NavisworksGeometryAdapter - 适配层
```csharp
/// <summary>
/// Navisworks API 与 geometry3Sharp 之间的转换适配器
/// </summary>
public static class NavisworksGeometryAdapter
{
#region 坐标转换
/// <summary>
/// Navisworks Point3D → geometry3Sharp Vector3d
/// </summary>
public static Vector3d ToVector3d(this Point3D point)
{
return new Vector3d(point.X, point.Y, point.Z);
}
/// <summary>
/// geometry3Sharp Vector3d → Navisworks Point3D
/// </summary>
public static Point3D ToPoint3D(this Vector3d vector)
{
return new Point3D(vector.x, vector.y, vector.z);
}
/// <summary>
/// Navisworks BoundingBox3D → geometry3Sharp AxisAlignedBox3d
/// </summary>
public static AxisAlignedBox3d ToAxisAlignedBox3d(this BoundingBox3D bbox)
{
return new AxisAlignedBox3d(
bbox.Min.ToVector3d(),
bbox.Max.ToVector3d()
);
}
#endregion
#region 几何提取
/// <summary>
/// 从 ModelItem 提取三角网格(简化版:使用包围盒)
/// </summary>
public static DMesh3 ExtractMeshSimple(ModelItem item)
{
var bbox = item.BoundingBox();
var mesh = new DMesh3();
// 将包围盒转为 8 个顶点 + 12 个三角形
// (简化实现,适用于快速验证)
AddBoxToMesh(mesh, bbox.ToAxisAlignedBox3d());
return mesh;
}
/// <summary>
/// 从 ModelItem 提取精确三角网格完整版Phase 2 实现)
/// </summary>
public static DMesh3 ExtractMeshAccurate(ModelItem item)
{
// TODO: 使用 GeometryExtractor 获取实际三角形
// 需要遍历 Navisworks Geometry API
throw new NotImplementedException("Phase 2");
}
#endregion
}
```
#### 5.2.2 SpatialIndexCache - 空间索引缓存
```csharp
/// <summary>
/// 场景空间索引缓存管理器
/// 在动画开始前预构建空间索引,动画过程中复用
/// </summary>
public class SpatialIndexCache
{
private static SpatialIndexCache _instance;
public static SpatialIndexCache Instance => _instance ??= new SpatialIndexCache();
// 场景 AABB 树(用于精确查询)
private DMeshAABBTree3 _sceneAABBTree;
// 障碍物空间哈希网格(用于快速范围查询)
private PointHashGrid3d<ModelItem> _obstacleHashGrid;
// 缓存版本(检测场景变化)
private int _cacheVersion = 0;
#region 构建方法
/// <summary>
/// 构建场景的空间索引
/// </summary>
public void BuildSpatialIndex(
IEnumerable<ModelItem> obstacles,
double hashGridCellSize)
{
LogManager.Info("[空间索引] 开始构建...");
var sw = Stopwatch.StartNew();
// 1. 构建 AABB 树
var sceneMesh = CombineMeshes(obstacles);
_sceneAABBTree = new DMeshAABBTree3(sceneMesh, autoBuild: true);
LogManager.Info($"[空间索引] AABB 树构建完成,节点数: {_sceneAABBTree.MaxLeafSize}");
// 2. 构建空间哈希网格
_obstacleHashGrid = new PointHashGrid3d<ModelItem>(hashGridCellSize, null);
foreach (var obstacle in obstacles)
{
var center = obstacle.BoundingBox().Center.ToVector3d();
_obstacleHashGrid.InsertPoint(obstacle, center);
}
LogManager.Info($"[空间索引] 哈希网格构建完成,格子大小: {hashGridCellSize}m");
_cacheVersion++;
sw.Stop();
LogManager.Info($"[空间索引] 构建完成,耗时: {sw.ElapsedMilliseconds}ms");
}
#endregion
#region 查询方法
/// <summary>
/// 快速范围查询(使用哈希网格)
/// </summary>
public List<ModelItem> FindNearbyObstacles(Point3D center, double radius)
{
if (_obstacleHashGrid == null)
throw new InvalidOperationException("空间索引未初始化");
var centerVec = center.ToVector3d();
var nearby = new List<ModelItem>();
// 哈希网格范围查询
// 注意PointHashGrid3d 没有直接的 FindNearestInRadius 方法
// 需要手动实现或使用 FindPointsInBox
var searchBox = new AxisAlignedBox3d(centerVec, radius);
// 遍历搜索框内的所有格子(简化实现)
// 实际应该调用哈希网格的范围查询方法
// 这里需要根据 geometry3Sharp 的实际 API 调整
return nearby;
}
/// <summary>
/// 精确相交查询(使用 AABB 树)
/// </summary>
public bool TestIntersection(DMesh3 objectMesh)
{
if (_sceneAABBTree == null)
throw new InvalidOperationException("空间索引未初始化");
var objectTree = new DMeshAABBTree3(objectMesh, autoBuild: true);
return _sceneAABBTree.TestIntersection(objectTree);
}
#endregion
#region 辅助方法
private DMesh3 CombineMeshes(IEnumerable<ModelItem> items)
{
var combinedMesh = new DMesh3();
foreach (var item in items)
{
var itemMesh = NavisworksGeometryAdapter.ExtractMeshSimple(item);
var editor = new MeshEditor(combinedMesh);
editor.AppendMesh(itemMesh);
}
return combinedMesh;
}
#endregion
}
```
#### 5.2.3 CollisionQueryHelper - 碰撞查询助手
```csharp
/// <summary>
/// 精确碰撞查询辅助类
/// </summary>
public static class CollisionQueryHelper
{
/// <summary>
/// 计算物体到障碍物的最短距离
/// </summary>
public static double CalculateMinDistance(
ModelItem movingObject,
ModelItem obstacle)
{
var mesh1 = NavisworksGeometryAdapter.ExtractMeshSimple(movingObject);
var mesh2 = NavisworksGeometryAdapter.ExtractMeshSimple(obstacle);
double minDistance = double.MaxValue;
// 遍历所有三角形对,找到最短距离
foreach (var tri1Id in mesh1.TriangleIndices())
{
var tri1 = GetTriangle(mesh1, tri1Id);
foreach (var tri2Id in mesh2.TriangleIndices())
{
var tri2 = GetTriangle(mesh2, tri2Id);
var query = new DistTriangle3Triangle3(tri1, tri2);
double distance = query.Get();
if (distance < minDistance)
{
minDistance = distance;
}
}
}
return minDistance;
}
/// <summary>
/// 检查射线路径是否畅通
/// </summary>
public static bool IsPathClear(
Point3D start,
Point3D end,
DMeshAABBTree3 sceneTree)
{
var direction = (end.ToVector3d() - start.ToVector3d()).Normalized;
var distance = Vector3d.Distance(start.ToVector3d(), end.ToVector3d());
var ray = new Ray3d(start.ToVector3d(), direction);
// 使用 AABB 树快速查询射线相交
int hitTriangle = sceneTree.FindNearestHitTriangle(ray);
if (hitTriangle == DMesh3.InvalidID)
return true; // 无相交
// 检查相交点是否在起终点之间
// TODO: 需要获取相交点位置并比较距离
return false;
}
private static Triangle3d GetTriangle(DMesh3 mesh, int triangleId)
{
var tri = mesh.GetTriangle(triangleId);
var v0 = mesh.GetVertex(tri.a);
var v1 = mesh.GetVertex(tri.b);
var v2 = mesh.GetVertex(tri.c);
return new Triangle3d(v0, v1, v2);
}
}
```
### 5.3 集成到现有系统
#### 修改 ClashDetectiveIntegration.cs
```csharp
// 在 GetPotentialColliders() 中使用空间索引
private List<ModelItem> GetPotentialColliders()
{
// 1. 计算路径包围盒
var pathBounds = CalculatePathBounds();
var pathCenter = GetBoundingBoxCenter(pathBounds);
var detectionRadius = GetBoundingBoxDiagonal(pathBounds) / 2;
// 2. 使用空间哈希网格快速查询
var potentialColliders = SpatialIndexCache.Instance.FindNearbyObstacles(
pathCenter,
detectionRadius
);
LogManager.Info($"空间索引查询结果: {potentialColliders.Count} 个潜在碰撞对象");
return potentialColliders;
}
```
---
## 6. 实施方案
### 6.1 分阶段实施
#### Phase 1: PointHashGrid3d 集成2-3 天,立即可用)
**目标**:使用空间哈希网格优化动画碰撞检测。
**任务**
1. 创建 `NavisworksGeometryAdapter` 类(坐标转换)
2. 创建 `SpatialIndexCache` 类(仅哈希网格部分)
3. 修改 `ClashDetectiveIntegration.GetPotentialColliders()` 使用哈希网格
4. 修改动画碰撞检测使用哈希网格查询
5. 性能测试和日志记录
**验收标准**
- ✅ 动画碰撞检测速度提升 5-10 倍
- ✅ 日志显示每帧实际检测的对象数量减少
- ✅ 功能正确性不变(碰撞结果与原方案一致)
---
#### Phase 2: DMeshAABBTree3 优化1 周)
**目标**:构建场景 AABB 树,优化范围查询和相交检测。
**任务**
1. 实现 `NavisworksGeometryAdapter.ExtractMeshSimple()`(使用包围盒)
2.`SpatialIndexCache` 中添加 AABB 树构建
3. 使用 AABB 树优化 `FindNearestTriangles()` 查询
4. 实现精确相交检测(替代简单包围盒测试)
5. 性能对比测试
**验收标准**
- ✅ AABB 树构建时间 < 5 中等场景
- 范围查询速度提升 10-30
- 支持精确三角形级别的碰撞检测
---
#### Phase 3: 精确距离和相交查询可选3-5 天)
**目标**使用精确几何查询提升碰撞报告质量
**任务**
1. 创建 `CollisionQueryHelper`
2. 实现精确距离计算DistTriangle3Triangle3
3. 实现路径可达性验证IntrRay3Triangle3
4. 在碰撞报告中显示精确距离和接触点
5. 可选实现 `ExtractMeshAccurate()` 精确几何提取
**验收标准**
- 碰撞报告显示精确距离非包围盒距离
- 支持路径可达性验证功能
- 性能可接受精确查询耗时 < 2x 简化查询
---
### 6.2 时间与资源估算
| 阶段 | 任务 | 工作量 | 依赖 |
|------|------|--------|------|
| Phase 1 | PointHashGrid3d 集成 | 2-3 | geometry3Sharp |
| Phase 2 | DMeshAABBTree3 优化 | 5-7 | Phase 1 |
| Phase 3 | 精确查询可选| 3-5 | Phase 2 |
| **总计** | | **10-15 天** | |
---
## 7. 技术挑战与缓解
### 7.1 Navisworks API 限制
**挑战**Navisworks `ModelItem` 不直接暴露三角网格数据
**缓解措施**
- **Phase 1**使用包围盒代替精确网格快速验证
- **Phase 2**研究 `GeometryExtractor` 提取实际几何
- **Phase 3**实现 Navisworks Geometry API DMesh3 转换器
### 7.2 坐标系转换
**挑战**Navisworks API geometry3Sharp 使用不同的类型系统
**缓解措施**
- 创建 `NavisworksGeometryAdapter` 适配层
- 统一使用模型单位避免米制/英制混淆
- 单元测试验证转换正确性
### 7.3 性能权衡
**挑战**空间索引构建有初始开销
**缓解措施**
- 在动画开始前预构建用户点击"生成动画"
- 缓存索引场景不变时复用
- 显示进度条让用户知道正在构建
---
## 8. 性能预期
### 8.1 性能对比(预估)
基于类似规模的空间索引系统经验
| 操作 | 当前实现 | Phase 1 (哈希) | Phase 2 (AABB树) |
|------|---------|---------------|-----------------|
| **范围查询** | O(n) = 290次 | O(1) 10次 | O(log n) 8次 |
| **碰撞检测** | 32,400次/动画 | 3,000次/动画 | 2,400次/动画 |
| **构建开销** | 0 | 0.1 | 2-5 |
| **内存占用** | 0 MB | +10 MB | +50 MB |
**场景假设**
- 对象总数290
- 动画帧数300
- 潜在碰撞对象108 经过预过滤
### 8.2 预期加速比
**Phase 1 完成后**
- 每帧碰撞检测108 对象 10 对象
- **加速比** 10
**Phase 2 完成后**
- 范围查询O(n) O(log n)
- **加速比** 30-50 组合效果
---
## 9. 与体素网格方案的关系
### 9.1 互补关系说明
| 方案 | 主要用途 | 数据结构 | 查询类型 |
|------|---------|---------|---------|
| **体素网格** | 路径规划 | 3D 网格 + SDF | 可通行性路径搜索 |
| **空间索引** | 碰撞检测 | AABB树哈希网格 | 范围查询相交测试 |
### 9.2 共用基础设施
两个方案共享 geometry3Sharp 的基础组件
- 数学类型Vector3d, AxisAlignedBox3d
- 坐标转换适配器NavisworksGeometryAdapter
- 几何提取工具
### 9.3 集成策略
```graph
geometry3Sharp 基础库
├── 体素网格模块 (用于路径规划)
│ ├── MeshSignedDistanceGrid
│ ├── Bitmap3 / DSparseGrid3
│ └── VoxelGrid (自定义)
└── 空间索引模块 (用于碰撞检测)
├── DMeshAABBTree3
├── PointHashGrid3d
└── Distance/Intersection 查询
```
---
## 10. 不适用的模块
以下 geometry3Sharp 模块**不适用于本项目**
### 10.1 网格编辑类
- **Remesher**, **Reducer**, **MeshEditor**
- **原因**Navisworks 是只读查看器不支持修改网格几何
### 10.2 曲线生成类
- **NURBSCurve2**, **BezierCurve**
- **原因**项目使用折线路径不需要复杂曲线拟合
### 10.3 网格修复类
- **MeshAutoRepair**, **RemoveDuplicateTriangles**
- **原因**Navisworks 模型已优化无法运行时修改
### 10.4 布尔运算类
- **MeshBoolean**
- **原因**文档明确说"不是健壮的布尔运算" Navisworks API 不支持
---
## 11. 实施建议
### 11.1 推荐的实施优先级
**立即实施(高优先级)**
1. **PointHashGrid3d** 快速见效大幅提升动画碰撞检测性能
**短期实施(中优先级)**
2. **DMeshAABBTree3** 进一步优化支持精确相交检测
**长期考虑(低优先级)**
3. **精确距离查询** 功能增强非关键路径
4. **射线相交查询** 路径验证功能可选
### 11.2 风险提示
**不要全盘集成 geometry3Sharp**应该
- 只提取需要的类避免依赖膨胀
- 创建适配层隔离外部依赖
- 渐进式验证每个 Phase 独立验收
---
## 12. 参考资料
### 12.1 geometry3Sharp 资源
- **GitHub原版**<https://github.com/gradientspace/geometry3Sharp>
- **GitHubfork**<https://github.com/NewWheelTech/geometry4Sharp>
- **NuGet**geometry4Sharp 1.0.0
- **原作者**Ryan Schmidt (@rms80)
- **算法来源**WildMagic5/GTEngine (David Eberly)
### 12.2 理论基础
- **空间哈希网格**
- "Spatial Hashing for 3D Grids" - Teschner et al., 2003
- "Optimized Spatial Hashing for Collision Detection of Deformable Objects"
- **AABB 树**
- "OBBTree: A Hierarchical Structure for Rapid Interference Detection" (Gottschalk et al., 1996)
- "Fast Collision Detection Using AABB Trees" - Real-Time Rendering
- **距离查询**
- "Distance Between Point and Triangle in 3D" - David Eberly, Geometric Tools
- "Fast Distance Queries for Triangles, Lines and Points using SSE"
### 12.3 相关文档
- 《体素网格路径规划方案.md》- 路径规划部分
- 《PATHFINDING_DESIGN.md》- A* 算法设计
- 《寻路算法的对比.md》- 算法选型依据
---
## 13. 总结
### 13.1 核心价值
1.**显著的性能提升**:碰撞检测加速 10-50 倍
2.**商业友好许可证**Boost License无需开源
3.**成熟稳定的代码**:源自经典几何库 WildMagic5
4.**渐进式集成**:分阶段实施,风险可控
5.**互补体素方案**:两者协同,各司其职
### 13.2 建议行动
**立即行动**
1. 安装 geometry4Sharp NuGet 包
2. 实施 Phase 1PointHashGrid3d
3. 测试性能提升
**后续行动**
- Phase 1 验证后,评估是否继续 Phase 2
- 与体素网格方案协同推进
### 13.3 成功标准
- ✅ 动画碰撞检测速度提升 10 倍以上
- ✅ 构建开销可接受(< 5
- 内存占用增加 < 100 MB
- 功能正确性保持不变
- 代码可维护性良好
---
**文档版本**: v1.0
**创建日期**: 2025-10-14
**最后更新**: 2025-10-14
**作者**: NavisworksTransport 开发团队
**相关文档**: 体素网格路径规划方案.md