C3D-HCWA-SERVICE · HCWA migration 2b/5: water service + end cap done
Classify the 8 skipped entities as WATER_SERVICE (1in blue water line to bldg, 2in PVC) and WATER_END_CAP (6in permanently capped PVC stub, per HCWA end-cap rule)
C# payload
// HCWA migration 2b/5: WATER SERVICE + END CAP. The 8 entities the water pass refused to
// classify are service-line features (1" blue water line to building, 2" PVC, 6" capped stub).
// HCWA has explicit layers: WATER_SERVICE, and WATER_END_CAP for permanently capped ends.
var bt = (BlockTable)Tx.GetObject(Db.BlockTableId, OpenMode.ForRead);
var ms = (BlockTableRecord)Tx.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
var lt = (LayerTable)Tx.GetObject(Db.LayerTableId, OpenMode.ForRead);
foreach (var n in new[]{"WATER_SERVICE","WATER_END_CAP","WATER_SERVICE_TEXT"})
if (!lt.Has(n)) { Log($"ABORT: layer '{n}' missing."); return; }
// service-feature shot points, by code
var svc = new List<(uint num, string code, Point2d p)>();
foreach (ObjectId id in CivilDoc.CogoPoints) {
var cp = (Autodesk.Civil.DatabaseServices.CogoPoint)Tx.GetObject(id, OpenMode.ForRead);
var u = (cp.RawDescription ?? "").Trim().ToUpperInvariant();
if (u.Contains("PVC") || u.Contains("BLUE WATER") || u.Contains("WATER LINE") || u.Contains("STUB"))
svc.Add((cp.PointNumber, u, new Point2d(cp.Easting, cp.Northing)));
}
Log($"service-coded points: {svc.Count}");
foreach (var s in svc.OrderBy(x=>x.num)) Log($" #{s.num} '{s.code}'");
int moved = 0, caps = 0;
foreach (ObjectId id in ms) {
var o = Tx.GetObject(id, OpenMode.ForRead);
var e = o as Autodesk.AutoCAD.DatabaseServices.Entity;
if (e == null || e.Layer != "V-WATR-STRC") continue;
Point2d q;
if (o is Circle c) q = new Point2d(c.Center.X, c.Center.Y);
else if (o is Polyline pl && pl.NumberOfVertices > 0) {
double sx=0, sy=0; for (int i=0;i<pl.NumberOfVertices;i++){var v=pl.GetPoint2dAt(i); sx+=v.X; sy+=v.Y;}
q = new Point2d(sx/pl.NumberOfVertices, sy/pl.NumberOfVertices);
} else continue;
string code = null; double bd = double.MaxValue;
foreach (var s in svc) { double d = q.GetDistanceTo(s.p); if (d < bd) { bd = d; code = s.code; } }
if (code == null || bd > 12.0) { Log($" still unclassified @({q.X:F1},{q.Y:F1}) — leaving on V-WATR-STRC"); continue; }
// a permanently capped stub is an end-of-line cap, not plain service
bool isCap = code.Contains("STUB") && code.Contains("PVC") && code.Contains("6");
string to = isCap ? "WATER_END_CAP" : "WATER_SERVICE";
var w = (Autodesk.AutoCAD.DatabaseServices.Entity)Tx.GetObject(id, OpenMode.ForWrite);
w.Layer = to;
var chk = (Autodesk.AutoCAD.DatabaseServices.Entity)Tx.GetObject(id, OpenMode.ForRead);
if (chk.Layer != to) continue;
moved++; if (isCap) caps++;
Log($" -> {to} (nearest '{code}' @ {bd:F1}')");
}
Log($"SERVICE migration: {moved} entities moved ({caps} end cap). Remaining backflow/RPZ stays put — no HCWA layer.");
Result
Log
service-coded points: 7 #1096 'GREASE TRAP 6 PVC 6.52 INV 7.77' #1132 '6 IN PVC STUB' #1133 '2 IN PVC LINE' #1134 '1 IN BLUE WATER LINE STUB' #1136 '1 IN BLUE WATER LINE AT BLDING' #1137 'WATER LINE TO BLDG' #1138 'WATER LINE MARK FOR NEW LINE TO BLDG' still unclassified @(2296419.2,1280017.1) — leaving on V-WATR-STRC -> WATER_END_CAP (nearest '6 IN PVC STUB' @ 0.0') -> WATER_SERVICE (nearest '2 IN PVC LINE' @ 0.0') -> WATER_SERVICE (nearest '1 IN BLUE WATER LINE STUB' @ 0.0') -> WATER_SERVICE (nearest '1 IN BLUE WATER LINE AT BLDING' @ 4.6') -> WATER_SERVICE (nearest '1 IN BLUE WATER LINE AT BLDING' @ 0.0') -> WATER_SERVICE (nearest 'WATER LINE TO BLDG' @ 0.0') -> WATER_SERVICE (nearest 'WATER LINE MARK FOR NEW LINE TO BLDG' @ 0.0') SERVICE migration: 7 entities moved (1 end cap). Remaining backflow/RPZ stays put — no HCWA layer.
Notes
What worked, what didn't, job-specific gotchas — flagged notes feed the recipes.
No notes yet.