Skip to content

Extract parcels from plat linework

Plat drawings almost never contain closed parcel polylines. Each boundary is drawn as open courses — one entity per bearing/distance call — and the “parcel” only exists where courses happen to enclose an area. extract_parcels recovers those enclosures: it nodes all linework on matching layers (splitting every segment at every intersection) and assembles the resulting faces into polygons with area, perimeter, and centroid.

This guide is the practical how-to. The geometric why lives in Why parcels need polygonization.

Run survey_dxf_layers with contains: "PROP" (or "BNDY", "LOT") before anything else. Boundary linework hides on layers you won’t guess, including bound-xref names like XREF-PLAN$0$C-PROP-LINE. Layer matching helps you here: patterns also match the suffix after the last $, so C-PROP* catches the bound-xref variant automatically.

{
"tool": "extract_parcels",
"operation": {
"file_path": "/data/site-plan.dxf",
"operation": "extract",
"parameters": {
"layer_pattern": "C-PROP*",
"min_area_sqft": 100,
"max_parcels": 500
}
}
}
Parameter Default What it does
layer_pattern "C-PROP*" fnmatch pattern selecting boundary layers (bound-xref suffixes included)
min_area_sqft 100 drops sliver faces below this area — noding artifacts, double-drawn lines
max_parcels 500 cap on returned parcels, largest first

DXF only — convert DWG first.

{
"success": true,
"parcels_found": 38,
"parcels": [
{
"area_sqft": 100623.4,
"area_acres": 2.31,
"perimeter_ft": 1284.9,
"centroid": { "x": 154102.2, "y": 88254.7 }
}
],
"diagnostics": {
"dangling_segments": 6,
"invalid_rings": 0
}
}

Areas assume drawing units are feet ($INSUNITS = 2); a units_note warns you when the header says otherwise.

The diagnostics explain linework that failed to close, which is often the real finding:

  • dangling_segments — courses with a free end that touch nothing. A parcel missing from the output usually traces to one dangling course: a gap where two lines almost-but-don’t meet, or a boundary that continues on a layer your pattern didn’t match. Widen the pattern or survey again.
  • invalid_rings — cut edges and self-intersections that polygonization rejected. Rare in surveyed linework; common in decorative or annotation-adjacent geometry that leaked onto a boundary layer.

A good verification loop: render the same pattern with render_svg and look at where the linework visibly gaps. Then cross-check totals with measure_by_layer on the same pattern — it uses the identical noding pipeline, so enclosed areas reconcile exactly.

  • Sliver threshold. If legitimate small features (utility easements, pump-house lots) are missing, lower min_area_sqft. If you get confetti, raise it.
  • Pooling layers. When boundaries span multiple layers (common after xref binding), a wider pattern like *PROP* lets faces close across layers. measure_by_layer with group_by: "pattern" does the same pooling for measurement.
  • Curve accuracy. Arcs and bulged polylines are flattened at a 0.5 ft sagitta tolerance — far below plat accuracy, so acreage figures are stable against the flattening.