# Navisworks 插件自动路径规划设计方案

## 1. 背景与目标

* **背景**: 当前已在Navisworks插件中集成Roy-T.AStar库，实现了基于二维地面投影的自动寻路功能。
* **问题**: 该方案无法处理三维空间中的障碍物（如管道、横梁），这些障碍物在地面上的投影区域会导致规划出的路径在实际三维空间中不可行。
* **目标**: 改进路径规划算法，使其能够识别并避开真实的三维障碍物，确保规划出的路径在三维空间中是可通行的。

## 2. 设计方案

提出三种解决方案，按复杂度和效果递增排列。

### 方案一：基于Navisworks API的完整3D空间分析与图构建 (推荐长期实施)

#### 2.1 核心思路

利用Navisworks强大的API，直接访问模型的三维几何和属性信息，在插件内部或外部预处理程序中，构建一个精确反映“可行驶区域”的拓扑图（Graph），然后在此图上运行A*算法。

#### 2.2 实施步骤

1. **数据获取 (Navisworks API)**:
    * 遍历模型，获取关键构件信息：
        * **地面/楼板 (Floor/Slab)**: 获取其几何形状（面片或网格），用于定义基础行驶区域。
        * **障碍物 (Obstacles)**: 获取所有可能阻挡物体的构件（如管道 `Pipe`、风管 `Duct`、横梁 `Beam`、设备 `Equipment` 等）的**三维包围盒 (Bounding Box)** 或精确网格数据。
        * **连接构件 (Connections)**: 获取门 `Door`、楼梯 `Stairs`、电梯 `Elevator` 等信息，用于处理特殊通行规则或楼层间移动。
    * 获取构件的属性（如类别、名称、ID），以便于分类和处理。

2. **3D空间分析与“可行驶区域”定义**:
    * **定义物体参数**: 确定物体的尺寸（长、宽、高 `H_object`）和最大行驶高度 `H_max`。
    * **方法A - 2.5D栅格化 (推荐)**:
        * 在地面平面上建立一个2D规则网格。
        * 对网格中的每个单元格 `(x, y)`，沿Z轴扫描从地面到 `H_max` 的空间。
        * 检查此垂直扫描线是否与任何障碍物的几何体相交。
        * 记录每个 `(x, y)` 单元格内所有“无障碍”的高度区间 `[Z_min, Z_max]`。
        * 如果只关心固定高度层（如所有通道在同一层），则只需检查该高度层是否有障碍物。
    * **方法B - 简化2D栅格化**: 结合方案三，作为此步骤的一个简化实现。

3. **图 (Graph) 构建**:
    * **节点 (Node)**: 每个“可通行”的网格单元格中心（或角落）作为图的节点，其坐标为 `(x, y, z)`。`z` 可以是地面高度或固定行驶层高度。
    * **边 (Edge)**: 相邻的可通行节点之间建立连接。
        * **成本计算**: 边的权重可以是欧几里得距离 `Distance`，也可以结合行驶时间 `Duration`（距离/预设速度）。
        * **特殊边**:
            * 门: 连接门两侧节点，成本可动态调整（如门关闭时成本极高）。
            * 楼梯/电梯: 连接不同楼层的对应节点，成本应反映垂直移动的时间。
    * **输出**: 生成一个可供Roy-T.AStar库使用的 `Graph` 对象。

4. **Navisworks插件集成**:
    * **初始化**: 插件启动或模型更新时，执行上述预处理步骤，生成并加载路径图。
    * **寻路调用**:
        * 用户指定起点和终点（3D坐标）。
        * 将3D点映射到图中最邻近的节点。
        * 调用 `PathFinder.FindPath(startNode, endNode, graph)` 进行寻路。
    * **结果可视化**: 将A*返回的路径（节点序列）在Navisworks视图中绘制出来。

#### 2.3 优点

* 精度最高，能真实反映三维空间的可通行性。
* 为未来扩展（如多层物体、更复杂的避障规则）奠定坚实基础。
* 一次计算，多次高效寻路。

#### 2.4 缺点

* 开发复杂度最高，需要深入理解和使用Navisworks API进行空间计算。
* 预处理阶段计算量较大。

### 方案二：后处理校验与迭代修正 (快速验证)

#### 2.1 核心思路

保留现有二维投影寻路逻辑，但在得到路径后，增加一个三维碰撞检测步骤来校验路径的可行性，并根据结果进行修正或提示。

#### 2.2 实施步骤

1. **执行二维寻路**: 运行当前基于地面投影的A*算法，得到一条二维路径。
2. **三维碰撞检测**:
    * 遍历路径上的关键点或按固定步长取点。
    * 在每个点上，根据预设的物体尺寸，在三维空间中生成一个代表物体的包围盒（AABB或OBB）。
    * 利用Navisworks API的碰撞检测功能，检查此包围盒是否与模型中的任何构件发生碰撞。
3. **处理与反馈**:
    * **无冲突**: 路径可行，直接输出。
    * **有冲突**:
        * **简单处理**: 向用户提示“路径在XX处存在碰撞，可能不可行”。
        * **复杂处理 (迭代)**:
            a. 记录所有发生碰撞的点及其在二维投影平面上的区域。
            b. 将这些冲突区域在原始二维寻路网格中临时标记为“不可通行”。
            c. 重新调用二维A*算法进行寻路。
            d. 重复步骤2和3，直到找到一条无冲突路径或达到最大迭代次数。

#### 2.3 优点

* 对现有代码改动最小，实现快速。
* 可以快速验证思路。

#### 2.4 缺点

* 效果有限，可能无法找到真正可行的路径。
* “试错-修正”机制效率低，可能需要多次迭代。
* 无法保证找到最优解。

### 方案三：混合方法 - 构建精确的可行驶区域网格 (推荐短期实施)

#### 3.1 核心思路

结合现有二维框架和Navisworks API能力。核心在于**不再使用建筑最大包围盒作为寻路依据，而是通过Navisworks API精确构建一个反映真实“可行驶区域”的二维网格**。该网格通过叠加“地面区域”和“障碍物投影区域”图层计算得出。

#### 3.2 实施步骤

1. **定义物体参数**:
    * 明确物体的尺寸（长、宽、高 `H_object`）。
    * 确定物体的最大行驶高度 `H_max`（例如，物体底盘离地高度 + H_object）。

2. **生成基础二维网格**:
    * **范围**: 基于整个建筑地面或您关心的区域，定义一个二维规则网格。网格的分辨率需要权衡精度和性能（例如，单元格大小可以是0.5m x 0.5m）。
    * **初始状态**: 此时，网格单元格的状态是**未知**的。

3. **构建“地面区域图层”**:
    * **目标**: 确定哪些网格单元格是**理论上**可供物体**安全停放或通过中心点**的区域（即有地面存在的区域）。
    * **方法 (利用Navisworks API)**:
        * 遍历模型，找到所有被分类为“Floor”、“Slab”或类似类别的构件。
        * 获取它们的几何信息（面片）。
        * 对于每个“地面”面片，判断其覆盖了哪些网格单元格（例如，单元格中心点是否在面片内，或单元格大部分区域在面片内）。
    * **结果**: 得到一个“地面图层”网格，其中标记了所有有地面的单元格。这表示物体**有可能**在这些区域活动。

4. **构建“障碍物投影图层”**:
    * **目标**: 识别并标记所有会**阻挡物体通行**的区域。
    * **方法 (利用Navisworks API)**:
        * 遍历模型，找到所有可能构成障碍的构件（Pipe, Duct, Beam, Column, Equipment, Wall等）。
        * **方法 A: 简单包围盒投影 (快速但粗糙)**:
            * 获取每个障碍物的三维Axis-Aligned Bounding Box (AABB)。
            * 计算每个障碍物AABB在地面（或物体行驶平面 `H_max`）上的二维投影区域。
        * **方法 B: 精确切片投影 (推荐，精度高)**:
            * **核心思想**: 在物体行驶高度 `H_object` 对障碍物进行水平“切片”，得到其在该高度的精确二维截面，再将此截面投影到地面网格。
            * **步骤**:
                1. **几何获取**: 使用Navisworks API获取障碍物的精确三角网格 (`Mesh`) 数据。
                2. **执行切片**: 计算水平平面 `Z = H_object` 与障碍物网格的交集。这通常需要实现一个算法或使用第三方计算几何库（如CGAL）来计算网格与平面的交线，得到一组表示截面轮廓的二维线段。
                3. **投影**: 由于截面本身就是高度为 `H_object` 的二维形状，将其Z坐标统一设为地面高度即可视为投影。
                4. **栅格化**: 将这些精确的二维截面线段“绘制”到基础二维网格上，标记被覆盖的单元格。
        * **方法 C: 视图导出与图像处理 (变通方法，实现相对简单)**:
            * **核心思想**: 利用Navisworks强大的渲染和剪裁功能，通过图像处理间接获得投影。
            * **步骤**:
                1. **设置视图**: 在Navisworks中设置一个俯视的正交视图 (Orthographic View)。
                2. **设置剪裁**: 应用剪裁平面，只显示模型在高度 `Z = H_object` 到 `Z = H_object + delta` (delta为很小的正值) 之间的“薄片”。
                3. **隐藏地面**: （可选）隐藏地面构件，使视图只显示障碍物薄片。
                4. **导出图像**: 使用API将此特定视图导出为二维图像（如PNG）。
                5. **图像处理**: 在插件或外部程序中，使用图像处理库识别图像中的障碍物像素，并将这些像素区域映射回原始的二维寻路网格，标记对应的单元格。
        * **选择建议**:
            * **初期验证**: 可使用 **方法 A** 快速搭建流程。
            * **中期迭代**: 推荐 **方法 C**，它在实现复杂度和精度之间取得了很好的平衡，能有效利用Navisworks现有功能。
            * **最终方案**: 如果对精度和性能有极致要求，应采用 **方法 B**。
        * **标记**: 将计算出的投影区域（无论采用哪种方法）所覆盖的网格单元格标记为“被障碍物投影覆盖”。
    * **结果**: 得到一个“障碍物投影图层”网格。

5. **合成最终“可通行区域网格”**:
    * **核心逻辑**: 一个网格单元格是**真正可通行**的，当且仅当：
        * 它在“地面图层”中被标记为**属于地面** (是潜在可达区域)。
        * **并且** 它在“障碍物投影图层”中**未被任何障碍物投影覆盖**。
    * **操作**: 遍历所有网格单元格，根据上述逻辑计算其最终状态。只有同时满足两个条件的单元格，才在最终用于寻路的网格中被标记为 `Accessible`（或类似表示可通行的状态）。

6. **使用Roy-T.AStar进行寻路**:
    * **创建Grid**: 使用上述最终生成的、精确的“可通行区域网格”来创建 `Roy_T.AStar.Grids.Grid` 对象。
        * 网格大小 (`GridSize`) 对应您的二维网格。
        * 每个单元格的状态 (`GridCellState`) 来自第5步计算出的最终结果。
        * 单元格大小 (`Size`) 对应您的网格分辨率。
        * `traversalVelocity` 可以设为一个默认值，或者根据不同区域类型进行调整。
    * **调用寻路**: `PathFinder.FindPath(startPosition, endPosition, grid)`。

#### 3.3 优点

* 实现相对简单，对现有架构改动较小。
* 能有效解决当前最主要的问题（空中障碍物投影导致的误判）。
* 开发周期短，可作为从方案二到方案一的过渡。
* **核心改进**: 通过构建精确的“可通行区域”网格，真正利用了Roy-T.AStar库的Grid功能，而非简单粗暴地使用建筑包围盒。

#### 3.4 缺点

* 精度低于方案一（例如，无法处理非垂直投影的复杂障碍物，或不同高度层的障碍物）。
* 仍然是基于二维的近似方法。

### 方案一：基于Navisworks API的完整3D空间分析与图构建 (推荐长期实施)

#### 2.1 核心思路

利用Navisworks强大的API，直接访问模型的三维几何和属性信息，在插件内部或外部预处理程序中，构建一个精确反映“可行驶区域”的拓扑图（Graph），然后在此图上运行A*算法。

#### 2.2 实施步骤

1. **数据获取 (Navisworks API)**:
    * 遍历模型，获取关键构件信息：
        * **地面/楼板 (Floor/Slab)**: 获取其几何形状（面片或网格），用于定义基础行驶区域。
        * **障碍物 (Obstacles)**: 获取所有可能阻挡物体的构件（如管道 `Pipe`、风管 `Duct`、横梁 `Beam`、设备 `Equipment` 等）的**三维包围盒 (Bounding Box)** 或精确网格数据。
        * **连接构件 (Connections)**: 获取门 `Door`、楼梯 `Stairs`、电梯 `Elevator` 等信息，用于处理特殊通行规则或楼层间移动。
    * 获取构件的属性（如类别、名称、ID），以便于分类和处理。

2. **3D空间分析与“可行驶区域”定义**:
    * **定义物体参数**: 确定物体的尺寸（长、宽、高 `H_object`）和最大行驶高度 `H_max`。
    * **方法A - 2.5D栅格化 (推荐)**:
        * 在地面平面上建立一个2D规则网格。
        * 对网格中的每个单元格 `(x, y)`，沿Z轴扫描从地面到 `H_max` 的空间。
        * 检查此垂直扫描线是否与任何障碍物的几何体相交。
        * 记录每个 `(x, y)` 单元格内所有“无障碍”的高度区间 `[Z_min, Z_max]`。
        * 如果只关心固定高度层（如所有通道在同一层），则只需检查该高度层是否有障碍物。
    * **方法B - 简化2D栅格化**: 结合方案三，作为此步骤的一个简化实现。

3. **图 (Graph) 构建**:
    * **节点 (Node)**: 每个“可通行”的网格单元格中心（或角落）作为图的节点，其坐标为 `(x, y, z)`。`z` 可以是地面高度或固定行驶层高度。
    * **边 (Edge)**: 相邻的可通行节点之间建立连接。
        * **成本计算**: 边的权重可以是欧几里得距离 `Distance`，也可以结合行驶时间 `Duration`（距离/预设速度）。
        * **特殊边**:
            * 门: 连接门两侧节点，成本可动态调整（如门关闭时成本极高）。
            * 楼梯/电梯: 连接不同楼层的对应节点，成本应反映垂直移动的时间。
    * **输出**: 生成一个可供Roy-T.AStar库使用的 `Graph` 对象。

4. **Navisworks插件集成**:
    * **初始化**: 插件启动或模型更新时，执行上述预处理步骤，生成并加载路径图。
    * **寻路调用**:
        * 用户指定起点和终点（3D坐标）。
        * 将3D点映射到图中最邻近的节点。
        * 调用 `PathFinder.FindPath(startNode, endNode, graph)` 进行寻路。
    * **结果可视化**: 将A*返回的路径（节点序列）在Navisworks视图中绘制出来。

#### 2.3 优点

* 精度最高，能真实反映三维空间的可通行性。
* 为未来扩展（如多层物体、更复杂的避障规则）奠定坚实基础。
* 一次计算，多次高效寻路。

#### 2.4 缺点

* 开发复杂度最高，需要深入理解和使用Navisworks API进行空间计算。
* 预处理阶段计算量较大。

### 方案二：后处理校验与迭代修正 (快速验证)

#### 2.1 核心思路

保留现有二维投影寻路逻辑，但在得到路径后，增加一个三维碰撞检测步骤来校验路径的可行性，并根据结果进行修正或提示。

#### 2.2 实施步骤

1. **执行二维寻路**: 运行当前基于地面投影的A*算法，得到一条二维路径。
2. **三维碰撞检测**:
    * 遍历路径上的关键点或按固定步长取点。
    * 在每个点上，根据预设的物体尺寸，在三维空间中生成一个代表物体的包围盒（AABB或OBB）。
    * 利用Navisworks API的碰撞检测功能，检查此包围盒是否与模型中的任何构件发生碰撞。
3. **处理与反馈**:
    * **无冲突**: 路径可行，直接输出。
    * **有冲突**:
        * **简单处理**: 向用户提示“路径在XX处存在碰撞，可能不可行”。
        * **复杂处理 (迭代)**:
            a. 记录所有发生碰撞的点及其在二维投影平面上的区域。
            b. 将这些冲突区域在原始二维寻路网格中临时标记为“不可通行”。
            c. 重新调用二维A*算法进行寻路。
            d. 重复步骤2和3，直到找到一条无冲突路径或达到最大迭代次数。

#### 2.3 优点

* 对现有代码改动最小，实现快速。
* 可以快速验证思路。

#### 2.4 缺点

* 效果有限，可能无法找到真正可行的路径。
* “试错-修正”机制效率低，可能需要多次迭代。
* 无法保证找到最优解。

### 方案三：混合方法 - 3D障碍物投影融合 (推荐短期实施)

#### 3.1 核心思路

结合现有二维框架和部分Navisworks API能力。在预处理阶段识别三维障碍物，并将其在地面（或行驶平面）的投影区域从可通行区域中排除。

#### 3.2 实施步骤

1. **障碍物识别与投影 (Navisworks API 预处理)**:
    * 遍历模型，识别所有可能构成障碍的构件（管道、横梁等）。
    * 获取这些构件的三维包围盒。
    * 计算这些包围盒在地面（或预设行驶平面）上的**二维投影区域**。
2. **更新二维寻路网格**:
    * 在您当前用于二维寻路的网格基础上，增加一个“障碍物投影图层”。
    * 将上一步计算出的所有投影区域，在二维网格中标记为“不可通行”。
3. **执行二维寻路**:
    * 在寻路时，一个网格单元格被认为是“可通行”的，当且仅当它在原始“地面可达性图”中是可达的，并且在“障碍物投影图层”中未被标记为不可通行。
    * 调用现有的Roy-T.AStar `Grid` 寻路功能。

#### 3.3 优点

* 实现相对简单，对现有架构改动较小。
* 能有效解决当前最主要的问题（空中障碍物投影导致的误判）。
* 开发周期短，可作为从方案二到方案一的过渡。

#### 3.4 缺点

* 精度低于方案一（例如，无法处理非垂直投影的复杂障碍物，或不同高度层的障碍物）。
* 仍然是基于二维的近似方法。

## 3. 推荐与实施计划

1. **短期 (验证与快速迭代)**: 实施 **方案三**。这能以最小的代价解决当前最紧迫的问题，验证思路。
2. **中期 (功能完善)**: 在方案三稳定后，评估其局限性。如果场景复杂度增加，开始规划 **方案一** 的开发。
3. **长期 (终极目标)**: 实施 **方案一**，构建完整的3D空间分析能力，为插件提供最强大、最精确的路径规划内核。
