# 快速取面工具设计 创建时间:2026-06-02 ## 目标 新增一个独立 ToolPlugin,通过单点+像素邻域法快速推断鼠标点击位置所在面的法向量。 和取点工具 `PathClickToolPlugin` 并列,互斥激活。 ## 核心算法 单点+像素邻域法 —— 一次点击内做三次 `PickItemFromPoint`: ``` 中心点: PickItemFromPoint(x, y) → p0 右邻域: PickItemFromPoint(x+δ, y) → p1 下邻域: PickItemFromPoint(x, y+δ) → p2 v1 = p1 - p0 v2 = p2 - p0 normal = normalize(cross(v1, v2)) ``` 偏移量 δ 三级递进:2px → 5px → 10px,小偏移共线时自动退到更大偏移。 ## 新增文件 | 文件 | 职责 | |---|---| | `src/Models/FaceInferResult.cs` | 结果数据类 | | `src/Core/FaceInferToolPlugin.cs` | ToolPlugin 主体 | 不修改任何现有文件。 ## 架构 ``` FaceInferToolPlugin : ToolPlugin │ ├── Plugin("FaceInferTool", "NavisworksTransport") │ ├── Static 成员 │ ├── event FaceInferred # 外部订阅事件 │ ├── AssemblyPath # 用于动态加载 │ └── TriggerFaceInferred() # 允许外部手动触发 │ ├── GetCursor → Cursor.MarkupQuickPick │ ├── MouseDown(x, y) │ ├── centerPick = PickItemFromPoint(x, y) │ ├── rightPick = PickItemFromPoint(x + δ, y) │ ├── downPick = PickItemFromPoint(x, y + δ) │ ├── 同构件校验 (ModelItem 比较) │ ├── 共线校验 (cross.Length < 0.001 → 退到下一级 δ) │ ├── 法向量归一化 │ ├── 朝向统一 (dot with viewDir, 始终指向相机) │ └── 触发 FaceInferred 事件 │ └── MouseMove → 暂不处理(轻量原则) ``` ## FaceInferResult 数据结构 ```csharp public class FaceInferResult { public Point3D HitPoint { get; } // 命中点(宿主坐标系) public Vector3D Normal { get; } // 面法向量(已归一化,朝向相机) public ModelItem ModelItem { get; } // 命中的 ModelItem public bool IsValid { get; } // 推断是否成功 } ``` 所有坐标均为**宿主坐标系**(`PickItemFromPoint` 原始输出)。 ## 激活方式 与 `PathClickToolPlugin` 完全相同的流程,仅插件名不同: ```csharp var assemblyPath = FaceInferToolPlugin.AssemblyPath; Application.Plugins.AddPluginAssembly(assemblyPath); var record = (ToolPluginRecord)Application.Plugins.FindPlugin("FaceInferTool.NavisworksTransport"); var plugin = record.LoadPlugin(); Application.MainDocument.Tool.SetCustomToolPlugin(plugin); ``` ## 光标 使用 `Cursor.MarkupQuickPick`。Navisworks `Cursor` 枚举无平行四边形,此为最接近的选项。 ## 与 PathClickToolPlugin 的关系 - 两者都是 `ToolPlugin`,同一时刻只有一个激活 - 互斥切换:取面时取点失活,取面结束切回取点 - 切换流程与项目中已有的「导航工具 ↔ ClickTool」切换模式一致 ## 暂不实现 | 项目 | 原因 | |---|---| | 透视近大远小动态 δ 调整 | 先验证精度,不够再加 | | 跨面距离检测 (maxDist) | 同构件判断已覆盖基本场景 | | 曲面曲率分析 | 不同业务需求 | | MouseMove 实时预览 | 保持轻量 | ## 下一步 1. 实现两个新文件 2. 在已知平面上验证法向量精度(误差应在 1° 以内) 3. 后续由调用方(ViewModel)按需集成激活/切换逻辑