# FreeCAD 3D 模型端子设计方案 ## 1. 目标 本文档定义电气设备 3D 模型上的“端子”如何设计、保存、生成和参与布线。 当前正式路线固定为: ```text STEP / STP / STE 原始几何 -> FreeCAD 添加模板端子 -> 保存为 FCStd 设备模板 -> QET 绑定该 FCStd 作为设备 3D 资产 -> 3D 视图打开 FreeCAD -> FreeCAD 从模板端子生成工程端子 -> 工程端子参与 3D 手动布线 ``` STEP / STP / STE 只作为几何输入。正式可复用的电气 3D 设备资产是 `.FCStd`。 ## 2. 名词约定 ### 2.1 端子 本文档统一使用“端子”作为电气设备上可接线位置的名称。 在不同软件或资料中,它也可能被称为: - 接线端子 - 接线点 - 连接点 - terminal - connection terminal 后续代码和文档尽量使用“端子”,避免继续使用泛化的 `connectionPoint` 作为正式设计依据。 ### 2.2 模板端子 模板端子存在于设备模板 `.FCStd` 中,表示“这个设备模型上哪里可以接线”。 模板端子是跨工程复用的槽位,不属于某一个具体项目。 例如电流互感器模板可以有: ```text 电流互感器.FCStd Body / imported geometry Terminal_P1 Terminal_P2 ``` `Terminal_P1` 和 `Terminal_P2` 是 FreeCAD LCS 对象。它们的位置表示真实接线位置,方向表示后续出线方向。 ### 2.3 工程端子 工程端子存在于具体项目的 `scene.FCStd` 中,表示“当前工程中某个设备实例上的可布线端子”。 工程端子从模板端子生成。它继承模板端子的位置、方向和槽位语义,同时补上当前工程的设备实例信息。 如果 QET 已传入真实 `terminal_uuid`,工程端子可以和 2D 端子准确绑定。如果 QET 没有传入 `terminal_uuid`,FreeCAD 只能生成本地 3D 工程端子,用于 3D 手动布线验证,不能可靠回写到 QET 2D 端子。 ## 3. 模板端子设计 模板端子使用 FreeCAD LCS 表示,推荐类型: ```text Part::LocalCoordinateSystem PartDesign::CoordinateSystem ``` 模板端子至少保存: | 属性 | 说明 | | --- | --- | | `Role = "Terminal"` | 标识该 LCS 是端子 | | `CanWire = true` | 表示该端子允许接线 | | `QetTemplateSlotName` | 模板内稳定槽位名,例如 `P1`、`P2`、`A1` | | `QetTerminalLabel` | 显示名称,可与槽位名一致 | | `QetTerminalType` | 端子类型,例如 `generic`、`primary`、`power`、`control` | | `Placement.Base` | 端子在设备模板局部坐标系中的位置 | | `Placement.Rotation` | 端子方向,默认把 LCS 本地 +Z 作为出线方向 | 模板端子禁止保存: ```text QetProjectUuid QetElementUuid QetTerminalUuid QetInstanceId ``` 原因是这些字段属于某个具体工程。如果写进模板,同一个设备模板传给别人或放到另一个工程里就会污染绑定关系。 ## 4. 工程端子设计 工程端子同样使用 LCS 表示,但它属于当前工程。 工程端子至少保存: | 属性 | 说明 | | --- | --- | | `QetProjectUuid` | 当前项目 UUID | | `QetElementUuid` | 2D 设备实例 UUID | | `QetInstanceId` | 3D 设备实例 ID | | `QetTerminalUuid` | QET 2D 端子 UUID;没有 QET 绑定时可使用 `local:*` 本地 UUID | | `Role = "Terminal"` | 标识为端子 | | `CanWire = true` | 允许被手动布线命令选择 | | `QetTemplateSlotName` | 来源模板槽位名 | 工程端子创建后放在设备组下面: ```text QETExchangeDevices QETDevice_ imported model objects QETTerminals_ P1 P2 ``` 手动布线命令只允许选择工程端子,不应该直接连接模板端子。 ## 5. 端子方向 端子方向对后续手动布线和自动布线都很重要。 当前约定: ```text LCS 本地 +Z 方向 = 端子出线方向 ``` 例如模板端子 `P1` 的 LCS 放在接线孔中心,LCS 的 +Z 指向电线离开设备的方向。后续手动布线或自动布线可以先沿该方向生成一小段出线段,再进入线槽或自由走线路径。 如果第一版模板制作界面暂时只能准确放置位置,方向可以先用默认方向;但正式设备模板最终应补齐方向,否则后续布线容易出现电线穿过设备或从错误方向出线。 ## 6. 自动生成工程端子规则 QET 点击 `3D视图` 打开 FreeCAD 后,FreeCAD 可以自动创建工程端子,但必须满足条件: 1. `2d_to_3d.json` 中存在端子数据。 2. 端子数据至少有 `terminal_uuid` 和 `instance_id`。 3. FreeCAD 能通过 `instance_id` 找到对应设备实例。 4. 该设备实例导入的 `.FCStd` 内有模板端子。 如果设备没有模板端子,FreeCAD 不自动凭空生成工程端子。 这样做是为了避免把端子生成在错误位置。没有模板端子的设备,应先补模板端子,或者由用户在 FreeCAD 中手动建立模板端子后再保存成新的 `.FCStd`。 ## 7. 手动生成工程端子规则 当 QET 没有传端子数据,或者某些设备没有自动生成工程端子时,用户可以在 FreeCAD 中手动生成工程端子。 推荐操作: 1. 在树目录中选中 `QETDevice_xxx` 设备组。 2. 点击 `QET模板 -> 生成工程端子`。 3. FreeCAD 扫描该设备里的模板端子。 4. 按模板端子的位置、方向和槽位名生成工程端子。 5. 工程端子放入该设备下的 `QETTerminals_xxx` 分组。 如果不选设备,命令可以尝试处理当前工程中所有 `QETDevice_xxx`。 手动生成工程端子时必须优先以模板端子为准,不能再用设备包围盒猜测端子位置。 如果没有 QET 真实 `terminal_uuid`,手动生成的工程端子使用本地 UUID: ```text local:: ``` 这种端子可以用于 3D 手动布线,但不能当作 QET 2D 端子的可靠回写依据。 ## 8. QET 数据传输责任边界 QET/zh 侧负责把 2D 端子和 3D 设备实例的绑定关系传给 FreeCAD。 第一版必须传: ```json { "terminal_uuid": "2d-terminal-uuid", "instance_id": "3d-device-instance-id", "element_uuid": "2d-device-element-uuid" } ``` 其中: - `terminal_uuid` 是 2D 端子主键,也是第一版端子绑定唯一依据。 - `instance_id` 表示该 2D 端子属于哪个 3D 设备实例。 - `element_uuid` 可帮助 FreeCAD 定位父设备,但第一版端子绑定仍以 `terminal_uuid` 为核心。 QET 不需要解析 `.FCStd` 内部 LCS,也不需要计算端子坐标。端子空间位置由 FreeCAD 模板负责。 后续如果需要更准确地把 2D 端子匹配到模板槽位,可以在交换 JSON 里增加非主键提示字段,例如: ```json { "terminal_uuid": "2d-terminal-uuid", "instance_id": "3d-device-instance-id", "slot_name_hint": "P1", "terminal_label": "P1" } ``` 这些字段只能作为匹配提示,不能替代 `terminal_uuid`。 当前 FreeCAD 侧已经支持用 `slot_name_hint` 或 `terminal_label` 优先匹配模板槽位,再退回顺序匹配。也就是说,zh 侧后续只要把端子提示名补上,FreeCAD 就能更稳定地把 2D 端子落到正确的模板端子上。 ## 9. 与布线的关系 手动布线连接的是工程端子,不是模板端子。 完整关系是: ```text 模板端子 -> 定义设备上哪里能接线 -> 提供局部坐标和出线方向 工程端子 -> 从模板端子生成 -> 绑定当前工程设备实例 -> 带 QET terminal_uuid 或 local UUID -> 被手动布线命令选择 导线 -> 连接两个工程端子 -> 起点和终点记录端子 UUID -> 路径几何保存在 scene.FCStd ``` 工程端子位置应跟随设备移动。实现上,工程端子挂在设备组下,并使用模板端子的局部坐标;计算布线路径时再取端子的全局坐标。 ## 10. 当前不采用的方案 ### 10.1 不把 STEP 当成最终电气资产 STEP 可以稳定保存几何,但不能可靠保存 FreeCAD LCS、动态属性、端子角色和接线资格。因此 STEP 只作为制作模板的输入。 ### 10.2 不依赖 `connectionPoint` 已有代码或旧文档中的 `connectionPoint` 可以作为历史参考,但当前正式端子方案不以它为核心。正式方案统一使用 FreeCAD 模板端子和工程端子。 ### 10.3 不再用 bbox fallback 作为正式端子 包围盒猜点容易把端子放到错误位置。当前正式方案中,设备没有模板端子时不自动创建工程端子。需要先补模板端子,或者由用户明确手动创建。 ## 11. 当前开发下一步 下一步优先做“工程端子生成和可验证流程”,不是继续扩大模板工具范围。 建议顺序: 1. 保持模板端子默认隐藏,只显示工程端子。 2. `生成工程端子` 命令只从模板端子生成工程端子。 3. 没有模板端子的设备不自动生成工程端子,并给出清晰提示。 4. 有 QET `terminal_uuid` 的端子生成真实工程端子。 5. 没有 QET `terminal_uuid` 但用户手动生成时,生成 `local:*` 本地工程端子。 6. 手动布线只允许连接工程端子。 7. `3d_to_2d.json` 回写时区分真实 QET 端子和本地端子,本地端子不作为 2D 绑定结果。 ## 12. 验收标准 第一版验收以电流互感器为例: 1. 从 STEP 制作 `电流互感器.FCStd`。 2. 模板中有 `P1`、`P2` 模板端子。 3. QET 绑定该 `.FCStd`。 4. QET 点击 `3D视图` 打开 FreeCAD。 5. FreeCAD 能导入设备模型。 6. 选中设备执行 `生成工程端子` 后,工程端子落在模板端子位置。 7. 移动设备后,工程端子跟随设备移动或能正确计算全局位置。 8. 选择两个设备上的工程端子可以创建手动导线。 9. 保存后重新打开,设备、工程端子和导线仍存在。 10. 如果 QET 提供真实 `terminal_uuid`,`3d_to_2d.json` 中能回写端子绑定;如果是 `local:*` 端子,则只用于 3D 本地布线。