NavisworksTransport/doc/design/2026/face-infer-tool-design.md
tian c7a1eeebb8 feat: add FaceInferToolPlugin - single-click face normal inference tool
- New FaceInferToolPlugin: pixel-neighborhood method with {2,5,10}px offsets
- New FaceInferResult data class
- Test button in SystemManagement page
- Cursor: MarkupAutoPoly (arrow + dashed box)
- Uses project-standard tools: FindNamedParentContainer, viewpoint.Position
- Design doc at doc/design/2026/face-infer-tool-design.md
2026-06-02 23:11:11 +08:00

3.4 KiB
Raw Blame History

快速取面工具设计

创建时间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 数据结构

public class FaceInferResult
{
    public Point3D HitPoint { get; }    // 命中点(宿主坐标系)
    public Vector3D Normal { get; }      // 面法向量(已归一化,朝向相机)
    public ModelItem ModelItem { get; }  // 命中的 ModelItem
    public bool IsValid { get; }         // 推断是否成功
}

所有坐标均为宿主坐标系PickItemFromPoint 原始输出)。

激活方式

PathClickToolPlugin 完全相同的流程,仅插件名不同:

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按需集成激活/切换逻辑