← Inbox

C3D-HCWA-POLY · HCWA migration 3/5: close polygons + build EOP done

Close sewer easement polylines (gaps are an explicit rejection criterion) and build ROAD_EDGE_OF_PAVEMENT as a closed polygon from the 8 surveyed EP points. TBC back-of-curb deliberately excluded per HCWA 'not back of curb'.

Script file
C3D-HCWA-POLY.cs
Target
C:\Users\sanja\OneDrive\_SurveyDisco\260613 - 5030 E Lake Pkwy, Stockbridge, GA 30281, USA\CSTORE WATER ABS-260612_SHEET.dwg · model space
Author
claude
Approved
yes · sanjay (batch-approved: HCWA migration)
Timeout
60s

C# payload

// HCWA migration 3/5: POLYGON CLOSURE. "All Polygon type features must be completely closed.
// Gaps in polygon boundaries will not be accepted." Closes sewer easements, and builds
// ROAD_EDGE_OF_PAVEMENT from the surveyed EP points (HCWA: EOP is "not back of curb", so the
// TBC curb linework is deliberately NOT used here).
var bt = (BlockTable)Tx.GetObject(Db.BlockTableId, OpenMode.ForRead);
var ms = (BlockTableRecord)Tx.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
var lt = (LayerTable)Tx.GetObject(Db.LayerTableId, OpenMode.ForRead);
foreach (var n in new[]{"SEWER_EASEMENT","ROAD_EDGE_OF_PAVEMENT"})
    if (!lt.Has(n)) { Log($"ABORT: layer '{n}' missing — run C3D-HCWALAYERS first."); return; }

// --- 1) close any open polyline already on SEWER_EASEMENT ---
int closed = 0;
foreach (ObjectId id in ms) {
    var o = Tx.GetObject(id, OpenMode.ForRead);
    if (o is Polyline pl && pl.Layer == "SEWER_EASEMENT" && !pl.Closed && pl.NumberOfVertices >= 3) {
        var w = (Polyline)Tx.GetObject(id, OpenMode.ForWrite);
        w.Closed = true;
        var chk = (Polyline)Tx.GetObject(id, OpenMode.ForRead);
        if (chk.Closed) { closed++; Log($"  closed easement polyline v={chk.NumberOfVertices} len={chk.Length:F1}'"); }
    }
}
Log($"Sewer easements closed: {closed}");

// --- 2) build ROAD_EDGE_OF_PAVEMENT from surveyed EP points ---
// Idempotent: skip if an EOP polygon already exists.
bool haveEop = false;
foreach (ObjectId id in ms) {
    var e = Tx.GetObject(id, OpenMode.ForRead) as Autodesk.AutoCAD.DatabaseServices.Entity;
    if (e != null && e.Layer == "ROAD_EDGE_OF_PAVEMENT") { haveEop = true; break; }
}
if (haveEop) { Log("ROAD_EDGE_OF_PAVEMENT already populated — skipping (idempotent)."); return; }

var cd = CivilDoc;
var ep = new List<(uint num, Point2d p)>();
foreach (ObjectId id in cd.CogoPoints) {
    var cp = (Autodesk.Civil.DatabaseServices.CogoPoint)Tx.GetObject(id, OpenMode.ForRead);
    var u = (cp.RawDescription ?? "").Trim().ToUpperInvariant();
    if (u == "EP" || u == "EP TBC") ep.Add((cp.PointNumber, new Point2d(cp.Easting, cp.Northing)));
}
if (ep.Count < 3) { Log($"only {ep.Count} EP points — cannot close a polygon"); return; }

// EP points fall in two north/south bands (two sides of the pavement). Split on the midpoint of
// the N range, order each band by Easting, then walk out along one band and back along the other
// so the ring never self-crosses.
double nMin = ep.Min(x => x.p.Y), nMax = ep.Max(x => x.p.Y), nMid = (nMin + nMax) / 2.0;
var south = ep.Where(x => x.p.Y <= nMid).OrderBy(x => x.p.X).ToList();
var north = ep.Where(x => x.p.Y  > nMid).OrderByDescending(x => x.p.X).ToList();
Log($"EP bands: south={south.Count} (N<={nMid:F1}), north={north.Count}");
if (south.Count == 0 || north.Count == 0) { Log("EP points not in two bands — needs manual review"); return; }

var ring = new List<(uint num, Point2d p)>();
ring.AddRange(south); ring.AddRange(north);
var poly = new Polyline();
for (int i = 0; i < ring.Count; i++) poly.AddVertexAt(i, ring[i].p, 0, 0, 0);
poly.Closed = true;                       // HCWA: must be a closed polygon
poly.Layer = "ROAD_EDGE_OF_PAVEMENT";
ms.AppendEntity(poly); Tx.AddNewlyCreatedDBObject(poly, true);

var v = (Polyline)Tx.GetObject(poly.ObjectId, OpenMode.ForRead);
Log($"ROAD_EDGE_OF_PAVEMENT: closed={v.Closed} v={v.NumberOfVertices} perim={v.Length:F1}' area={v.Area:F0} sf (verified)");
Log("  ring order: " + string.Join(" ", ring.Select(x => x.num)));
Log("NOTE: built from EP shots only. TBC (back of curb) intentionally excluded per HCWA.");

Result

Status
success
Drawing file
C:\Users\sanja\OneDrive\_SurveyDisco\260613 - 5030 E Lake Pkwy, Stockbridge, GA 30281, USA\CSTORE WATER ABS-260612_SHEET.dwg
Message
Executed C3D-HCWA-POLY (0 entities touched).
Entities
Duration
415 ms
Civil 3D
25.0.0.0

Log

  closed easement polyline v=3 len=452.3'
  closed easement polyline v=6 len=1020.4'
  closed easement polyline v=4 len=481.7'
Sewer easements closed: 3
EP bands: south=6 (N<=1280321.6), north=2
ROAD_EDGE_OF_PAVEMENT: closed=True v=8 perim=429.2' area=9221 sf (verified)
  ring order: 1047 1049 1048 1027 1026 1003 1014 1016
NOTE: built from EP shots only. TBC (back of curb) intentionally excluded per HCWA.

Notes

What worked, what didn't, job-specific gotchas — flagged notes feed the recipes.

No notes yet.