# ADtools **Repository Path**: debuger123/adtools ## Basic Information - **Project Name**: ADtools - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-13 - **Last Updated**: 2026-06-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # PCB Copper STEP Toolset 从 Altium Designer 的 `.PcbDoc` 或 `.step` 文件中提取铜皮几何,按层布尔求和(Union),导出合并后的 STEP 3D 模型。 ## 工具概览 | 脚本 | 功能 | 输入 | 输出 | |------|------|------|------| | `pcbdoc_to_step.py` | 直接读取 PcbDoc,提取铜皮,按层挤出+合并,导出 STEP | `.PcbDoc` | `.step` | | `step_merge_copper.py` | 合并已有 STEP 文件中的所有实体 | `.step` | `_merged.step` | ## 安装依赖 ```bash pip install altium-monkey cadquery-ocp pywin32 ``` | 库 | 用途 | |----|------| | [altium-monkey](https://github.com/wavenumber-eng/altium_monkey) | 解析 PcbDoc 二进制格式,提取铜皮几何和层叠参数 | | [cadquery-ocp](https://github.com/CadQuery/OCP) | OpenCASCADE Python 绑定,3D 建模与布尔运算 | | pywin32 | Windows COM 接口(可选,用于 AD 自动化) | --- ## 1. pcbdoc_to_step.py ### 功能 直接解析 Altium Designer 的 `.PcbDoc` 文件,无需安装或启动 AD: - 按层提取所有铜皮几何(走线、圆弧、填充、区域、覆铜、焊盘、过孔) - 从 PcbDoc 层叠数据读取每层铜皮厚度(不硬编码) - 将 2D 铜皮轮廓挤出为 3D 实体 - 每层内并行布尔求和 - 导出合并后的 STEP 文件,保留所有铜皮层 ### 处理流程 ``` .PcbDoc 文件 (OLE 二进制容器) │ ▼ altium_monkey 解析 │ ├─ 铜皮几何数据 (按层分组) │ ├─ Tracks: 走线 (x1,y1 → x2,y2, width) │ ├─ Arcs: 圆弧 (center, radius, angles, width) │ ├─ Fills: 填充矩形 (corner1, corner2, rotation) │ ├─ Regions: 多边形区域 (vertices, holes) │ ├─ ShapeBasedRegions: 渲染后的覆铜 (含圆弧段) │ ├─ Pads: 焊盘 (position, size, shape) │ ├─ Vias: 过孔 (position, diameter) │ └─ Polygons: 覆铜定义 (outline, cutouts) │ ├─ 层叠参数 (从 Board6/Data 读取) │ ├─ 每层铜皮厚度 (mil → mm) │ ├─ 介质厚度 │ └─ 累积 Z 位置 │ ▼ OCP (OpenCASCADE) 3D 建模 │ ├─ 2D 轮廓 → 挤出 (Prism) → 3D Solid │ ├─ Track → 矩形截面挤出 │ ├─ Fill → 矩形挤出 │ ├─ Region → 多边形挤出 │ ├─ Pad/Via → 圆柱体 (Cylinder) │ └─ Polygon → 多边形挤出 │ ▼ 并行布尔求和 (分治策略) │ ├─ 每层内部: 所有实体 → 1 个合并体 └─ 所有层 → 最终 STEP ``` ### 用法 ```bash # 基本用法 python pcbdoc_to_step.py board.PcbDoc # 指定输出文件名 python pcbdoc_to_step.py board.PcbDoc output.step # 指定并行线程数 python pcbdoc_to_step.py board.PcbDoc output.step 8 ``` ### 输出示例 ``` 读取 PcbDoc: board.PcbDoc 解析完成, 耗时 1.2s 层叠信息 (来源: V9): Top Layer: 铜厚=1.38mil (35.1μm), Z=0.000mm Inner Layer: 铜厚=0.69mil (17.5μm), Z=0.165mm Bottom Layer: 铜厚=1.38mil (35.1μm), Z=1.535mm 板总厚度: 1.600mm 检测到 3 个铜皮层: Top Layer: 46 个对象 (38 tracks, 8 pads), 铜厚=35.1μm Mid Layer: 12 个对象 (12 tracks), 铜厚=17.5μm Bottom Layer: 32 个对象 (24 tracks, 8 pads), 铜厚=35.1μm 开始 3D 构建 (线程数=4)... ... 总耗时: 8.5s 输出: board_copper.step (12.34 MB) 铜皮层数: 3 ``` ### 单位换算 Altium PcbDoc 内部使用"万分之一 mil"作为坐标单位: ``` 1 内部单位 = 0.0001 mil = 0.00000254 mm ``` 脚本中的换算常量: ```python INTERNAL_TO_MM = 0.0254 / 10000.0 # 内部单位 → mm MIL_TO_MM = 0.0254 # mil → mm(层叠数据用) ``` ### 层 ID 映射 | 层 ID | 含义 | |-------|------| | 1 | Top Layer | | 2-31 | Mid Layer 1-30 | | 32 | Bottom Layer | | 39-54 | Internal Plane 1-16 | | 74 | Multi-Layer(通孔焊盘/过孔) | --- ## 2. step_merge_copper.py ### 功能 读取已有 STEP 文件,将所有 Solid Body 布尔求和为一个整体。适用于 AD 手动导出的 STEP 文件。 ### 处理流程 ``` STEP 文件 │ ▼ OCP STEPControl_Reader │ ├─ 提取所有 Solid Body │ ▼ 分治并行合并 │ │ Round 1: [A,B,C,D,E,F,G,H] │ → (A+B) (C+D) (E+F) (G+H) 4线程并行 │ │ Round 2: [AB, CD, EF, GH] │ → (AB+CD) (EF+GH) 2线程并行 │ │ Round 3: [ABCD, EFGH] │ → (ABCD+EFGH) 1线程 │ ▼ 导出 STEP ``` ### 用法 ```bash python step_merge_copper.py board.step python step_merge_copper.py board.step board_merged.step 8 ``` --- ## 3D 建模原理 ### OpenCASCADE B-Rep 建模流程 所有 2D→3D 转换遵循 OpenCASCADE 的边界表示法(B-Rep)管线: ``` 点 (gp_Pnt) → 边 (BRepBuilderAPI_MakeEdge) → 环 (BRepBuilderAPI_MakeWire) → 面 (BRepBuilderAPI_MakeFace) → 体 (BRepPrimAPI_MakePrism / MakeCylinder) ``` ### 走线 → 3D ``` 走线: (x1,y1) → (x2,y2), width=w 1. 计算方向向量: dx=x2-x1, dy=y2-y1 2. 计算法线: nx=-dy/len * w/2, ny=dx/len * w/2 3. 生成 4 个角点: (x1+nx, y1+ny) ─────── (x2+nx, y2+ny) │ │ (x1-nx, y1-ny) ─────── (x2-nx, y2-ny) 4. 多边形挤出 → 3D 实体 ``` ### 焊盘/过孔 → 3D ``` 焊盘: position=(cx,cy), radius=r → BRepPrimAPI_MakeCylinder(axis, r, thickness) → 直接生成精确圆柱体 ``` --- ## 并行布尔求和算法 采用分治(Divide and Conquer)策略,类似归并排序: - **时间复杂度**: O(N) → O(log N) 轮,每轮并行 - **线程安全**: OpenCASCADE 的 C++ 内核在运算时释放 Python GIL,多线程真正并行 - **容错**: 单对合并失败时跳过,不中断整体流程 ```python def _parallel_fuse(solids, max_workers=4): while len(solids) > 1: # 相邻配对 pairs = [(solids[i], solids[i+1]) for i in range(0, len(solids)-1, 2)] leftover = solids[-1] if len(solids) % 2 else None # 线程池并行 fuse with ThreadPoolExecutor(max_workers=max_workers) as pool: results = [pool.submit(fuse_pair, a, b) for a, b in pairs] solids = [r.result() for r in results] if leftover: solids.append(leftover) ``` --- ## 层叠数据读取 从 PcbDoc 的 `Board6/Data` 流中读取层叠参数,支持两种格式: | 格式 | 版本 | 内容 | |------|------|------| | `layer_stackup` | AD 旧版 | 仅铜皮层,LAYER1-32 | | `v9_stack` | AD 25+ | 完整物理层叠(铜皮+介质+阻焊+丝印) | 每层包含: | 字段 | 单位 | 说明 | |------|------|------| | `copper_thickness` | mil | 铜皮厚度 | | `diel_height` | mil | 介质厚度 | | `diel_material` | — | 介质材料(FR-4 等) | | `diel_constant` | — | 介电常数 | | `diel_type` | — | 0=Core, 1=Prepreg, 3=SolderMask | Z 位置通过累积铜皮厚度+介质厚度计算,精确反映实际板叠结构。 --- ## 打包为 EXE ```bash pip install pyinstaller # 打包 step_merge_copper pyinstaller --onefile --console --name StepMergeCopper --collect-all OCP --collect-all cadquery_ocp step_merge_copper.py # 打包 pcbdoc_to_step pyinstaller --onefile --console --name PcbDocToStep --collect-all OCP --collect-all cadquery_ocp pcbdoc_to_step.py ``` 输出位于 `dist/` 目录,约 100-110 MB(含 OpenCASCADE 内核)。 --- ## 已知限制 1. **Region 挖孔未处理**: `_make_region_solid()` 中的 `holes` 参数暂未实现差集运算 2. **ShapeBasedRegion 圆弧段简化**: 圆弧顶点按直线处理,未精确建模圆弧轮廓 3. **Pad 形状简化**: 矩形/八角形焊盘统一按圆形处理 4. **层叠 Z 位置**: V9 格式层名映射依赖字符串匹配,非标准命名可能失败 5. **STEP 转 PcbDoc 不支持**: STEP 是纯几何格式,不包含电气信息,无法反向生成 PcbDoc --- ## 技术栈 | 组件 | 技术 | |------|------| | PcbDoc 解析 | [altium-monkey](https://github.com/wavenumber-eng/altium_monkey) (Python) | | 3D 建模引擎 | [OpenCASCADE](https://dev.opencascade.de/) via [OCP](https://github.com/CadQuery/OCP) | | 布尔运算 | BRepAlgoAPI_Fuse (OpenCASCADE) | | 并行计算 | Python ThreadPoolExecutor | | STEP I/O | STEPControl_Reader / STEPControl_Writer (OpenCASCADE) |