Reading 3D Solids with ezdxf Python: Extract ACIS Payloads from DXF Files
To read 3D solids with ezdxf in Python, query 3DSOLID entities from the DXF modelspace and access their embedded ACIS/SAT payload via the .acis property. ezdxf does not reconstruct B-Rep topology, generate meshes, or convert parametric geometry to standard triangle formats — it exposes the raw ACIS string exactly as stored in the DXF file. For production AEC/GIS pipelines, pair this extraction with a dedicated ACIS parser or geometry kernel (python-occ, OpenCASCADE, or cadquery) to convert the payload into usable vertices, faces, or STEP/IGES outputs. For broader entity traversal and memory-efficient DXF processing, see the ezdxf Deep Dive.
How ezdxf Handles 3D Solids in DXF Files
AutoCAD stores parametric 3D geometry as 3DSOLID entities. Unlike basic 3DFACE or MESH objects, 3DSOLID entities encapsulate a complete Boundary Representation (B-Rep) inside a proprietary ACIS/SAT text blob. When you parse a DXF file, ezdxf reads this blob directly from DXF group codes 1 and 3, making it accessible through the .acis property as a list of strings — one string per ACIS line.
The diagram below shows where 3DSOLID fits in a DXF entity pipeline and why ACIS payloads must be routed separately from faceted geometry.
In automated interoperability workflows, treating 3DSOLID as a raw payload — rather than a ready-to-render mesh — prevents topology corruption. DXF files frequently mix faceted approximations (MESH, 3DFACE) with true parametric solids. Routing ACIS payloads to a downstream conversion service preserves precision and avoids silent data loss that occurs when forcing solids into polygonal formats prematurely.
This distinction also matters for Geometry & Mesh Conversion workflows: attempting to pass an unprocessed 3DSOLID entity directly into trimesh or a GeoJSON serializer will silently drop the geometry.
Production-Ready Script
The following script safely extracts ACIS payloads from all 3DSOLID entities in a DXF file, handles multi-line ACIS data, validates the payload header, and writes structured JSON for downstream processing.
# ezdxf>=1.1.0, Python 3.9+
import ezdxf
import json
import sys
from pathlib import Path
from typing import List, Dict, Any
def extract_3dsolid_acis(dxf_path: str, output_json: str) -> None:
"""Extract ACIS/SAT payloads from 3DSOLID entities in a DXF file."""
try:
doc = ezdxf.readfile(dxf_path)
msp = doc.modelspace()
except ezdxf.DXFError as e:
sys.exit(f"Failed to load DXF: {e}")
# The correct DXF entity type string is "3DSOLID" — not "SOLID3D"
solids = msp.query("3DSOLID")
if not solids:
print("No 3DSOLID entities found in modelspace.")
return
extracted: List[Dict[str, Any]] = []
for solid in solids:
# .acis returns list[str] — one entry per SAT line
acis_lines: List[str] = solid.acis
if not acis_lines:
# Likely encrypted; log the handle for licensed ACIS SDK processing
print(f"Warning: Handle {solid.dxf.handle} has empty ACIS payload (possibly encrypted).")
continue
acis_str = "\n".join(acis_lines)
# Validate ACIS header: first line must start with "ACIS" or "ASM"
first_line = acis_lines[0].strip()
if not (first_line.startswith("ACIS") or first_line.startswith("ASM")):
print(f"Warning: Handle {solid.dxf.handle} has unrecognized ACIS header: {first_line!r}")
continue
extracted.append({
"entity_handle": solid.dxf.handle,
"layer": solid.dxf.layer,
"acis_version": first_line,
"line_count": len(acis_lines),
"payload_length_bytes": len(acis_str.encode("utf-8")),
"raw_acis": acis_str,
})
Path(output_json).write_text(json.dumps(extracted, indent=2), encoding="utf-8")
print(f"Extracted {len(extracted)} 3DSOLID payloads → {output_json}")
if __name__ == "__main__":
extract_3dsolid_acis("input.dxf", "solids_acis.json")
Key implementation notes:
msp.query("3DSOLID")uses the correct DXF type string. The variantSOLID3Ddoes not exist in the DXF specification and will return no results silently.solid.acisreturnslist[str], one entry per SAT line. Do not attemptsolid.dxf.acis_data— that attribute does not exist on thedxfnamespace object and will raiseDXFAttributeError.- Some AutoCAD 2021+ versions store ACIS data as an encrypted binary blob. These payloads will appear as an empty list and must be handled separately (see fallback strategies below).
- Separating metadata (
entity_handle,layer,acis_version) from the raw payload in the output JSON lets downstream batch routers filter and dispatch without loading full ACIS strings unnecessarily. - The
DXFErrorguard aroundezdxf.readfile()catches malformed headers and version mismatches before any entity iteration begins — especially important when processing bulk DXF exports from DXF entity structure breakdown pipelines.
Compatibility Matrix
| Component | Supported Range | Notes |
|---|---|---|
ezdxf version |
>=1.0.0 |
Earlier versions may handle ACIS line joining differently; >=1.1.0 recommended. |
| Python | 3.9+ |
Uses typing, pathlib, and walrus-free list comprehensions. |
| DXF format | R2000 (AC1015) — R2018 (AC1032) |
3DSOLID stabilized in R2000. Newer versions may encrypt ACIS. |
| ACIS/SAT format | v1.0 — v7.x |
Proprietary Spatial format. Full parsing requires OpenCASCADE, python-occ, or a licensed ACIS SDK. |
| OS | Cross-platform | ACIS parsing binaries from OpenCASCADE often require platform-native builds. |
| Encrypted payloads | AutoCAD 2021+ | solid.acis returns []; requires Spatial ACIS SDK or AutoCAD batch export as STEP before processing. |
| Custom entity types | Civil 3D, Plant 3D | May use subclass extensions that lack standard ACIS headers; validate before routing. |
For the official entity specification, see the Autodesk DXF Reference for 3DSOLID. For geometry kernel integration, consult the OpenCASCADE documentation.
Fallback Strategies When ACIS Extraction Fails
ACIS payloads fail in automated pipelines for three main reasons: encryption (AutoCAD 2021+), ACIS version mismatches, or proprietary subclass extensions from vertical products. Implement these fallbacks in priority order to maintain pipeline continuity.
1. Pre-process to mesh before DXF export
Run a batch AutoLISP or .NET script inside AutoCAD or Civil 3D to convert 3DSOLID entities to MESH entities before the DXF is written. ezdxf then resolves faceted geometry via MESH or 3DFACE queries, bypassing ACIS entirely. This is the most reliable fallback for pipelines where you control the export step.
2. Export as STEP or IGES from the source application
Convert solids to *.step or *.iges using AutoCAD’s export dialog or a command-line batch script. STEP preserves full B-Rep topology and is natively importable by python-occ (pythonOCC) and cadquery. This is the recommended path when parametric accuracy must be preserved for spatial analysis or BIM-to-GIS coordinate transformation — for example, before running CAD local coordinate to EPSG:4326 conversion.
# python-occ STEP import example (pythonOCC>=7.7.0)
from OCC.Core.STEPControl import STEPControl_Reader
from OCC.Core.IFSelect import IFSelect_RetDone
reader = STEPControl_Reader()
status = reader.ReadFile("model.step")
if status == IFSelect_RetDone:
reader.TransferRoots()
shape = reader.OneShape()
3. Use trimesh for polygonal approximations
If the DXF contains embedded mesh approximations alongside the solids, extract facets from MESH and 3DFACE entities and pass them to trimesh for lightweight analysis. This bypasses B-Rep reconstruction but sacrifices parametric precision — acceptable for visual validation or GIS footprint extraction but not for engineering tolerances.
4. Handle encrypted payloads explicitly
When solid.acis returns [] or the first line does not start with ACIS/ASM, log the entity handle and skip conversion. Batch-log affected files for manual review or for routing to a licensed Spatial ACIS SDK. Never let a silent empty-list result pass through as valid geometry — this is a common source of corrupt spatial indexes downstream.
5. Validate ACIS headers in CI gates
Add a pre-processing assertion that counts entities where solid.acis is non-empty versus total 3DSOLID count. If more than 20% of solids have empty payloads, fail the pipeline early and raise an alert rather than silently producing an incomplete geometry dataset. This is particularly important in batch DXF processing pipelines that feed into GIS ingestion or BIM coordination workflows.
Does ezdxf reconstruct B-Rep topology from 3DSOLID entities?
No. ezdxf exposes only the raw ACIS/SAT text blob stored in DXF group codes 1 and 3. It does not parse ACIS geometry, generate triangle meshes, or rebuild B-Rep topology. A separate geometry kernel — such as OpenCASCADE via python-occ — is required for any mesh reconstruction or solid analysis.
Why does solid.acis return an empty list?
AutoCAD 2021 and later versions can store ACIS data as an encrypted binary blob when the drawing contains licensed geometry or DRM-protected content. When encryption is applied, ezdxf cannot decode the payload and .acis returns []. Log the entity handle and route the file to a licensed Spatial ACIS SDK or export as STEP from within AutoCAD.
What is the difference between 3DSOLID and MESH in DXF?
3DSOLID stores a parametric Boundary Representation encoded as an ACIS/SAT string — it carries exact topology, curved surfaces, and feature history. MESH and 3DFACE store explicit polygonal facets: a list of vertices and face indices with no parametric information. ezdxf can extract vertex coordinates from MESH and 3DFACE directly; 3DSOLID requires ACIS parsing for full geometry access.
Can I convert a 3DSOLID ACIS payload to STEP without AutoCAD?
Yes. python-occ (pythonOCC) wraps OpenCASCADE and can import ACIS strings via BRepTools then export using STEPControl_Writer. cadquery provides a higher-level interface to the same OpenCASCADE backend. Both approaches preserve B-Rep topology and produce standards-conformant STEP files suitable for downstream GIS or structural analysis.
Related Pages
- ezdxf Deep Dive: Production-Grade DXF Parsing — parent reference covering entity traversal, block references, and memory-efficient DXF processing
- Python Parsing & Geometry Extraction — overview of the full extraction pipeline from DXF and IFC ingestion through to GIS-ready outputs
- Geometry & Mesh Conversion — converting extracted geometry (including solid approximations) to GeoJSON, trimesh, and other polygonal formats
- Converting CAD Local Coordinates to EPSG:4326 — georeferencing the vertex data produced after ACIS-to-mesh conversion
- DXF Entity Structure Breakdown — group code taxonomy and section structure that governs how
3DSOLIDpayloads are stored and read