本机环境已实测:SOLIDWORKS 2025 SP01.1(RevisionNumber 33.1.1)、 Python 3.14.3 64 位 + pywin32,GetActiveObject 可挂已开实例。 已跑通的链路: - EasyEDA get3DFile 导 STEP —— 桥有 30s 硬超时,必须异步启动+轮询; 4MB 分块 base64 取回(刀片 31.2MB/25s,底板 53.9MB/44s) - GetImportFileData + LoadFile4 导入(得到带位号的装配树,一块板 95 个文档) - 遍历 GetDocuments 拿临时顶层 SLDASM → AddComponent4 插入(⛔ AddComponent5 恒返回 None) - ToolsCheckInterference2(0, EMPTY, False, pc, pf) 5 参形式可调 - CloseAllDocuments(True) 清理(295 文档 0.9s) ⛔ 未完成:刀片摆位(CreateTransform 卡在 pywin32 封送)、 坐标系(插入后两板被重心归零,§14 的平移量不能直接用)。 ⇒ 现状能装能查,但两板堆在原点,干涉结果无工程意义。 NOTES-probed.md 记了 18 节实测坑,包括: - 无参成员是属性不是方法(含 GetMathUtility 这个例外) - SaveAs3 返回 True 但写出的是废件(外部引用断链) - LoadFile4 不会插进当前装配体 - 动态派发"找不到成员"时用 _oleobj_.GetIDsOfNames + Invoke 绕行 Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_0168Bu6SEx3cXXCJLkdnE6zB
98 行
4.7 KiB
Markdown
98 行
4.7 KiB
Markdown
---
|
||
name: solidworks-assembly
|
||
description: 把 EasyEDA 的 PCB 导成 STEP、在本机 SOLIDWORKS 里装配并做干涉检查。用于「底板 + 刀片插在一起会不会撞」这类机械核对,也用于量插槽插入深度这类 EDA 侧算不出来的数。涉及 SolidWorks / STEP / 3D 装配 / 干涉检查 / 机械干涉 时触发。
|
||
---
|
||
|
||
# SolidWorks 装配与干涉检查(PhoneRail 专用)
|
||
|
||
> ⚠ **动手前先读 `NOTES-probed.md`** —— 那是本机逐条实测出来的 API 口径与坑,
|
||
> 每一条都踩过一次。不读会把同样的坑再踩一遍。
|
||
> 环境已实测:SOLIDWORKS 2025 SP01.1(`RevisionNumber` = `33.1.1`)、
|
||
> Python 3.14.3 **64 位** + pywin32(32 位 Python 连不上 64 位 SW,本机不存在这问题)。
|
||
|
||
## 什么时候用
|
||
|
||
- 底板与刀片、刀片与刀片之间的**机械干涉**核对(EDA 侧只能算 2.5D 净距,算不了竖插后的三维关系)
|
||
- 量 EDA 侧拿不到的机械数:插槽**插入深度**、塑料体内腔、刀片底边离底板多高
|
||
- ⚠ **但凡实物在手,优先用卡尺**。STEP 里的连接器是厂商**标称模型**,不含公差;
|
||
3D 能替代"按标称值推算",替代不了实测。
|
||
|
||
## 整条链(每一步都已实测通过)
|
||
|
||
### 1. 从 EasyEDA 导出 STEP
|
||
|
||
```python
|
||
# 桥有 30 s 硬超时,大板同步调用必断 ⇒ 异步启动 + 轮询
|
||
START = "window.__gen={state:'running'}; (async()=>{ ... get3DFile(name,'step',['Component Model'],'Outfit',true) ... })(); return {started:true};"
|
||
# 再每 5 s 查 window.__gen.state,done 后用 4 MB 分块 base64 取回
|
||
```
|
||
|
||
实测:刀片 31.2 MB(生成 22.6 s + 取回 2 s)、底板 53.9 MB(生成 40 s + 取回 4 s)。
|
||
归档在 `.claude/r2/3d/`(已 `.gitignore`)。细节见 NOTES §6。
|
||
|
||
### 2. 导入 SolidWorks
|
||
|
||
```python
|
||
app = wc.GetActiveObject('SldWorks.Application') # 挂已开着的实例
|
||
data = app.GetImportFileData(step_path)
|
||
err = wc.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 0)
|
||
app.LoadFile4(step_path, 'r', data, err) # err.value == 0 即成功
|
||
```
|
||
|
||
导进来是**带位号的装配树**(`R1~R0402~…`、`U4~TSSOP-24~…`),一块板 95 个文档。
|
||
⛔ 第三参不能传 `None`(报"类型不匹配");⛔ `OpenDoc6` 导 STEP 返回 None。见 NOTES §3。
|
||
|
||
### 3. 找到可插引用 + 装配
|
||
|
||
```python
|
||
# 导入后**不要关文档**,遍历 GetDocuments 找:有路径 + GetType==2 + .SLDASM
|
||
p = ... # → %TEMP%\swx…\IC~~\PhoneRail_base.step.SLDASM
|
||
c = asm.AddComponent4(p, '', 0.0, 0.0, 0.0) # ✅ 用 AddComponent4
|
||
```
|
||
|
||
⛔ **`AddComponent5`(8 参)在本机恒返回 `None`**,换参数没用,直接用 `AddComponent4`。
|
||
⛔ 别走"另存再插":`SaveAs3` 出来的是废件、`CopyDocument` 返回 2、`OpenDoc7` 打不开 STEP。
|
||
见 NOTES §11/§12/§15。
|
||
|
||
### 4. 干涉检查
|
||
|
||
```python
|
||
pc = wc.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_VARIANT, None)
|
||
pf = wc.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_VARIANT, None)
|
||
n = asm.ToolsCheckInterference2(0, EMPTY, False, pc, pf) # 5 参,少一个都报"非选择性的参数"
|
||
```
|
||
|
||
⛔ 第 2 参只能传 `EMPTY`(`VARIANT(VT_DISPATCH, None)`),塞零部件元组会报"服务器出现意外情况"。
|
||
|
||
### 5. 清理
|
||
|
||
```python
|
||
app.CloseAllDocuments(True) # 295 个文档 0.9 s 关完,SW 不退出
|
||
```
|
||
⛔ 一关就清空 `%TEMP%\swx…\IC~~\`,所以第 3 步必须在清理**之前**做完。
|
||
|
||
## ⛔ 未完成的两步(别当成能用)
|
||
|
||
1. **刀片摆位**。变换矩阵算好了(NOTES §14),但 `CreateTransform` 卡在 pywin32 封送:
|
||
`GetMathUtility` 要用 dispid 绕行才拿得到(NOTES §17),拿到后 `CreateTransform`
|
||
**又**报"找不到成员"——同一个病一层套一层,未解。
|
||
2. **坐标系**:`AddComponent4` 插进总装后,两块板都被**重心归零**
|
||
(刀片 `x -45~45 / y -34~34`、底板 `x -49~49 / y -49~49`),
|
||
NOTES §14 那套"原点 = 板左下角"的平移量**不能直接用**,要按 `GetBox` 现算。
|
||
|
||
⇒ 现状:能装、能查干涉,但**两块板都堆在原点**,查出来的干涉没有工程意义。
|
||
要么解掉上面两点,要么在 SolidWorks 里手工拖一次(更快)。
|
||
|
||
## 调试时的通用招数
|
||
|
||
动态派发报"找不到成员"时,先确认名字在不在:
|
||
|
||
```python
|
||
did = app._oleobj_.GetIDsOfNames('GetMathUtility') # 在 → 返回 dispid
|
||
raw = app._oleobj_.Invoke(did, 0, pythoncom.DISPATCH_METHOD, 1)
|
||
```
|
||
|
||
还有一条贯穿始终的规律:**无参成员基本都是属性**(`app.GetDocumentCount` / `doc.GetTitle` /
|
||
`doc.EditRebuild3` 都不加括号),有参的才是方法。但**有例外**(`GetMathUtility`),
|
||
拿不准就去 `sldworks.tlb` 查 `invkind`(NOTES §8 给了读法)。
|