Tools: DXF analysis
The six tools on this page run on pure ezdxf/shapely — no CAD kernel, no display, host-side or in-container alike. All of them:
- accept DXF only (error:
"...reads DXF only; convert DWG to DXF first"— see Handle DWG) - accept both ASCII and binary DXF encodings transparently — the shared loader sniffs the encoding and routes text files through ezdxf’s recover mode (real-world files carry thousands of fixable defects), while binary files take the strict reader, because recover mode cannot parse binary DXF at all
- take the standard operation envelope; parameters listed below go in
operation.parameters - enforce the file-size limit and path validation, returning
{"error": "..."}on violation - treat layer patterns as fnmatch, also matching the suffix after the last
$so bound-xref layer names likeXREF-PLAN$0$C-PROP-LINEmatchC-PROP*(see Xref shells)
survey_dxf_layers
Section titled “survey_dxf_layers”Inventory which DXF layers actually carry geometry, and how much — modelspace plus geometry inside block references (INSERT expansion).
Use this before extract_parcels to discover the right layer_pattern: real civil drawings scatter boundary linework across hundreds of layers, and guessing patterns blind wastes calls.
| Parameter | Type / default | Description |
|---|---|---|
contains |
string, "" |
case-insensitive substring filter on layer names (e.g. "PROP", "ROAD") |
include_blocks |
bool, true |
expand INSERT references |
top |
int, 60 |
max layers returned, busiest first |
Returns a busiest-first list of layers with entity counts broken down by entity type, plus totals. Errors: missing file, non-DXF input, unsafe path.
extract_parcels
Section titled “extract_parcels”Extract closed parcel polygons and acreage from open boundary linework in a DXF file (civil/survey plat drawings).
Real plat linework draws parcels as open courses, not closed polylines. This tool nodes all linework on layers matching the pattern (splitting at every intersection) and assembles the enclosed faces — the full mechanism is described in Why parcels need polygonization.
| Parameter | Type / default | Description |
|---|---|---|
layer_pattern |
string, "C-PROP*" |
fnmatch pattern for boundary layers |
min_area_sqft |
float, 100 |
drop sliver faces below this area |
max_parcels |
int, 500 |
cap on returned parcels, largest first |
Returns each parcel’s area (sq ft and acres), perimeter, and centroid, plus diagnostics (dangling_segments, invalid_rings) explaining any linework that failed to close. Areas assume feet ($INSUNITS = 2); a units note warns otherwise. Errors: missing file, oversize file, non-DXF input.
extract_annotations
Section titled “extract_annotations”Extract all text content from a DXF file: modelspace and paperspace TEXT/MTEXT, text inside block definitions, MTEXT embedded in MULTILEADER callouts, and ATTRIB values on block references — with MTEXT formatting codes stripped.
Naive text queries silently miss MULTILEADER-embedded content and block-internal text; this tool walks all five sources. On civil drawings, multileaders are exactly where lot labels and callouts hide, and “silently missing one annotation” is the failure mode a title company cares about.
| Parameter | Type / default | Description |
|---|---|---|
pattern |
string, none | case-insensitive regex; matched against the plain text and a single-line whitespace-normalized form, so multi-line labels match one-line patterns |
layer_pattern |
string, "*" |
fnmatch filter on layer names, bound-xref suffixes included |
include_blocks |
bool, true |
walk block definitions |
include_paperspace |
bool, true |
walk paperspace layouts |
max_results |
int, 2000 |
cap on returned annotations; annotations_found still reports the full match count |
Returns annotations, each with its text, layer, insertion point, and container — "modelspace", "layout:C4", "block:NAME", or "...:insert:BLOCKNAME" for attribute values.
A drawing with no text anywhere returns annotations_found: 0 with an empty list. Zero is a valid answer, not an error — verified against a dense 16,000-entity mechanical drawing that is pure linework.
list_sheets
Section titled “list_sheets”Enumerate the paperspace layouts (plan-set sheets) in a DXF file with per-sheet metadata: name, paper size (mm and inches), entity count, and harvested title-block text.
Use this to build a sheet index of a plan set (“which sheet is the grading plan?”) without rendering anything. The title_block_text list is deliberately raw candidate strings — direct TEXT/MTEXT in the layout plus text and attribute values inside INSERTed title-block blocks (nested sub-blocks followed a couple of levels). The calling LLM interprets which string is the sheet title.
| Parameter | Type / default | Description |
|---|---|---|
include_model |
bool, false |
include the Model layout as a pseudo-sheet (callers usually want deliverable sheets only) |
max_text_per_sheet |
int, 60 |
cap on harvested strings per sheet |
measure_by_layer
Section titled “measure_by_layer”Roll up linework quantities per DXF layer: total length (curves flattened) and closed-polygon area/acreage recovered by noding the linework and assembling enclosed faces — the same pipeline as extract_parcels, so the two reconcile.
Use this for quantity-takeoff questions (“how many feet of road edge?”, “how much area do the easement boundaries enclose?”). Zero closed_area with nonzero length is normal for open linework (centerlines, profiles); dangling_segments explains why faces did not close.
| Parameter | Type / default | Description |
|---|---|---|
layer_pattern |
string, "*" |
fnmatch pattern for layers to measure — prefer something narrower like "C-ROAD*" on large files |
group_by |
string, "layer" |
"layer" = one rollup row per matched layer; "pattern" = pool all matched linework into a single rollup, letting faces close across layers |
include_blocks |
bool, true |
expand INSERT references, transforms applied |
min_area_sqft |
float, 100 |
drop sliver faces below this area |
Returns per-layer (or pooled) rollups with total length, closed area in sq ft and acres, and dangling-segment counts. Lengths/areas assume feet; units_note warns otherwise. Annotation entity types (TEXT, MTEXT, HATCH, DIMENSION, MULTILEADER) are never counted as linework.
render_svg
Section titled “render_svg”Render a DXF layout to an SVG file, filtered to layers matching a pattern — a quick visual of exactly the linework you care about (just the parcel boundaries, or one full sheet).
| Parameter | Type / default | Description |
|---|---|---|
layer_pattern |
string, "*" |
fnmatch pattern for layers to render |
output_name |
string, "render" |
output filename stem, no path separators; file becomes <output_name>.svg |
layout |
string, "Model" |
"Model" or a paperspace sheet name from list_sheets |
Returns the output path (under the server’s output directory), file size, entity count, and SVG element count.
Behavior worth knowing (details in Render layer-filtered SVGs):
- Frozen/off layers that match the pattern are force-rendered — naming a pattern means you want to see it.
- A pattern matching nothing returns an error with similar layer names as a hint, never an empty file.
- Rendering a full sheet of a large civil file can take ~10 s and produce multi-MB output — prefer narrow patterns.