# dxf2elmt `dxf2elmt` 是一个把 ASCII 或二进制 DXF 图纸转换为 [QElectroTech](https://qelectrotech.org/) `.elmt` 元件文件的命令行工具。 源项目地址: ## 编译 项目使用 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 ` | 设置 SPLINE 的折线细分数量,默认值为 20;数值越大越平滑 | | `-i`, `--info` | 输出实体统计和转换耗时 | | `-d`, `--dtext` | 当前为保留参数;现有实现始终把 TEXT/MTEXT 转为动态文本 | 查看完整参数: ```bash dxf2elmt --help ``` ## 当前实体映射 | DXF 实体 | ELMT 图元 | 当前处理方式 | | --- | --- | --- | | `LINE` | `` | 保留两个端点、颜色、线型和数值线宽 | | `CIRCLE` | `` | 以等宽、等高椭圆表示圆 | | `ARC` | `` | 保留圆心、半径、起始角和圆弧角度 | | `ELLIPSE` | `` | 转换中心、长轴和短长轴比例 | | `POLYLINE` | `` / `` / `` | 两个顶点转直线;识别为圆时转椭圆;其余转多边形 | | `LWPOLYLINE` | `` / `` / `` / `` | 根据顶点数、圆形特征和 bulge 分别处理,详细规则见下文 | | `SPLINE` | `` | 按 `spline-step` 采样为折线,不保留参数曲线本身 | | `SOLID` | 填充 `` | 按 DXF 的 `1-2-4-3` 顶点顺序恢复边界并填充 | | `TRACE` | 填充 `` | 与 SOLID 相同,按四边形边界转换并填充 | | `TEXT` | `` | 转换内容、位置、旋转、字号、宽度系数和对齐方式 | | `MTEXT` | `` | 部分支持,转换内容、位置、方向、字号和对齐方式 | | `ATTDEF`(属性定义) | `` | 转换属性标签及其文本样式和位置 | | `LEADER` | 一组 `` | 相邻顶点生成线段,首段可带箭头 | | `INSERT` | 块实例或 `` | 普通 INSERT 展开块;特定连接点块转为端子 | 未列出的实体当前不会生成 ELMT 图元。 ### LWPOLYLINE 映射规则 - 两个顶点且第一个顶点 `bulge != 0`:转换为圆弧。 - 两个顶点且没有 bulge:转换为直线。 - 多个顶点且整体被识别为圆:转换为椭圆。 - 同时包含直线段和 bulge 圆弧段:按段拆分为多个 `` 和 ``,避免圆弧丢失。 - 其他情况:转换为 ``。 - 开放多段线不会把最后一个顶点错误连接回第一个顶点;闭合多段线会保留闭合段。 ## 样式映射 ### 线宽 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 的 `` 定义。 - 普通 INSERT 会展开为带 `block_name` 和 `block_instance` 元数据的块实例图元。 - 嵌套块可以递归转换;序列化时内部图元使用最外层有效实例元数据。 - 名称为 `ARROWUNKNOWN` 且带有 `connector` 属性的 INSERT 会转换为 QElectroTech ``,属性值同时用于端子名称和连接点标签。 - 名称为 `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)