Skip to content

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 like XREF-PLAN$0$C-PROP-LINE match C-PROP* (see Xref shells)

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 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 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.


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

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 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.