cad2d-ir is a typed intermediate representation and conversion toolkit
for 2D CAD data.
It provides:
- a canonical JSON Schema for 2D CAD geometry and tables;
- native DXF, DWG, DGN, DWF/DWFx, EDRW (eDrawings), EXB, HP-GL/PLT, ICD (iCAD SX), IDW, JWW, JWS, MI/BI, SXF, and vector PDF import paths;
- DXF R12 (
AC1009) and R2010 (AC1024) export; - structured import/export diagnostics;
- deterministic IR-entity to DXF-handle correspondence.
pip install cad2d-ir
pip install "cad2d-ir[dwg]"
pip install "cad2d-ir[dgn]"
pip install "cad2d-ir[dwf]"
pip install "cad2d-ir[edrawings]" # eDrawings drawings (.edrw); Linux x86_64, Windows, macOS arm64
# HP-GL: install local ezhpgl + cad2d-ir wheels until the first ezhpgl release
# then: pip install "cad2d-ir[hpgl]"
pip install "cad2d-ir[idw]" # Python 3.11+; see the IDW license notice below
pip install "cad2d-ir[jww]"
pip install "cad2d-ir[mi]"
pip install "cad2d-ir[pdf]" # vector PDF (pypdfium2)
pip install "cad2d-ir[sxf]"
pip install "cad2d-ir[all]"Python 3.10 or newer is required. The core wheel is pure Python; native format adapters are optional extras.
IDW license notice: IDW support uses
inventor-kit, which is offered under PolyForm Noncommercial 1.0.0 with separate commercial licenses. Before using IDW in commercial workflows, including internal business use, review the IDW licensing terms.
pip install cad2d-ir and pip install "cad2d-ir[all]" do not install
inventor-kit; install [idw] explicitly when needed. The development command
uv sync --all-extras below includes [idw] and installs inventor-kit.
HP-GL uses ezhpgl through the optional [hpgl] extra. See HP-GL conversion
for local wheel installation, paper-space mapping, page selection and loss reporting.
For development, the current lock requires an adjacent ../ezhpgl checkout
until its first registry release. Registry CI validation follows publication:
uv sync
uv sync --all-extras
uv run python -m pytestIR entities include LINE, CIRCLE, ARC, POINT,
ELLIPSE, LWPOLYLINE, SPLINE, TEXT,
MTEXT, INSERT, HATCH, DIMENSION, and IMAGE.
Layer, linetype, text-style, dimension-style, and block tables are represented
by the schema. entities is model space; the paper-space sheets of a DXF or
DWG drawing, with their viewports onto model space, are kept apart in layouts.
Import adapters:
| Format | Path | Dependency |
|---|---|---|
| DXF | built-in parser | core |
| DWG | native ezdwg model |
cad2d-ir[dwg] |
| DGN V7 2D / V8 | native ezdgn models |
cad2d-ir[dgn] |
| DWF/DWFx 2D | normalized ezdwf sheet model |
cad2d-ir[dwf] |
| EDRW (eDrawings drawing sheets) | HOOPS segment tree from edrawings-kit |
cad2d-ir[edrawings] |
| EXB (CAXA CAD / 电子图板) | stored-entity model from ezexb |
cad2d-ir[exb] |
| HP-GL / HP-GL/2 / bounded PCL/PJL | Rust plot model from ezhpgl |
cad2d-ir[hpgl] |
| ICD (iCAD SX 2D drawing area) | saved views and entities from icadkit |
cad2d-ir[icad] |
| IDW (Autodesk Inventor drawing) | saved-display model from inventor-kit |
cad2d-ir[idw] |
| JWW | native ezjww model |
cad2d-ir[jww] |
| JWS (Jw_cad registered symbol) | native ezjww model (0.7 or later) |
cad2d-ir[jww] |
| MI / gzip-wrapped BI | native ezmi2d document model |
cad2d-ir[mi] |
| PDF (vector plot) | PDFium page objects via pypdfium2; arcs, linetypes, layers, text and plot scale recovered |
cad2d-ir[pdf] |
| SXF SFC/P21 | backend-neutral ezsxf drawing |
cad2d-ir[sxf] |
Native adapters preserve source semantics and provenance rather than flattening through an intermediate DXF.
# Validate IR
cad2d-ir validate examples/ir/minimal.json
# DXF -> IR with BOM/codepage/UTF-8/CP932 detection
cad2d-ir dxf2ir drawing.dxf -o drawing.json --pretty
cad2d-ir dxf2ir drawing.dxf --encoding cp932 -o drawing.json
# Auto-detected DXF/DWG/DGN/DWF/DWFx/EDRW/EXB/HP-GL/ICD/IDW/JWW/JWS/MI/BI/PDF/SFC/P21 -> IR
cad2d-ir import drawing.JWW -o drawing.json --pretty
cad2d-ir import drawing.dwg -o drawing.json --pretty
cad2d-ir import drawing.dgn -o drawing.json --pretty
cad2d-ir import drawing.dwfx -o drawing.json --pretty
cad2d-ir import drawing.edrw -o drawing.json --pretty
cad2d-ir import drawing.exb -o drawing.json --pretty
cad2d-ir import drawing.idw -o drawing.json --pretty
cad2d-ir import drawing.mi -o drawing.json --pretty
cad2d-ir import plot.pdf -o plot.json --pretty
cad2d-ir import drawing.p21 -o drawing.json --pretty
# HP-GL -> all-page IR, or one explicit paper-space DXF page
cad2d-ir import drawing.plt -o drawing.ir.json --pretty
cad2d-ir hpgl2dxf drawing.plt --page 1 -o page1.dxf --report page1-report.json
# Status 1 means a partial/approximate result was written; inspect the report.
# IR -> R2010 or R12 DXF
cad2d-ir ir2dxf drawing.json --target-version AC1024 -o drawing-r2010.dxf
cad2d-ir ir2dxf drawing.json --target-version AC1009 \
--encoding cp932 --curve-segments 128 -o drawing-r12.dxffrom cad2d_ir import convert_file_to_ir, convert_ir_to_dxf_text
imported = convert_file_to_ir("drawing.dxf", strict=False)
print(imported.statistics["encoding"])
for diagnostic in imported.diagnostics:
print(diagnostic.code, diagnostic.as_dict())
exported = convert_ir_to_dxf_text(
imported.document,
target_version="AC1024",
generic_dimensions="explode",
)
for entry in exported.entity_map:
print(entry["ir_id"], entry["handle"], entry["dxf_type"])R2010 output assigns deterministic handles and emits $HANDSEED.
Re-importing the DXF records each handle in entity.source.id. R12 omits
handles and retains deterministic index values in the entity map.
convert_file_to_ir("model.dwg", keep_3d=True) additionally returns the
geometry DWG/DXF sources had before XY projection (3D polylines, faces, block
placements, counts of unreadable solids) in ImportResult.model3d; the IR
itself stays two-dimensional. See docs/IMPORTERS.md, "3D side channel".
TABLEScontains LAYER, LTYPE, and STYLE records from IR tables.- GENERIC dimensions expand to their preserved visual primitives by default.
- R12 declares
$DWGCODEPAGE=ANSI_932and file output uses CP932 by default; LWPOLYLINE becomes POLYLINE/VERTEX, MTEXT becomes TEXT, ELLIPSE/SPLINE become sampled polylines, and HATCH becomes boundary polylines. - Every skip, approximation, explosion, and normalization is represented by an
ExportDiagnostic. - The same document and options produce byte-identical DXF and entity-map output within a package minor version.
constraintsare IR-only and are diagnosed when omitted from DXF.- A complete affine
INSERT.transformcannot be represented by plain DXF INSERT and is diagnosed when omitted. - R12 has no true-color, lineweight, or
$INSUNITSequivalent with the same semantics; downgrade diagnostics disclose those losses. - HATCH support focuses on polyline-style loops.
- Ellipse start/end parameters are radians independently of
header.angle_unit. - DGN import covers V7 2D and native V8 documents. V7 text encoding
auto-detection probes ASCII, CP932, then Latin-1 at file scope; V8 text
arrives already decoded per element.
ezdgnrejects V7 3D; V8 3D models and multi-model files are reduced to one projected model with explicit loss diagnostics, and V8 shared-cell definitions, fills, color tables, and spline knots are not decoded yet. - DWF/DWFx import preserves sheet identity in metadata while placing supported 2D entities and markups in one IR modelspace. Raster payloads and complex brush semantics remain source metadata/diagnostics rather than invented IR geometry.
- IDW import consumes the saved sheet display returned by
inventor_kit.read_drawing_file(lines, curves, filled triangles, text and image placements as Inventor stored them). It does not open referenced IPT/IAM files or regenerate views, so drawing views that Inventor saved only as raster caches (for example every view in 2027-era files) have no vector geometry in the IR; their placements are kept insource.metadata.idwand disclosed byIDW_VIEW_RASTER_ONLY/IDW_IMAGE_NOT_IN_IR. Coordinates are sheet paper space scaled from Inventor's internal centimetres to millimetres (IDW_UNITS_ASSUMED_CM); multiple sheets are tiled along +X. Supported segment majors followinventor-kit(23, 24, 26, 28, 29, 31 in 0.6.0); other profiles raiseImporterError("unsupported IDW profile ...").inventor-kitneeds Python 3.11+; see the IDW licensing terms. It also declarescq-acis(CadQuery/OCCT, about 1 GB) for IPT/IAM geometry, which the IDW path never imports. Consumers that only need IDW can exclude it, for example with uv'soverride-dependencies = ["cq-acis; python_full_version < '0'"]orpip install --no-deps inventor-kit. - MI import consumes
ezmi2d>=0.2,<0.3directly. Part definitions and shared occurrences become IR blocks and INSERTs; source radians are normalized to IR degrees..bidispatch covers the gzip-wrapped MI container verified byezmi2d, not every historical Drafting/ME10 BI compression variant.
See:
src/cad2d_ir/
api.py
cli.py
diagnostics.py
schema.py
codecs/dxf.py
importers/
data/ir_schema.json
ir_schema.json
tests/
examples/
docs/
cad2d-ir itself is licensed under MIT (LICENSE), including its IDW
adapter code. Optional parser dependencies retain their own licenses.
IDW support depends on inventor-kit, which is offered under
PolyForm Noncommercial 1.0.0
with separate commercial licenses from UnRobotics Inc. The MIT license for
cad2d-ir does not grant additional rights to use or redistribute inventor-kit.
- Use permitted by the PolyForm terms does not require a commercial agreement.
- Use outside those permissions, including commercial internal business use and commercial product integration, requires a separate written commercial agreement with UnRobotics Inc. See the upstream commercial licensing guide and contact form.
- If you redistribute
inventor-kitwith your application, comply with its distribution terms and preserve the applicable license texts and notices.
These additional conditions concern the inventor-kit dependency used for IDW
support. Workflows using only other formats do not require inventor-kit;
their respective dependency licenses still apply. Refer to the upstream
license notice
for the full scope, including earlier MIT material and third-party components.