secondmouseau/swiftdxf
A small, dependency-free Swift reader for ASCII DXF — AutoCAD's Drawing Interchange Format —
What it reads
The 2D entity set that dominates real-world drawings, from the ENTITIES (model-space) section:
| DXF entity | DXF.Entity case | |---|---| | LINE | .line(a, b, layer, color) | | CIRCLE | .circle(center, radius, …) | | ARC | .arc(center, radius, startDeg, endDeg, …) | | ELLIPSE | .ellipse(center, majorAxis, ratio, startParam, endParam, …) | | POINT | .point(at, …) | | TEXT, MTEXT | .text(at, height, rotationDeg, string, …) | | LWPOLYLINE, POLYLINE/VERTEX | .polyline(vertices, closed, …) — each vertex carries its bulge | | DIMENSION | .dimension(Dimension) — semantic measurement only, not the rendered arrow/text glyphs |
Entities it does not model (e.g. INSERT, SPLINE, HATCH) are skipped, not fatal.
Drawing also exposes header essentials: version ($ACADVER), insUnits ($INSUNITS), and the declared extMin / extMax extents ($EXTMIN / $EXTMAX), plus a computed bounds over the entities actually read.
Behaviours worth knowing
- Encoding. Files are decoded as UTF-8 when valid, otherwise CP932 / Shift-JIS — the common
code page for DXF exported by Japanese CAD tools (e.g. Jw_cad). Because CP932 is an ASCII superset, the group-code structure is unaffected either way. AutoCAD \U+XXXX text escapes are decoded.
- Line endings & padding. Handles LF / CRLF / CR and R12-style space-padded group codes (
0). - Ellipse normalisation. DXF requires
ratio = minor/major ≤ 1. Files that emitratio > 1
(a swapped major axis) are normalised to the canonical form — same curve, valid axis — so consumers like OCCT's Geom_Ellipse (which demands majorRadius ≥ minorRadius) get correct geometry. This matches ezdxf's normalisation exactly.
- Binary DXF is detected and rejected (
Error.binaryUnsupported) — convert to ASCII DXF first. - Model space only. Mirrors what
ezdxf'smodelspace()iterates;BLOCKSdefinitions are not
expanded.
Correctness: tested against an oracle
tools/oracle.py runs ezdxf over the same files and emits per-file entity counts and a geometry digest (the sum of every defining coordinate scalar, in document order). The dxfdump executable emits the identical shape from SwiftDXF:
swift run dxfdump drawing.dxf | python3 -m json.toolAcross an 11-file corpus (~62,000 entities, mixed R12 drawings incl. Jw_cad exports), SwiftDXF matches ezdxf exactly — every entity count and every coordinate scalar, to the bit. The Tests/SwiftDXFTests/CorpusOracleTests.swift suite pins those ezdxf-derived counts as a regression gate (skipped when the corpus is absent; point DXF_CORPUS at a folder of .dxf files to run).
Install
.package(url: "https://github.com/SecondMouseAU/SwiftDXF.git", from: "0.1.0"),
// target dependency: .product(name: "SwiftDXF", package: "SwiftDXF")Scope
A focused 2D reader, not a full DXF/DWG toolkit. Out of scope for now: DWG, binary DXF, block/insert expansion, splines, hatches, dimensions, and writing. (DXF writing for the JWW format lives in SwiftJWW.)
License
MIT — see LICENSE.
Package Metadata
Repository: secondmouseau/swiftdxf
Default branch: main
README: README.md