You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
LightWork3D/docs/2D-3D交换协议.md

455 lines
10 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 2D / 3D 交换协议(第一版)
本文档只描述 **QET 与 FreeCAD 之间的 JSON 交换格式**
不负责描述:
- 数据库建表
- 数据库存储约束
- 旧表兼容策略
这些内容统一放在:
- [数据库设计.md](D:\project\LightWork3D\FreeCAD\docs\数据库设计.md)
---
## 1. 协议目标
第一版协议只解决下面这条最小闭环:
1. QET 能把当前项目中的设备实例和端子实例导出给 FreeCAD
2. FreeCAD 能根据导出结果创建或更新 3D 设备实例
3. FreeCAD 能根据导出结果创建或更新 3D 端子对象
4. FreeCAD 保存后,能把最小回写结果再交还给 QET
当前版本明确采用:
- **文件交换**
- **JSON 格式**
当前版本明确不采用:
- 实时 RPC
- HTTP API
- 直接双向数据库同步
---
## 2. 交换文件位置建议
建议所有交换文件都放到项目目录下:
```text
<ProjectRoot>/.qet_freecad/
2d_to_3d.json
3d_to_2d.json
scene.FCStd
logs/
```
含义:
- `2d_to_3d.json`QET 导出给 FreeCAD 的输入快照
- `3d_to_2d.json`FreeCAD 回写给 QET 的结果快照
- `scene.FCStd`:该项目对应的 FreeCAD 3D 工程
---
## 3. 第一版 `2d_to_3d.json` 设计原则
### 3.1 最小主键集
第一版最小主键集只认:
- `project_uuid`
- `element_uuid`
- `terminal_uuid`
- `instance_id`
### 3.2 数据来源
`2d_to_3d.json` 不是数据库整表导出,而是:
> 从 QET 当前项目状态中整理出的、面向 FreeCAD 使用的最小交换快照。
也就是说:
- 它可以来自数据库
- 也可以来自当前内存状态
- 但最终输出是给 FreeCAD 消费的统一协议格式
### 3.3 协议可以比数据库稍微丰富
数据库设计要求尽量去冗余。
但 JSON 交换协议可以为了:
- 降低 FreeCAD 读取复杂度
- 提升可调试性
- 避免 FreeCAD 再回查 QET 内部数据库
而适当带上一些“已解析数据”。
这不等于数据库必须保留这些字段。
---
## 4. 第一版 `2d_to_3d.json` 顶层结构
推荐结构:
```json
{
"schema_version": "1.1",
"project_uuid": "string",
"generated_at": "2026-05-18T10:30:00+08:00",
"source": {
"app": "QET",
"version": "string"
},
"cabinet": {},
"devices": [],
"terminals": [],
"device_models": []
}
```
说明:
- `schema_version`:协议版本,便于后续兼容升级
- `project_uuid`:项目主键
- `generated_at`:导出时间
- `source`:导出来源信息
- `cabinet`:当前图纸属性中绑定的机柜信息
- `devices`:设备实例绑定
- `terminals`:端子实例绑定
- `device_models`:设备 3D 模型解析结果
---
## 5. `cabinet` 结构
### 5.1 作用
当前版本仍然以 **图纸** 作为交换单位。
但图纸属性本身已经绑定了一个机柜,因此 `2d_to_3d.json` 顶层会额外带上:
> 当前图纸绑定的机柜信息
这样 FreeCAD 在保持“按图纸导入设备/端子”的同时,也能知道:
- 这批设备属于哪个机柜
- 这个机柜当前绑定了哪个 3D 相对路径
### 5.2 推荐字段
```json
{
"location_id": 12,
"label": "C",
"name": "电容柜",
"display_text": "C - 电容柜",
"associated_fileset": "电容柜文件集",
"three_d_relative_path": "3D/Cabinets/C.FCStd",
"resolved_scene_path": "C:/Users/Admin/Documents/MingTuProject/xxx/3D/Cabinets/C.FCStd"
}
```
### 5.3 字段说明
| 字段 | 中文 | 必需 | 说明 |
| --- | --- | --- | --- |
| `location_id` | 机柜位置ID | 否 | 当前图纸属性绑定的机柜位置 ID |
| `label` | 机柜标注 | 否 | 用于 3D 侧快速识别机柜 |
| `name` | 机柜名称 | 否 | 机柜名称 |
| `display_text` | 机柜显示文本 | 否 | 等价于 QET 图纸属性界面中看到的机柜显示文本 |
| `associated_fileset` | 关联文件集 | 否 | 当前机柜位置绑定的文件集信息 |
| `three_d_relative_path` | 3D 相对路径 | 否 | 相对于工程目录保存的 3D 机柜路径 |
| `resolved_scene_path` | 已解析机柜场景路径 | 否 | QET 已解析出的本地场景文件路径,便于 FreeCAD 直接使用 |
### 5.4 说明
- `cabinet` 是一个 **图纸级上下文对象**
- 它不是设备绑定表或端子绑定表的扩张
- 它只描述“当前图纸绑定了哪个机柜,以及机柜当前对应哪个 3D 文件”
---
## 6. `devices` 结构
### 6.1 作用
`devices` 负责表达:
> 一个 2D 设备实例,对应哪个 3D 设备实例。
### 6.2 第一版字段
```json
{
"element_uuid": "string",
"instance_id": "string",
"display_tag": "string"
}
```
### 6.3 字段说明
| 字段 | 中文 | 必需 | 说明 |
| --- | --- | --- | --- |
| `element_uuid` | 2D设备实例UUID | 是 | QET 图纸中的设备实例主键 |
| `instance_id` | 3D实例ID | 是 | FreeCAD 侧设备实例主键 |
| `display_tag` | 2D设备实例标注 | 否 | JSON 显示辅助字段,优先使用 2D 中设备标注作为 FreeCAD 树标签;为空时再退回 `instance_id` / `element_uuid` |
### 6.4 说明
- 如果第一次进入 3D 时还没有 `instance_id`,允许先导出空字符串或缺省值
- FreeCAD 创建 3D 实例后,再在回写阶段补齐
- `display_tag` 不进入第一版数据库最小字段集,它只存在于交换 JSON 中,用来让 3D 树视图与 2D 标注更容易对上
---
## 7. `terminals` 结构
### 7.1 作用
`terminals` 负责表达:
> 一个 2D 端子实例,属于哪个 3D 设备实例。
### 7.2 第一版字段
```json
{
"terminal_uuid": "string",
"instance_id": "string",
"element_uuid": "string"
}
```
### 7.3 字段说明
| 字段 | 中文 | 必需 | 说明 |
| --- | --- | --- | --- |
| `terminal_uuid` | 2D端子UUID | 是 | QET 端子实例主键 |
| `instance_id` | 3D实例ID | 是 | 该端子所属的 3D 设备实例 |
| `element_uuid` | 2D设备实例UUID | 否 | JSON 导入辅助字段,帮助 FreeCAD 在首次没有 `instance_id` 时仍能知道端子属于哪个设备 |
### 7.4 为什么这里允许带 `element_uuid`
注意:
- `element_uuid` **不是**第一版端子绑定表的数据库字段扩张
- 它只是交换 JSON 中的上下文辅助字段
原因:
- 当某些设备第一次进入 3D、暂时还没有 `instance_id`
- FreeCAD 仍需要知道该端子属于哪个 2D 设备实例
所以这里允许 JSON 比数据库稍微丰富一些。
### 7.5 为什么第一版不带更多字段
第一版先不强制包含:
- `terminal_key`
- `connection_point_key`
- `symbol_terminal`
- `wire_label`
- `net_id`
原因:
- 这些字段当前都不是 FreeCAD 第一版创建端子对象的硬前提
- 端子语义可以通过 `terminal_uuid` 回查 QET
- 先把绑定关系打通,比先堆字段更重要
---
## 8. `device_models` 结构
### 8.1 作用
`device_models` 不是绑定表本身,而是:
> QET 在导出时,顺手把设备对应 3D 模型资源解析出来,减少 FreeCAD 再回查 QET 内部数据库的复杂度。
### 8.2 第二步设备导入推荐字段
```json
{
"element_uuid": "string",
"device_id": 123,
"parts_3d": "string",
"resolved_model_path": "string"
}
```
### 8.3 字段说明
| 字段 | 中文 | 必需 | 说明 |
| --- | --- | --- | --- |
| `element_uuid` | 2D设备实例UUID | 是 | 与 `devices` 关联 |
| `device_id` | 设备类型ID | 否 | QET 设备主数据 ID |
| `parts_3d` | 3D模型资源URI | 否 | 原始资源引用,来自 `device_3d_asset.uri``device_attribute.parts_3d` |
| `resolved_model_path` | 已解析模型路径 | 是 | QET 已经解析好的本地模型文件路径FreeCAD 第二步直接用它导入 STEP / FCStd |
### 8.4 为什么 `resolved_model_path` 是第二步关键字段
第二步开始FreeCAD 不再只做 JSON 校验,而要真正导入设备模型。
如果没有 `resolved_model_path`FreeCAD 就必须自己理解和回查:
1. `element_uuid`
2. `device_id`
3. `device_3d_asset`
4. `device_attribute.parts_3d`
5. 本地路径解析规则
这会让 FreeCAD 过度耦合 QET 内部数据库结构。
所以第二步推荐由 QET 在导出时直接给出:
- `resolved_model_path`
让 FreeCAD 只负责消费结果。
### 7.4 为什么这里允许同时带 `parts_3d`
注意:
- **数据库设计**里我们已经决定不在绑定表冗余保存 `asset_uri`
- 但**交换协议**里允许带 `parts_3d`
原因是:
- JSON 是导出快照
- 不是绑定数据库本身
- 这样 FreeCAD 读取时更简单
也就是说:
> 数据库去冗余
> JSON 可适度带已解析结果
---
## 8. 第一版 `2d_to_3d.json` 完整样例
```json
{
"schema_version": "1.0",
"project_uuid": "proj-001",
"generated_at": "2026-05-18T10:30:00+08:00",
"source": {
"app": "QET",
"version": "1.0"
},
"devices": [
{
"element_uuid": "elem-1001",
"instance_id": "fc-inst-0001"
}
],
"terminals": [
{
"terminal_uuid": "term-2001",
"instance_id": "fc-inst-0001",
"element_uuid": "elem-1001"
},
{
"terminal_uuid": "term-2002",
"instance_id": "fc-inst-0001",
"element_uuid": "elem-1001"
}
],
"device_models": [
{
"element_uuid": "elem-1001",
"device_id": 123,
"parts_3d": "models/mccb/model.step",
"resolved_model_path": "C:/Users/Admin/Documents/MingTuProject/models/mccb/model.step"
}
]
}
```
---
## 9. 第一版 `3d_to_2d.json` 建议
第一版回写建议同样保持最小化。
推荐结构:
```json
{
"schema_version": "1.0",
"project_uuid": "string",
"generated_at": "2026-05-18T11:00:00+08:00",
"instances": [],
"terminals": []
}
```
### 9.1 `instances`
```json
{
"element_uuid": "string",
"instance_id": "string"
}
```
### 9.2 `terminals`
```json
{
"terminal_uuid": "string",
"instance_id": "string"
}
```
### 9.3 说明
第一版不回写:
- 3D 位姿
- 装配层级
- 几何路径
- 线槽信息
这些仍以 FreeCAD 文档为准。
---
## 10. 第一版推荐交互流程
1. 用户在 QET 中点击 `3D视图`
2. QET 生成 `2d_to_3d.json`
3. QET 打开 FreeCAD并打开 `scene.FCStd`
4. FreeCAD 读取 `2d_to_3d.json`
5. FreeCAD 创建或更新:
- 3D 设备实例
- 3D 端子对象
6. 用户在 FreeCAD 中完成装配和接线
7. 用户保存 FreeCAD 工程
8. FreeCAD 生成 `3d_to_2d.json`
9. QET 在后续时机读取 `3d_to_2d.json`
---
## 11. 当前推荐结论
第一版协议建议明确分层:
- **数据库设计**:尽量去冗余
- **JSON 协议**:允许带少量已解析结果,方便 FreeCAD 使用
一句话总结:
> 第一版先把 `2d_to_3d.json` 做成“面向 FreeCAD 的最小项目快照”,而不是数据库整表镜像。