feature/更新文档-zh-0518

csm
zhanghao 1 week ago
parent d315f500e3
commit 45fdeba1d1

@ -0,0 +1,39 @@
Rules:
- 涉及 QET <-> FreeCAD 协同开发前,先阅读 `D:\project\LightWork3D\FreeCAD\docs\数据库设计.md`
- 第一版 2D/3D 协同只允许使用这两张绑定表:
- `project_2d3d_symbol_binding`
- `project_2d3d_terminal_binding`
- 第一版禁止依赖这些 Legacy 表:
- `project_3d_scene_instance`
- `project_3d_space_object`
- `project_2d3d_link`
- `start_end_terminal_matches`
- 第一版禁止假定 3D 位姿保存在数据库中3D 位姿和装配状态以 FreeCAD 文档为准
- `device_attribute` 只作为设备类型主数据表使用,不承担 2D/3D 实例绑定职责
- 3D 模型资源绑定优先使用 `device_3d_asset``device_attribute.parts_3d` 仅允许作为兼容/回退字段
- `project_2d3d_symbol_binding` 第一版只允许依赖:
- `project_uuid`
- `element_uuid`
- `instance_id`
- `project_2d3d_terminal_binding` 第一版只允许依赖:
- `project_uuid`
- `terminal_uuid`
- `instance_id`
- 第一版禁止继续依赖这些字段:
- `source_diagram_uuid`
- `scene_diagram_uuid`
- `device_id`
- `display_tag`
- `asset_uri`
- `host_binding_mode`
- `host_object_id`
- `host_object_type`
- `extra_json`
- `binding_key`
- `symbol_terminal`
- `terminal_key`
- `connection_point_key`
- `wire_label`
- `net_id`
- `conductor_uuid`
- 第一版 3D 端子绑定唯一依据是 `terminal_uuid`

@ -0,0 +1,522 @@
# FreeCAD Windows 编译运行傻瓜指南
这份文档面向第一次在 Windows 上编译 FreeCAD 的同学。
目标是:
- 不改源码
- 用 Visual Studio 2022 成功编译
- 能在本机直接运行 FreeCAD
- 能在 VS 里按 `F5` 调试
本文档基于下面这套已经验证成功的组合:
- 源码分支:`releases/FreeCAD-1-1`
- 源码版本:`1.1.1-28-g94f4cb77f6`
- 编译器Visual Studio 2022
- 构建配置:`RelWithDebInfo | x64`
- LibPack`LibPack-1.1.0-v3.1.1.3-Release`
## 1. 先理解三个目录
编译 FreeCAD 时,最好把“源码目录”“构建目录”“运行目录”分开。
建议按下面这样放:
```text
D:\project\LightWork3D\FreeCAD 源码目录
E:\fc\LibPack-1.1.0-v3.1.1.3-Release 依赖目录
E:\fc\build-relwithdebinfo-libpack3113 构建目录
E:\fc\run-FreeCAD-1.1.1 安装后的运行目录
```
不要把所有东西都堆在一个目录里。
## 2. 需要安装的软件
至少准备好这些:
1. `Visual Studio 2022`
2. `Desktop development with C++` 工作负载
3. `CMake`
4. `Git`
建议:
- 用 64 位系统
- `E:` 盘最好预留 100GB 以上
- `C:``D:` 至少各留 30GB 可用空间
## 3. 下载源码
把 FreeCAD 源码放到:
```text
D:\project\LightWork3D\FreeCAD
```
如果你已经有源码,确认当前分支是:
```powershell
git -C D:\project\LightWork3D\FreeCAD rev-parse --abbrev-ref HEAD
```
应该看到:
```text
releases/FreeCAD-1-1
```
## 4. 下载完全匹配的 LibPack
这一步非常重要。
对于这份源码,不要随便换别的 LibPack。已经验证成功的是
[LibPack-1.1.0-v3.1.1.3-Release.7z](https://github.com/FreeCAD/FreeCAD-LibPack/releases/download/3.1.1.3/LibPack-1.1.0-v3.1.1.3-Release.7z)
下载后解压到:
```text
E:\fc\LibPack-1.1.0-v3.1.1.3-Release
```
不要用 `3.1.1.2`
这份源码配 `3.1.1.2` 时,已经实测会在链接阶段报 `boost::program_options ... contains` 相关错误。
## 5. 清理磁盘空间
如果你之前编过很多次,建议先清理旧构建目录。
重点清理这些“可再生目录”:
```text
旧 build 目录
旧 LibPack 目录
下载缓存
C:\Users\<你的用户名>\AppData\Local\Temp
C:\Windows\Temp
```
如果你在编译中看到下面这些错误:
```text
No space left on device
磁盘空间不足
无法创建目录
```
那不是源码问题,就是磁盘满了。
## 6. 新建构建目录
`E:` 盘新建目录:
```text
E:\fc\build-relwithdebinfo-libpack3113
```
## 7. 用 CMake 生成 VS 工程
打开 PowerShell执行
```powershell
$cmake = 'C:\CMake\bin\cmake.exe'
$src = 'D:\project\LightWork3D\FreeCAD'
$build = 'E:\fc\build-relwithdebinfo-libpack3113'
$libpack = 'E:\fc\LibPack-1.1.0-v3.1.1.3-Release'
$env:Path = @(
'C:\CMake\bin',
'D:\VisualStudio\MSBuild\Current\Bin',
'D:\VisualStudio\Common7\IDE',
'C:\Git\cmd',
'C:\Windows\System32',
'C:\Windows',
'C:\Windows\System32\Wbem',
'C:\Windows\System32\WindowsPowerShell\v1.0',
"$libpack\bin",
"$libpack\lib"
) -join ';'
& $cmake `
-S $src `
-B $build `
-G 'Visual Studio 17 2022' `
-A x64 `
-D FREECAD_LIBPACK_USE=ON `
-D FREECAD_LIBPACK_DIR=$libpack `
-D CMAKE_CONFIGURATION_TYPES=RelWithDebInfo
```
成功后会生成:
```text
E:\fc\build-relwithdebinfo-libpack3113\FreeCAD.sln
```
## 8. 编译前先记住一个坑
这套环境里,`TechDraw` 模块会触发 MSVC 的编译器堆空间不足:
```text
error C1060: 编译器的堆空间不足
```
这不是源码坏了。
解决办法是不改源码,只在编译时强制:
```text
/MP1
```
也就是让 `cl.exe` 单进程编译重模块。
## 9. 编译整个工程
继续在 PowerShell 里执行:
```powershell
$cmake = 'C:\CMake\bin\cmake.exe'
$build = 'E:\fc\build-relwithdebinfo-libpack3113'
$libpack = 'E:\fc\LibPack-1.1.0-v3.1.1.3-Release'
$env:Path = @(
'C:\CMake\bin',
'D:\VisualStudio\MSBuild\Current\Bin',
'D:\VisualStudio\Common7\IDE',
'C:\Git\cmd',
'C:\Windows\System32',
'C:\Windows',
'C:\Windows\System32\Wbem',
'C:\Windows\System32\WindowsPowerShell\v1.0',
"$libpack\bin",
"$libpack\lib"
) -join ';'
$env:_CL_ = '/MP1'
& $cmake --build $build --config RelWithDebInfo --target ALL_BUILD --parallel 1
```
说明:
- `--parallel 1` 是 MSBuild 外层单并发
- `_CL_=/MP1` 是 C/C++ 编译器内层单并发
这两个都保留,最稳。
## 10. 不要直接运行 build 目录里的 FreeCAD.exe
很多人编译成功后,第一反应是去点:
```text
E:\fc\build-relwithdebinfo-libpack3113\bin\RelWithDebInfo\FreeCAD.exe
```
这通常会报各种缺 DLL比如
- `xerces-c_3_2.dll`
- `icuuc74.dll`
- `boost_program_options-vc143-mt-x64-1_87.dll`
- `pyside6.abi3.dll`
- `shiboken6.abi3.dll`
原因不是没编好,而是它只是构建产物,不是整理好的运行目录。
## 11. 生成真正可运行的安装目录
编译完成后执行:
```powershell
$cmake = 'C:\CMake\bin\cmake.exe'
$build = 'E:\fc\build-relwithdebinfo-libpack3113'
$prefix = 'E:\fc\run-FreeCAD-1.1.1'
& $cmake --install $build --config RelWithDebInfo --prefix $prefix
```
执行完以后,真正建议运行的是:
```text
E:\fc\run-FreeCAD-1.1.1\bin\FreeCAD.exe
```
## 12. 推荐运行方式
推荐做法不是双击某个 `bat`,而是:
1. 先执行 `INSTALL`
2. 然后在 Visual Studio 里直接按 `F5`
这样有几个好处:
- 断点能直接生效
- 环境变量配置固定在 VS 里,不容易忘
- 每次改完代码后可以继续用同一套调试入口
运行时真正使用的程序是:
```text
E:\fc\run-FreeCAD-1.1.1\bin\FreeCAD.exe
```
## 13. 在 VS 中打开哪个目录
你在 Visual Studio 里要打开的是:
```text
E:\fc\build-relwithdebinfo-libpack3113
```
准确地说,是打开这个文件:
[E:\fc\build-relwithdebinfo-libpack3113\FreeCAD.sln](E:\fc\build-relwithdebinfo-libpack3113\FreeCAD.sln)
不要打开:
- `D:\project\LightWork3D\FreeCAD` 作为“编译入口”
- `E:\fc\run-FreeCAD-1.1.1` 作为“解决方案目录”
这两个都不是 VS 编译入口。
## 14. 在 VS 中怎样直接 F5 运行
### 14.1 启动工程
打开解决方案后:
1. 配置切到 `RelWithDebInfo | x64`
2. 右键 `FreeCADMain`
3. 选择“设为启动项目”
### 14.2 调试配置
打开:
`FreeCADMain -> 属性 -> 配置属性 -> 调试`
填写:
`命令`
```text
E:\fc\run-FreeCAD-1.1.1\bin\FreeCAD.exe
```
`工作目录`
```text
E:\fc\run-FreeCAD-1.1.1\bin
```
`环境`
```text
FREECAD_LIBPACK_BIN=E:\fc\LibPack-1.1.0-v3.1.1.3-Release\bin
PATH=E:\fc\LibPack-1.1.0-v3.1.1.3-Release\bin;E:\fc\LibPack-1.1.0-v3.1.1.3-Release\lib;E:\fc\LibPack-1.1.0-v3.1.1.3-Release\bin\Lib\site-packages\PySide6;E:\fc\LibPack-1.1.0-v3.1.1.3-Release\bin\Lib\site-packages\shiboken6;E:\fc\run-FreeCAD-1.1.1\bin;%PATH%
QT_PLUGIN_PATH=E:\fc\LibPack-1.1.0-v3.1.1.3-Release\plugins
QML2_IMPORT_PATH=E:\fc\LibPack-1.1.0-v3.1.1.3-Release\qml
```
配完以后,直接按 `F5`
注意:
- `FREECAD_LIBPACK_BIN` 这一行不要漏
- 它不是可有可无的变量
- 在 Windows + Python 3.12 下,很多模块会靠它触发 `os.add_dll_directory(...)`
- 如果漏掉它,程序本体可能能启动,但打开带 `Part`、`Measure`、`TechDraw`、`PartDesignGui` 的工程时会报 `DLL load failed while importing ...`
### 14.3 如果打开自带工程时报模块导入失败
如果你打开 FreeCAD 自带工程后,消息面板里出现类似这些错误:
```text
DLL load failed while importing Part
DLL load failed while importing Measure
DLL load failed while importing TechDraw
DLL load failed while importing PartDesignGui
Cannot create object 'Page'
Cannot create object 'Template'
Cannot create object 'Hatch'
```
先不要怀疑源码,也不要先改代码。
先检查下面 4 件事:
1. 你运行的是不是 `E:\fc\run-FreeCAD-1.1.1\bin\FreeCAD.exe`
2. 你是不是已经执行过 `INSTALL`
3. VS 调试环境里有没有 `FREECAD_LIBPACK_BIN=E:\fc\LibPack-1.1.0-v3.1.1.3-Release\bin`
4. `PATH` 里有没有 LibPack 的 `bin/lib`、PySide6、shiboken6、运行目录的 `bin`
这类报错在当前这套环境下绝大多数都属于“VS 调试环境没配完整”,不是源码本身坏了。
## 15. 每次改完代码后该怎么做
推荐顺序:
1. 在 VS 里编译你改动的项目
2. 再编一次 `ALL_BUILD`
3. 再执行一次 `INSTALL`
4. 在 VS 里按 `F5`
如果你不执行 `INSTALL`,运行目录里的文件可能不是最新的。
## 16. 常见错误和对应处理
### 错误 1`python312_d.lib` 找不到
原因:
- 你在编 `Debug`
- 但 LibPack 是 release 版
解决:
- 不要用 `Debug`
- 用 `RelWithDebInfo``Release`
### 错误 2`boost::program_options ... contains` 链接失败
原因:
- LibPack 版本不匹配
解决:
- 改用 `LibPack-1.1.0-v3.1.1.3-Release`
### 错误 3`No space left on device` / `磁盘空间不足`
原因:
- 盘满了
解决:
- 清理旧 build
- 清理旧 LibPack
- 清理 Temp
- 把构建目录移到 `E:`
### 错误 4`C1060 编译器的堆空间不足`
原因:
- `TechDraw` 太重
- 编译器内部并发太高
解决:
```powershell
$env:_CL_='/MP1'
cmake --build E:\fc\build-relwithdebinfo-libpack3113 --config RelWithDebInfo --target ALL_BUILD --parallel 1
```
### 错误 5直接双击 exe 提示缺 DLL
原因:
- 你点的是构建产物目录里的裸 `exe`
解决:
- 不要直接点 `build\bin\RelWithDebInfo\FreeCAD.exe`
- 先执行 `INSTALL`
- 然后在 VS 中把启动命令设为 `E:\fc\run-FreeCAD-1.1.1\bin\FreeCAD.exe`
- 并在 VS 调试配置里补好 `PATH`、`QT_PLUGIN_PATH`、`QML2_IMPORT_PATH`
### 错误 6打开自带工程时报 `DLL load failed while importing Part/Measure/TechDraw/PartDesignGui`
原因:
- 运行时不是源码坏了
- 而是 VS 的调试环境缺少关键变量
- 最常见的是漏掉 `FREECAD_LIBPACK_BIN`
解决:
- 确认已经执行过 `INSTALL`
- 在 VS 的调试环境中加入:
```text
FREECAD_LIBPACK_BIN=E:\fc\LibPack-1.1.0-v3.1.1.3-Release\bin
```
- 同时保留:
```text
PATH=E:\fc\LibPack-1.1.0-v3.1.1.3-Release\bin;E:\fc\LibPack-1.1.0-v3.1.1.3-Release\lib;E:\fc\LibPack-1.1.0-v3.1.1.3-Release\bin\Lib\site-packages\PySide6;E:\fc\LibPack-1.1.0-v3.1.1.3-Release\bin\Lib\site-packages\shiboken6;E:\fc\run-FreeCAD-1.1.1\bin;%PATH%
QT_PLUGIN_PATH=E:\fc\LibPack-1.1.0-v3.1.1.3-Release\plugins
QML2_IMPORT_PATH=E:\fc\LibPack-1.1.0-v3.1.1.3-Release\qml
```
说明:
- 这类问题通常可以通过环境配置解决
- 不需要先修改任何源码
## 17. 一套最终可复用的命令
### 生成工程
```powershell
$cmake = 'C:\CMake\bin\cmake.exe'
$src = 'D:\project\LightWork3D\FreeCAD'
$build = 'E:\fc\build-relwithdebinfo-libpack3113'
$libpack = 'E:\fc\LibPack-1.1.0-v3.1.1.3-Release'
$env:Path = @(
'C:\CMake\bin',
'D:\VisualStudio\MSBuild\Current\Bin',
'D:\VisualStudio\Common7\IDE',
'C:\Git\cmd',
'C:\Windows\System32',
'C:\Windows',
'C:\Windows\System32\Wbem',
'C:\Windows\System32\WindowsPowerShell\v1.0',
"$libpack\bin",
"$libpack\lib"
) -join ';'
& $cmake -S $src -B $build -G 'Visual Studio 17 2022' -A x64 -D FREECAD_LIBPACK_USE=ON -D FREECAD_LIBPACK_DIR=$libpack -D CMAKE_CONFIGURATION_TYPES=RelWithDebInfo
```
### 编译
```powershell
$env:_CL_='/MP1'
cmake --build E:\fc\build-relwithdebinfo-libpack3113 --config RelWithDebInfo --target ALL_BUILD --parallel 1
```
### 安装到运行目录
```powershell
cmake --install E:\fc\build-relwithdebinfo-libpack3113 --config RelWithDebInfo --prefix E:\fc\run-FreeCAD-1.1.1
```
### 运行
打开:
[E:\fc\build-relwithdebinfo-libpack3113\FreeCAD.sln](E:\fc\build-relwithdebinfo-libpack3113\FreeCAD.sln)
确认:
- 启动项目是 `FreeCADMain`
- 配置是 `RelWithDebInfo | x64`
- 已执行过 `INSTALL`
- 调试命令指向 `E:\fc\run-FreeCAD-1.1.1\bin\FreeCAD.exe`
然后按:
```text
F5
```
---
如果你严格按这份文档走,基于当前这份源码和这套 LibPack已经实测可以成功编译并运行。
如果后面换了源码分支,第一件事先确认:**LibPack 版本是不是还匹配。**

@ -701,3 +701,494 @@ LCS 不负责:
一句话总结: 一句话总结:
> 3D 端子不应只是几何点,而应是“有位置的 2D 电气语义映射节点”。 > 3D 端子不应只是几何点,而应是“有位置的 2D 电气语义映射节点”。
## 24. 阶段 A统一标识和数据口径
阶段 A 的目标不是先把 2D/3D 联动界面做出来,而是先把“双方到底在说谁”这件事说清楚。
如果这一阶段没有先定死,后面最容易出现的问题是:
- 2D 里的设备实例和 3D 里的设备实例靠显示名硬猜
- 端子编号改一次,绑定关系全部漂移
- 同一个对象在数据库、3D 文档、界面显示里分别有三套名字
- 回写数据时不知道应该更新哪一条记录
所以阶段 A 的交付物应该是:
- 一份统一字段清单
- 一份主键和唯一性约定
- 一份“谁是主数据源”的边界说明
- 一份最小同步记录样例
### 24.1 阶段 A 的范围
阶段 A 先不做下面这些事:
- 不做 FreeCAD 端子对象代码
- 不做自动装配
- 不做自动路由
- 不做 2D/3D 双向实时联动
阶段 A 只回答四个问题:
1. 设备怎么唯一识别
2. 端子怎么唯一识别
3. 2D 和 3D 之间靠哪些字段绑定
4. 哪些字段由 2D 负责,哪些字段由 3D 负责
### 24.2 总体原则
建议在阶段 A 固定下面四条原则:
1. 电气语义真相源在 2D
2. 空间位姿真相源在 3D
3. 绑定靠稳定 ID不靠显示名称
4. 一个字段只定义一个主责任方,避免双写冲突
也就是说:
- 2D 负责定义“这是什么设备、这是什么端子、它属于哪个网络”
- 3D 负责定义“这个设备装在哪里、这个端子在空间里具体在哪”
### 24.3 阶段 A 推荐统一字段
建议第一版统一下面这组字段名。后续无论走 SQLite、JSON、还是接口对象都尽量保持同名。
#### 24.3.1 项目级字段
- `project_uuid`
- `project_name`
- `source_diagram_uuid`
- `scene_diagram_uuid`
含义建议:
- `project_uuid`:整个项目唯一标识
- `project_name`:项目显示名称,不参与绑定主键
- `source_diagram_uuid`2D 原理图/来源图纸唯一标识
- `scene_diagram_uuid`3D 场景或 3D 视图唯一标识
#### 24.3.2 设备级字段
- `element_uuid`
- `instance_id`
- `device_id`
- `display_tag`
- `asset_uri`
- `layout_2d_diagram`
- `host_object_id`
- `host_object_type`
含义建议:
- `element_uuid`2D 元件实例唯一标识
- `instance_id`3D 设备实例唯一标识
- `device_id`:设备类型或库元件标识
- `display_tag`:界面显示标签,例如 `QF1`
- `asset_uri`3D 资产路径或 3D 资源定位符
- `layout_2d_diagram`2D 布局图标识
- `host_object_id`3D 中的宿主对象标识,例如某导轨、安装板、柜体分区
- `host_object_type`:宿主对象类型,例如 `Rail`、`Panel`、`Cabinet`
#### 24.3.3 端子级字段
- `terminal_uuid`
- `terminal_key`
- `symbol_terminal`
- `connection_point_key`
- `terminal_direction`
- `terminal_type`
- `wire_label`
- `net_id`
含义建议:
- `terminal_uuid`2D 端子实例唯一标识
- `terminal_key`:设备内部端子业务键,例如 `QF1:13`
- `symbol_terminal`:图纸显示端子号,例如 `13`
- `connection_point_key`3D 连接点键,例如设备模型中的 `cp_13`
- `terminal_direction`:端子方向/进出方向语义
- `terminal_type`:端子类型语义
- `wire_label`:当前线号/导线标签
- `net_id`:网络唯一标识
### 24.4 推荐主键和唯一性约定
建议在阶段 A 先把“哪个字段必须稳定、哪个字段只是显示用途”彻底分开。
#### 24.4.1 只做显示用途,不可作为绑定主键
下面这些字段不建议直接作为绑定主键:
- `project_name`
- `display_tag`
- `symbol_terminal`
- 任何中文名称
- 任何模型树显示名称
原因很简单:
- 这些字段可能会被人工修改
- 它们有显示意义,但不一定有全局唯一性
- 一旦改名,绑定关系会断
#### 24.4.2 推荐的主键约定
建议按下面规则理解:
- 设备绑定主键:`project_uuid + element_uuid`
- 3D 设备实例主键:`project_uuid + instance_id`
- 端子绑定主键:`project_uuid + terminal_uuid`
- 3D 连接点主键:`project_uuid + instance_id + connection_point_key`
如果需要业务可读键,可以再保留:
- `terminal_key = <display_tag>:<symbol_terminal>`
但这个可读键建议作为辅助字段,不代替 `terminal_uuid`
### 24.5 一对一 / 一对多关系约定
阶段 A 建议先把关系收紧,不要一开始就支持太多复杂映射。
第一版建议:
- 一个 `element_uuid` 对应一个 3D `instance_id`
- 一个 `terminal_uuid` 对应一个 3D 端子对象
- 一个 3D 端子对象对应一个 `connection_point_key`
这意味着第一版先按最稳的模型来:
- 一个 2D 设备实例,只落成一个 3D 设备实例
- 一个 2D 端子,只绑定一个 3D 连接点
后续如果要支持:
- 一符号多模型
- 一端子多连接点
- 跳线桥接
再在阶段 B/C 之后扩展,不建议在阶段 A 就放开。
### 24.6 2D 与 3D 的职责边界
为了避免双向覆盖,建议把字段责任按下面方式固定。
#### 24.6.1 由 2D 负责的字段
- `project_uuid`
- `source_diagram_uuid`
- `element_uuid`
- `device_id`
- `display_tag`
- `terminal_uuid`
- `terminal_key`
- `symbol_terminal`
- `wire_label`
- `net_id`
- 端子类型、端子方向、电气属性
也就是说2D 负责:
- 设备是谁
- 端子是谁
- 设备和端子在电气上是什么意思
- 它们属于哪个网络
#### 24.6.2 由 3D 负责的字段
- `instance_id` 对应的空间位姿
- 宿主对象落点
- 3D 端子具体几何位置
- `connection_point_key` 对应的实际连接点落位
- 柜内装配关系
也就是说3D 负责:
- 它在柜体中装在哪里
- 它挂在哪条导轨、哪块安装板上
- 端子在三维空间里具体位于哪里
#### 24.6.3 需要双方共同遵守但不能双写冲突的字段
- `asset_uri`
- `instance_id`
- `connection_point_key`
- `host_object_id`
- `host_object_type`
建议策略:
- 第一版由 2D 提供 `asset_uri`
- 第一版由 3D 回写 `instance_id / connection_point_key / host_object_*`
- 如果 2D 后续能预先规划 3D 实例 ID也要保证生成规则稳定且不会和 3D 重复造号
### 24.7 阶段 A 的推荐记录样例
下面给出两个“建议形态”的样例,目的是帮助阶段 A 对齐字段语义,不代表必须先改成 JSON 存储。
#### 24.7.1 设备级绑定样例
```json
{
"project_uuid": "proj-001",
"source_diagram_uuid": "sch-001",
"element_uuid": "elem-a1b2c3",
"instance_id": "inst-qf1",
"device_id": "MCCB_1P_OF",
"display_tag": "QF1",
"asset_uri": "file:///assets/MCCB_1P_OF.step",
"layout_2d_diagram": "layout-main",
"host_object_id": "rail-01",
"host_object_type": "Rail"
}
```
#### 24.7.2 端子级绑定样例
```json
{
"project_uuid": "proj-001",
"source_diagram_uuid": "sch-001",
"element_uuid": "elem-a1b2c3",
"terminal_uuid": "term-13",
"instance_id": "inst-qf1",
"terminal_key": "QF1:13",
"symbol_terminal": "13",
"connection_point_key": "cp_13",
"terminal_direction": "bidirectional",
"terminal_type": "power",
"wire_label": "W-001",
"net_id": "net-l1"
}
```
### 24.8 阶段 A 与现有 2D 代码的对应关系
当前 2D 代码里,阶段 A 所需的大部分基础其实已经存在。
#### 24.8.1 设备 3D 资源字段
已有:
- `parts_3d`
- `layout_2d_diagram`
参考:
- [deviceeditor.cpp](D:/project/MingTuCAD/qelectrotech/sources/DeviceManager/deviceeditor.cpp:1484)
- [DeviceMeta.h](D:/project/MingTuCAD/qelectrotech/sources/DeviceManager/DeviceMeta.h:32)
#### 24.8.2 端子属性字段
已有:
- `tag`
- `direction`
- `type_id`
- `max_wire`
- `mnemonic`
- `usage`
- `max_sec`
- `min_sec`
参考:
- [deviceterminaleditor.cpp](D:/project/MingTuCAD/qelectrotech/sources/InsertFunction/deviceterminaleditor.cpp:94)
- [deviceterminaleditor.cpp](D:/project/MingTuCAD/qelectrotech/sources/InsertFunction/deviceterminaleditor.cpp:214)
#### 24.8.3 2D/3D 绑定表
已有:
- `project_3d_scene_instance`
- `project_3d_space_object`
- `project_2d3d_link`
- `project_2d3d_symbol_binding`
- `project_2d3d_terminal_binding`
- `start_end_terminal_matches`
参考:
- [projectlocaldatabase.cpp](D:/project/MingTuCAD/qelectrotech/sources/dataBase/projectlocaldatabase.cpp:364)
- [projectlocaldatabase.cpp](D:/project/MingTuCAD/qelectrotech/sources/dataBase/projectlocaldatabase.cpp:411)
- [projectlocaldatabase.cpp](D:/project/MingTuCAD/qelectrotech/sources/dataBase/projectlocaldatabase.cpp:425)
- [projectlocaldatabase.cpp](D:/project/MingTuCAD/qelectrotech/sources/dataBase/projectlocaldatabase.cpp:446)
- [projectlocaldatabase.cpp](D:/project/MingTuCAD/qelectrotech/sources/dataBase/projectlocaldatabase.cpp:469)
所以阶段 A 的重点并不是“重新设计一套完全新的数据结构”,而是:
- 统一字段命名
- 统一主键规则
- 明确哪些现有字段可以直接沿用
- 明确哪些字段需要补充或规范化
### 24.9 阶段 A 的文档交付清单
建议阶段 A 至少完成下面这些文档性交付物:
1. 《字段对照表》
2. 《主键与唯一性约定》
3. 《2D/3D 职责边界说明》
4. 《设备级绑定样例》
5. 《端子级绑定样例》
只有这几样都齐了,后面的代码实现才不容易边写边改字段语义。
### 24.10 阶段 A 的验收标准
阶段 A 完成的判断标准建议定成下面这些:
1. 团队内部能明确回答:
- 设备靠哪个字段唯一识别
- 端子靠哪个字段唯一识别
- 哪些字段只是显示用途
2. 能给出一条设备绑定记录样例
3. 能给出一条端子绑定记录样例
4. 能明确指出每个关键字段由 2D 还是 3D 负责
5. 不需要看代码猜字段含义,单看文档就能开始阶段 B
## 25. 2D -> 3D 字段对照表
下面这张表的目标不是一次覆盖所有未来字段,而是先把阶段 A 真正要对齐的核心字段固定下来。
建议使用原则:
- 左侧 `2D 字段` 表示 QElectroTech 侧已有字段或推荐输出字段
- 中间 `3D 字段` 表示 FreeCAD 侧对象属性、绑定对象属性或同步结构中的字段名
- `责任方` 表示该字段的主维护方
- `备注` 用于说明是否直接映射、是否仅显示、是否后续回写
### 25.1 项目级字段对照
| 2D 字段 | 3D 字段 | 责任方 | 备注 |
| --- | --- | --- | --- |
| `project_uuid` | `ProjectUuid` | 2D | 项目全局主键3D 只读并保存,不自行生成 |
| `project_name` | `ProjectName` | 2D | 仅显示用途,不作为绑定主键 |
| `source_diagram_uuid` | `SourceDiagramUuid` | 2D | 2D 来源图纸主键3D 端用于追溯来源 |
| `scene_diagram_uuid` | `SceneDiagramUuid` | 3D | 3D 场景主键,若 2D 侧已有对应字段可同步保存 |
### 25.2 设备级字段对照
| 2D 字段 | 3D 字段 | 责任方 | 备注 |
| --- | --- | --- | --- |
| `element_uuid` | `ElementUuid` | 2D | 2D 设备实例主键,设备绑定首要识别字段 |
| `instance_id` | `InstanceId` | 3D | 3D 设备实例主键,建议由 3D 创建后回写 2D |
| `device_id` | `DeviceId` | 2D | 设备类型标识,可映射到元件库类型 |
| `display_tag` | `DisplayTag` | 2D | 显示名,例如 `QF1`,不可替代主键 |
| `parts_3d` / `asset_uri` | `AssetUri` | 2D | 3D 资产路径来源字段,第一版由 2D 提供 |
| `layout_2d_diagram` | `Layout2DDiagram` | 2D | 2D 布局来源标识3D 仅保存引用 |
| `host_object_id` | `HostObjectId` | 3D | 设备在 3D 中挂载到哪个宿主对象,例如导轨或安装板 |
| `host_object_type` | `HostObjectType` | 3D | 宿主对象类型,例如 `Rail`、`Panel`、`Cabinet` |
| `pos_x / pos_y / pos_z`(若 2D 侧后续引入) | `Placement.Base` | 3D | 第一版建议位姿由 3D 主导2D 可只保存回写结果 |
| `rot_x / rot_y / rot_z`(若 2D 侧后续引入) | `Placement.Rotation` | 3D | 同上,作为 3D 位姿结果回写,不建议 2D 首发控制 |
### 25.3 端子级字段对照
| 2D 字段 | 3D 字段 | 责任方 | 备注 |
| --- | --- | --- | --- |
| `terminal_uuid` | `TerminalUuid` | 2D | 2D 端子实例主键,端子绑定核心标识 |
| `terminal_key` | `TerminalKey` | 2D | 业务可读键,例如 `QF1:13`,建议稳定生成 |
| `symbol_terminal` | `SymbolTerminal` | 2D | 图纸显示端子号,例如 `13`,仅显示和辅助检索 |
| `tag` | `TerminalTag` | 2D | 若 2D 端已有端子标签字段,可单独映射保留 |
| `direction` | `TerminalDirection` | 2D | 端子方向语义3D 用于规则判断,不直接决定整体路由 |
| `type_id` | `TerminalTypeId` | 2D | 端子类型枚举主键,便于后续规则扩展 |
| `mnemonic` | `Mnemonic` | 2D | 端子助记符,偏显示和检索用途 |
| `usage` | `Usage` | 2D | 端子用途说明,例如控制、电源、保护 |
| `max_wire` | `MaxWire` | 2D | 最大接线数,后续可用于 3D 规则检查 |
| `max_sec` | `MaxSection` | 2D | 最大线径/截面积,第一版可先只保存不执行校验 |
| `min_sec` | `MinSection` | 2D | 最小线径/截面积,第一版可先只保存不执行校验 |
| `connection_point_key` | `ConnectionPointKey` | 3D | 3D 连接点键,建议由 3D 端确定后回写 2D |
| `wire_label` | `WireLabel` | 2D | 线号/导线标签3D 只读并附着到端子或导线对象 |
| `net_id` | `NetId` | 2D | 网络主键3D 连线对象应直接读取并保存 |
| `can_wire`(若 2D 侧后续显式输出) | `CanWire` | 2D/3D 共同遵守 | 第一版默认可由 3D 端按端子对象类型推导,也可由 2D 显式下发 |
### 25.4 3D 端子与连接点扩展字段
这部分字段不一定在 2D 现有数据库里原生存在,但建议在 3D 侧先固定命名,便于后续回写和扩展。
| 2D 字段 | 3D 字段 | 责任方 | 备注 |
| --- | --- | --- | --- |
| - | `OwnerDevice` | 3D | FreeCAD 端子对象指向所属设备对象的链接属性 |
| - | `LcsName` | 3D | 端子几何基准的 LCS 名称,便于界面调试和对象检索 |
| - | `Status` | 3D | 3D 端子当前状态,例如 `Unbound`、`Bound`、`Connected` |
| `extra_json`(若已有或后续扩展) | `ExtraJson` | 双方约定 | 放临时扩展字段,但不建议承载主键语义 |
### 25.5 表级映射建议
为了让字段对照真正能落到代码里,建议阶段 A 同时固定“字段主要从哪张表来”。
| 2D 表/来源 | 对应 3D 对象/结构 | 责任方 | 备注 |
| --- | --- | --- | --- |
| `project_2d3d_symbol_binding` | 3D 设备实例绑定记录 | 2D 写入3D 读取/回写部分字段 | 设备级绑定主表 |
| `project_2d3d_terminal_binding` | 3D 端子对象绑定记录 | 2D 写入3D 回写 `connection_point_key` 等 | 端子级绑定主表 |
| `project_3d_scene_instance` | 3D 场景实例位姿记录 | 3D | 位姿与宿主落位建议由 3D 主导 |
| `device_circuit_terminals` | 3D 端子语义属性来源 | 2D | 类型、方向、线径、接线数等语义来源 |
| `parts_3d` / `layout_2d_diagram` | 3D 资产入口与布局引用 | 2D | 第一版不建议 3D 自行猜资产路径 |
### 25.6 推荐命名规则
为了减少后续字段漂移,建议阶段 A 先固定这些命名规则:
- 数据库存储字段保持 `snake_case`
- FreeCAD 对象属性使用 `PascalCase`
- 界面显示名允许中文,但不参与绑定
- `Uuid` 后缀只用于真正全局唯一标识
- `Key` 后缀用于业务键或连接点键
- `Id` 后缀用于类型标识、实例标识或宿主标识
示例:
- 数据库字段:`terminal_uuid`
- FreeCAD 属性:`TerminalUuid`
- 界面显示:`端子 13`
### 25.7 第一版建议严格区分的字段
下面这些字段看起来相近,但建议在阶段 A 就明确区分,避免后面混用:
#### 25.7.1 `terminal_uuid``terminal_key`
- `terminal_uuid`:机器主键,稳定唯一
- `terminal_key`:业务可读键,便于调试和跨界面识别
不建议只保留 `terminal_key`,因为显示编号或设备标签变化时它可能变化。
#### 25.7.2 `element_uuid``instance_id`
- `element_uuid`2D 设备实例身份
- `instance_id`3D 设备实例身份
这两个字段不要互相替代。第一版即使它们暂时值相同,也建议语义上保持区分。
#### 25.7.3 `symbol_terminal``connection_point_key`
- `symbol_terminal`2D 图纸上的端子显示号
- `connection_point_key`3D 模型内部连接点键
一个显示端子号理论上可以映射到一个具体连接点,但两者不是同一个概念。
### 25.8 字段对照表的使用方式
这张表建议在阶段 B/C 里直接作为开发输入使用:
1. 2D 侧先检查哪些字段已经稳定存在
2. 对不存在但必要的字段做补充或规范化
3. 3D 侧严格按对照表创建对象属性
4. 接口层不要临时发明新名字,优先复用这里的统一命名
也就是说,后续代码实现时应该尽量做到:
> 看字段对照表就能知道字段从哪来、落到哪去、该由谁维护。
### 24.11 阶段 A 结束后再进入代码
阶段 A 结束后,下一步再做代码时,建议顺序是:
1. 先在 2D 侧把设备级绑定输出稳定下来
2. 再在 3D 侧按 `instance_id` 落设备实例
3. 设备级稳定后,再进入端子级绑定
也就是说,阶段 A 的价值就在于:
> 先把绑定语言说清楚,再开始真正的数据读写和对象创建。

@ -0,0 +1,10 @@
@echo off
setlocal
set "FC_LIBPACK=E:\fc\LibPack-1.1.0-v3.1.1.3-Release"
set "FC_RUN=E:\fc\run-FreeCAD-1.1.1"
set "FC_PYSIDE=%FC_LIBPACK%\bin\Lib\site-packages\PySide6"
set "FC_SHIBOKEN=%FC_LIBPACK%\bin\Lib\site-packages\shiboken6"
set "QT_PLUGIN_PATH=%FC_LIBPACK%\plugins"
set "QML2_IMPORT_PATH=%FC_LIBPACK%\qml"
set "PATH=%FC_LIBPACK%\bin;%FC_LIBPACK%\lib;%FC_PYSIDE%;%FC_SHIBOKEN%;%FC_RUN%\bin;%PATH%"
start "" /D "%FC_RUN%\bin" "%FC_RUN%\bin\FreeCAD.exe"

@ -0,0 +1,481 @@
# 2D / 3D 协同数据库设计(第一版最小集)
本文档只保留当前阶段真正必需的字段。
目标不是一次把未来所有能力都放进表里,而是先支持下面这条最小闭环:
1. 2D 里有设备实例
2. 2D 里有端子实例
3. FreeCAD 里创建对应的 3D 设备实例
4. FreeCAD 里创建对应的 3D 端子对象
5. 2D 与 3D 可以靠稳定主键互相找到对方
当前设计严格遵守两条原则:
- 电气语义以 2D 为准
- 空间位姿以 3D 为准
另外再补一条当前版本明确采用的约定:
- 3D 设备资源不在绑定表中重复保存,统一通过 `element_uuid -> device_id -> parts_3d` 回查
因此,第一版不重复存这些信息:
- `display_tag`
- `terminal_key`
- `connection_point_key`
- `host_binding_mode`
- `host_object_id`
- `host_object_type`
- `extra_json`
- `scene_diagram_uuid`
- `source_diagram_uuid`
原因很简单:
- 这些字段当前要么能通过 2D 主键回查
- 要么属于未来扩展
- 要么当前语义还不够稳定
## 1. 统一主键约定
第一版只认下面这几个核心标识:
- `project_uuid`
- `element_uuid`
- `terminal_uuid`
- `instance_id`
含义:
- `project_uuid`:项目唯一标识
- `element_uuid`2D 设备实例唯一标识
- `terminal_uuid`2D 端子实例唯一标识
- `instance_id`3D 设备实例唯一标识,由 FreeCAD 生成
## 2. 需要保留的最小表
第一版只建议保留 2 张表:
1. `project_2d3d_symbol_binding`
2. `project_2d3d_terminal_binding`
---
## 3. 设备绑定表
表名:
`project_2d3d_symbol_binding`
作用:
> 记录“一个 2D 设备实例,对应哪个 3D 设备实例,以及它使用哪个 3D 资源”
但“它使用哪个 3D 资源”这一点,第一版不在本表中直接存储,而是通过 2D 侧已有关系回查:
`element_uuid -> device_id -> parts_3d`
### 3.1 保留字段
| 字段名 | 中文 | 责任方 | 说明 |
| --- | --- | --- | --- |
| `project_uuid` | 项目UUID | 2D | 项目范围主键 |
| `element_uuid` | 设备实例UUID | 2D | 2D 设备实例唯一标识 |
| `instance_id` | 3D实例ID | 3D | FreeCAD 生成的 3D 设备实例唯一标识 |
### 3.2 推荐约束
- 主唯一键:`(project_uuid, element_uuid)`
- 3D 实例唯一键:`(project_uuid, instance_id)`
### 3.3 推荐 SQLite 结构
```sql
CREATE TABLE IF NOT EXISTS project_2d3d_symbol_binding (
project_uuid TEXT NOT NULL,
element_uuid TEXT NOT NULL,
instance_id TEXT NOT NULL,
PRIMARY KEY (project_uuid, element_uuid)
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_symbol_binding_instance
ON project_2d3d_symbol_binding(project_uuid, instance_id);
```
### 3.4 为什么只留这 3 个字段
因为第一版要解决的问题只有:
- 2D 设备是谁:`element_uuid`
- 3D 设备是谁:`instance_id`
- 属于哪个项目:`project_uuid`
而 3D 模型资源本身可以通过:
- `element_uuid`
- 回查到对应设备实例
- 再回查 `device_id`
- 最后拿到 `parts_3d`
所以第一版不重复存 `asset_uri`
---
## 4. 端子绑定表
表名:
`project_2d3d_terminal_binding`
作用:
> 记录“一个 2D 端子实例,对应哪个 3D 设备实例上的端子对象”
### 4.1 保留字段
| 字段名 | 中文 | 责任方 | 说明 |
| --- | --- | --- | --- |
| `project_uuid` | 项目UUID | 2D | 项目范围主键 |
| `terminal_uuid` | 端子UUID | 2D | 2D 端子实例唯一标识 |
| `instance_id` | 3D实例ID | 3D | 该端子属于哪个 3D 设备实例 |
### 4.2 推荐约束
- 主唯一键:`(project_uuid, terminal_uuid)`
- 查询索引:`(project_uuid, instance_id)`
### 4.3 推荐 SQLite 结构
```sql
CREATE TABLE IF NOT EXISTS project_2d3d_terminal_binding (
project_uuid TEXT NOT NULL,
terminal_uuid TEXT NOT NULL,
instance_id TEXT NOT NULL,
PRIMARY KEY (project_uuid, terminal_uuid)
);
CREATE INDEX IF NOT EXISTS idx_terminal_binding_instance
ON project_2d3d_terminal_binding(project_uuid, instance_id);
```
### 4.4 为什么不保留 `terminal_key``connection_point_key`
当前第一版设计里:
- 3D 端子本身就是 2D 端子的空间映射
- 所有端子语义都可以通过 `terminal_uuid` 从 2D 回查
所以目前不需要额外再保存:
- `terminal_key`
- `symbol_terminal`
- `connection_point_key`
- `wire_label`
- `net_id`
这些信息如果后续 3D 侧需要显示或校验,可以通过 `terminal_uuid` 回查 2D。
---
## 5. 现阶段明确删掉的字段
下面这些字段不是说永远没用,而是 **第一版先删掉,不进入最小表结构**。
### 5.1 从设备绑定表中删掉
- `source_diagram_uuid`
- `scene_diagram_uuid`
- `device_id`
- `display_tag`
- `asset_uri`
- `host_binding_mode`
- `host_object_id`
- `host_object_type`
- `extra_json`
### 5.2 从端子绑定表中删掉
- `element_uuid`
- `binding_key`
- `symbol_terminal`
- `terminal_key`
- `connection_point_key`
- `wire_label`
- `net_id`
- `conductor_uuid`
- `extra_json`
### 5.3 从 3D 实例表中删掉
- `project_3d_scene_instance` 整张表
- 所有位姿字段:`tx / ty / tz / rx / ry / rz`
- 所有缩放字段:`sx / sy / sz`
- 所有 3D 场景附加字段:`diagram_uuid / asset_id / extra_json`
---
## 6. 第一版数据流
### 6.1 2D -> 3D
2D 提供:
- `project_uuid`
- `element_uuid`
- `terminal_uuid`
3D 在导入和实例化时生成:
- `instance_id`
然后写入:
- `project_2d3d_symbol_binding`
- `project_2d3d_terminal_binding`
### 6.2 3D -> 2D
3D 第一版只回写:
- `instance_id`
当前不回写位姿。
原因是:
- 3D 场景真相源已经切换为 FreeCAD
- 2D 不再承担 3D 场景保存职责
- 避免 FreeCAD 文档和数据库各存一份位姿造成冲突
---
## 7. 这版设计的核心思想
第一版故意把设计收得很紧,只保留:
- 一个 2D 设备实例如何找到 3D 设备实例
- 一个 2D 端子实例如何找到 3D 端子对象
也就是说,当前数据库设计只服务于:
> “2D 语义 + 3D 空间映射”这个最小闭环
而且这里的“空间映射”只表示:
- 2D 对象知道自己对应哪个 3D 实例
不表示数据库要保存完整 3D 位姿。
---
## 8. 后续扩展时再加的字段
只有当下面这些需求真的出现时,再补字段:
- 多 3D 场景:补 `scene_diagram_uuid`
- 设备挂载规则:补 `host_object_id / host_object_type`
- 3D 资源缓存:补 `asset_uri`
- 多连接点/复杂端子:补 `connection_point_key`
- 3D 端子独立语义缓存:补 `terminal_key / symbol_terminal`
- 导线级 3D 校验:补 `wire_label / net_id / conductor_uuid`
- 2D 侧需要读取 3D 位姿:再恢复 3D 场景实例表或等价位姿存储
- 临时扩展:最后才考虑 `extra_json`
---
## 9. FreeCAD 与数据库的职责边界
继续收缩后的职责建议如下:
### 9.1 数据库负责
- 2D 设备实例和 3D 设备实例的绑定
- 2D 端子实例和 3D 端子对象的绑定
### 9.2 FreeCAD 负责
- 3D 设备实例实际创建
- 设备位姿
- 导轨/安装板/柜体装配关系
- 端子在空间中的实际几何位置
- 3D 接线几何
也就是说,第一版开始就建议明确:
> 3D 位姿和装配关系只保存在 FreeCAD 文档里,不在数据库中重复保存。
---
## 10. 当前推荐结论
第一版数据库设计建议就收成这三张表:
1. `project_2d3d_symbol_binding`
2. `project_2d3d_terminal_binding`
并且只保留最小核心字段:
- 设备绑定只保留:`project_uuid / element_uuid / instance_id`
- 端子绑定只保留:`project_uuid / terminal_uuid / instance_id`
一句话总结:
> 第一版先让 2D 能找到 3D至于 3D 怎么摆、摆在哪、怎么装配,全部交给 FreeCAD 自己管理。
---
## 11. 第一版交换形式
第一版 2D / 3D 协同,交换形式先统一为:
- **JSON 文件交换**
当前不建议第一版直接做:
- 实时数据库双向同步
- 进程间 RPC
- HTTP API
- FreeCAD 保存后直接写回 QET 运行库
原因:
- JSON 最容易调试
- 字段改动时最容易观察
- 不会把 QET 和 FreeCAD 的运行时强耦合在一起
- 更适合当前仍在收缩字段和表结构的阶段
---
## 12. 第一版工具入口
QET 侧建议保留并改造一个工具项:
- `3D视图`
这个工具项的职责不再是走 QET 旧的 3D 模块逻辑,而是:
1. 从 QET 当前项目和当前 2D 图纸中整理 2D -> 3D 最小绑定数据
2. 导出 `2d_to_3d.json`
3. 启动 FreeCAD或打开已有的 FreeCAD 工程文件
也就是说:
> 第一版 `3D视图` 本质上是“导出 2D 快照并切换到 FreeCAD”的入口。
---
## 13. 第一版交换目录建议
建议在项目目录下固定一套交换目录:
```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 工程
- `logs/`:调试与排障日志
---
## 14. 第一版时机约定
### 14.1 QET -> FreeCAD
触发时机:
- 用户点击 QET 的 `3D视图`
动作:
1. 更新并确认当前 2D 设备实例 / 端子实例绑定
2. 生成 `2d_to_3d.json`
3. 打开 FreeCAD
4. 打开或创建 `scene.FCStd`
### 14.2 FreeCAD -> QET
第一版不建议:
- FreeCAD 保存时直接写数据库
第一版建议:
- FreeCAD 保存时输出 `3d_to_2d.json`
然后由 QET 在后续时机主动读取:
- 手动刷新
- 再次点击 `3D视图`
- 或后续增加单独的“从 3D 刷新”命令
这样做的目的,是先把同步时机收成“文件交换”,避免两边运行时直接打架。
---
## 15. 第一版最小交换内容
### 15.1 `2d_to_3d.json`
第一版只要求包含最小绑定信息:
- 设备绑定:
- `project_uuid`
- `element_uuid`
- `instance_id`
- 端子绑定:
- `project_uuid`
- `terminal_uuid`
- `instance_id`
说明:
- `instance_id` 在第一版中由 FreeCAD 侧生成更合理
- 如果首次进入 3D 时尚未生成 `instance_id`,可以先导出为空,再由 FreeCAD 创建后回写
### 15.2 `3d_to_2d.json`
第一版只建议回写:
- `project_uuid`
- `element_uuid`
- `instance_id`
- `terminal_uuid`
当前不要求回写:
- 3D 位姿
- 装配结构
- 导线几何路径
这些仍以 FreeCAD 文档为准。
---
## 16. 第一版推荐交互流程
建议按下面这条闭环实现:
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`
一句话总结:
> 第一版先做“QET 导出 JSON + 打开 FreeCADFreeCAD 保存时回写 JSON”的文件交换闭环不做强耦合实时同步。
Loading…
Cancel
Save