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.

190 lines
7.7 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.

# dxf2elmt
`dxf2elmt` 是一个把 ASCII 或二进制 DXF 图纸转换为
[QElectroTech](https://qelectrotech.org/) `.elmt` 元件文件的命令行工具。
源项目地址:<https://github.com/qelectrotech/dxf2elmt_vadoola>
## 编译
项目使用 Rust最低支持版本MSRV为 1.79.0。
```bash
cargo build --release
```
编译后的程序位于:
```text
target/release/dxf2elmt.exe
```
## 使用方法
转换一个或多个 DXF 文件:
```bash
dxf2elmt drawing.dxf
dxf2elmt first.dxf second.dxf
```
输出文件与输入 DXF 位于同一目录,文件名不变,仅将扩展名改为 `.elmt`
常用参数:
| 参数 | 作用 |
| --- | --- |
| `-v`, `--verbose` | 不写入 `.elmt` 文件,改为把 XML 输出到标准输出 |
| `-s`, `--spline-step <N>` | 设置 SPLINE 的折线细分数量,默认值为 20数值越大越平滑 |
| `-i`, `--info` | 输出实体统计和转换耗时 |
| `-d`, `--dtext` | 当前为保留参数;现有实现始终把 TEXT/MTEXT 转为动态文本 |
查看完整参数:
```bash
dxf2elmt --help
```
## 当前实体映射
| DXF 实体 | ELMT 图元 | 当前处理方式 |
| --- | --- | --- |
| `LINE` | `<line>` | 保留两个端点、颜色、线型和数值线宽 |
| `CIRCLE` | `<ellipse>` | 以等宽、等高椭圆表示圆 |
| `ARC` | `<arc>` | 保留圆心、半径、起始角和圆弧角度 |
| `ELLIPSE` | `<ellipse>` | 转换中心、长轴和短长轴比例 |
| `POLYLINE` | `<line>` / `<ellipse>` / `<polygon>` | 两个顶点转直线;识别为圆时转椭圆;其余转多边形 |
| `LWPOLYLINE` | `<line>` / `<arc>` / `<ellipse>` / `<polygon>` | 根据顶点数、圆形特征和 bulge 分别处理,详细规则见下文 |
| `SPLINE` | `<polygon>` | 按 `spline-step` 采样为折线,不保留参数曲线本身 |
| `SOLID` | 填充 `<polygon>` | 按 DXF 的 `1-2-4-3` 顶点顺序恢复边界并填充 |
| `TRACE` | 填充 `<polygon>` | 与 SOLID 相同,按四边形边界转换并填充 |
| `TEXT` | `<dynamic_text>` | 转换内容、位置、旋转、字号、宽度系数和对齐方式 |
| `MTEXT` | `<dynamic_text>` | 部分支持,转换内容、位置、方向、字号和对齐方式 |
| `ATTDEF`(属性定义) | `<dynamic_text>` | 转换属性标签及其文本样式和位置 |
| `LEADER` | 一组 `<line>` | 相邻顶点生成线段,首段可带箭头 |
| `INSERT` | 块实例或 `<terminal>` | 普通 INSERT 展开块;特定连接点块转为端子 |
未列出的实体当前不会生成 ELMT 图元。
### LWPOLYLINE 映射规则
- 两个顶点且第一个顶点 `bulge != 0`:转换为圆弧。
- 两个顶点且没有 bulge转换为直线。
- 多个顶点且整体被识别为圆:转换为椭圆。
- 同时包含直线段和 bulge 圆弧段:按段拆分为多个 `<line>``<arc>`,避免圆弧丢失。
- 其他情况:转换为 `<polygon>`
- 开放多段线不会把最后一个顶点错误连接回第一个顶点;闭合多段线会保留闭合段。
## 样式映射
### 线宽
ELMT 只输出数值字段 `line-width-mm`,不再输出旧的
`line-weight:thin/normal/...` 档位。
LW 当前提供以下毫米预设值:
```text
0.00, 0.05, 0.09, 0.13, 0.15, 0.18, 0.20, 0.25,
0.30, 0.35, 0.40, 0.50, 0.53, 0.60, 0.70, 0.80,
0.90, 1.00, 1.06, 1.20, 1.40, 1.58, 2.00, 2.11 mm
```
默认值为 `0.25 mm`。转换器得到毫米线宽后,会按 LW 的
`normalizedMillimeters` 规则选择距离最近的预设值,例如
`0.33 → 0.35 mm`、`0.68 → 0.70 mm`。超出范围的值会归一到最接近的端点预设。
线宽来源和优先级如下:
1. `LWPOLYLINE.constant_width` 大于 0 时,作为该图元的宽度来源。
2. 否则读取第一个顶点的 `starting_width``ending_width`
3. 没有多段线宽度时,读取 DXF 实体公共组码 370 `line_weight`,其非负值按 `1/100 mm` 转换,例如 `35` 得到 `0.35 mm`
4. `BYLAYER`、`BYBLOCK`、`DEFAULT` 等负值当前不会被伪造成固定线宽,也不会输出 `line-width-mm`
5. 对得到的毫米值执行 LW 预设归一化,再输出 `line-width-mm`
DXF 组码 39 的 `thickness` 是沿挤出方向的三维厚度,不是二维描边宽度。
转换器不会用 `thickness` 计算 `line-width-mm`
### 线型
以下 DXF 线型名称会转换为 ELMT 虚线:
- 名称中包含 `DASH`
- `BORDURE`
- `INTERROMPU`
- `INTERROMPUx2`
- `TRACECAD_ISO02W100`
其他线型目前按普通实线处理,不解析 DXF 线型的具体线段和空隙图案。
### 颜色
- `LINE`、`ARC`、`LWPOLYLINE`、`TEXT` 和属性文本会优先读取 ACI 颜色索引,否则读取 24 位真彩色。
- 部分通过几何识别生成的图元仍使用黑色默认值,例如部分 `CIRCLE`、`ELLIPSE`、`POLYLINE`、`SPLINE`、`SOLID` 和 `TRACE` 路径。
- `BYLAYER``BYBLOCK` 颜色尚未完整解析其最终继承值。
## 坐标、单位和二维化
- DXF Y 轴会翻转以适配 ELMT 坐标方向。
- 图形会根据 DXF 头部的 `default_drawing_units` 缩放;无单位图纸暂不缩放。
- 当前毫米图纸使用代码中的 `3.78` 缩放因子。
- 转换完成后,元件图形会以自身包围盒为依据移动到局部坐标中心。
- INSERT 会应用块基点、插入位置、X/Y 缩放和旋转。
- ELMT 元件是二维图形,因此图元 Z 坐标、挤出方向和 `thickness` 不会转换成三维模型。
## 块和端子
- 被 INSERT 引用的 DXF 块会写入 ELMT 的 `<blocks>` 定义。
- 普通 INSERT 会展开为带 `block_name``block_instance` 元数据的块实例图元。
- 嵌套块可以递归转换;序列化时内部图元使用最外层有效实例元数据。
- 名称为 `ARROWUNKNOWN` 且带有 `connector` 属性的 INSERT 会转换为
QElectroTech `<terminal>`,属性值同时用于端子名称和连接点标签。
- 名称为 `ORIENT` 的辅助图层会跳过,不导出定位标记。
## 已知限制
- `HATCH`、`DIMENSION`、`3DFACE`、`MESH` 等未实现实体会被跳过。
- 不支持真正的三维符号3D 数据只保留可转换的二维 XY 投影。
- `LWPOLYLINE` 的逐段可变宽度尚未完整表达。目前会取第一个顶点的非零起始或结束宽度,并把它应用到整个转换结果。
- `LWPOLYLINE` 的几何宽度当前直接写入毫米字段,因此非毫米 DXF 的宽度还需要补充单位换算。
- 组码 370 的 `BYLAYER` / `BYBLOCK` 线宽尚未解析图层或父块的继承值。
- MTEXT 的内联格式、复杂字体替换、段落布局和背景框尚未完整支持。
- `--dtext` 当前不会改变行为TEXT 和 MTEXT 都默认输出动态文本。
- 深层嵌套块、非均匀缩放后的圆弧以及复杂镜像仍需要更多样图验证。
- 当前错误信息较少,部分不支持的实体会被静默忽略。
## DXF 诊断工具
必要时可使用 `dxf2json.exe` 把 DXF 转换为 JSON以检查实体、块、属性、
对齐方式、颜色、坐标、bulge 和宽度数据。
```bash
dxf2json drawing.dxf
```
## 测试
```bash
cargo test
```
当前回归测试覆盖 XRECORD 清理、端子语义、块实例、嵌套块、SOLID 填充、
混合 LWPOLYLINE 圆弧拆分、负 bulge 圆弧方向以及数值线宽转换。
## 待办事项
- 支持剩余二维实体。
- 完善图层、块和尺寸样式继承。
- 完善非毫米图纸的多段线宽度换算。
- 改进错误信息和日志输出。
## Credits
- [Antonioaja](https://github.com/antonioaja) 创建了最初版本的
[dxf2elmt](https://github.com/antonioaja/dxf2elmt)。
- [QElectroTech](https://qelectrotech.org/)
- [dxf-rs](https://github.com/IxMilia/dxf-rs)
- [simple-xml-builder](https://github.com/Accelbread/simple-xml-builder)
- [bspline](https://github.com/Twinklebear/bspline)
- [tempfile](https://github.com/Stebalien/tempfile)