← Inbox

C3D-HCWA-WATER · HCWA migration 2/5: water layers done

Split V-WATR-STRC by feature type using nearest coded COGO point: FH/WV/vault. WV within 5ft of a hydrant goes to FIRE_HYDRANT_VALVE per Rev 1.6. RPZ backflow left in place (no HCWA layer).

Script file
C3D-HCWA-WATER.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 2/5: WATER. V-WATR-STRC mixes hydrants/valves/vaults on one layer — HCWA
// requires each on its own. Classify each entity by the NEAREST coded COGO point (not by guess):
//   FH -> FIRE_HYDRANT | WV adjacent to a FH -> FIRE_HYDRANT_VALVE (Rev 1.6) | WV -> WATER_VALVE
//   VAULT COR / WATER VAULT -> WATER_VAULT | RPZ BFP -> left alone (no HCWA layer)
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);
string[] need = { "FIRE_HYDRANT","FIRE_HYDRANT_VALVE","WATER_VALVE","WATER_VAULT","WATER_LINE",
                  "WATER_LINE_TEXT","WATER_VALVE_TEXT","FIRE_HYDRANT_TEXT","WATER_VAULT_TEXT" };
foreach (var n in need) if (!lt.Has(n)) { Log($"ABORT: layer '{n}' missing — run C3D-HCWALAYERS first."); return; }

// --- collect coded water points ---
var cd = CivilDoc;
var pts = new List<(uint num, string code, 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=="FH" || u=="WV" || u.Contains("VAULT") || u.Contains("RPZ"))
        pts.Add((cp.PointNumber, u, new Point2d(cp.Easting, cp.Northing)));
}
// a WV within 5' of a FH is that hydrant's valve -> FIRE_HYDRANT_VALVE
var fh = pts.Where(x => x.code=="FH").ToList();
string ClassOf(Point2d q) {
    var best = ""; double bd = double.MaxValue;
    foreach (var p in pts) { double d = q.GetDistanceTo(p.p); if (d < bd) { bd = d; best = p.code; } }
    if (bd > 12.0) return null;                       // too far from any coded point -> skip
    if (best == "FH") return "FIRE_HYDRANT";
    if (best == "WV") {
        foreach (var h in fh) if (q.GetDistanceTo(h.p) <= 5.0) return "FIRE_HYDRANT_VALVE";
        return "WATER_VALVE";
    }
    if (best.Contains("RPZ")) return null;             // backflow: no HCWA layer, leave in place
    if (best.Contains("VAULT")) return "WATER_VAULT";
    return null;
}

var plan = new List<(ObjectId id, string to)>();
foreach (ObjectId id in ms) {
    var o = Tx.GetObject(id, OpenMode.ForRead);
    var e = o as Autodesk.AutoCAD.DatabaseServices.Entity;
    if (e == null) continue;

    if (e.Layer == "V-WATR-STRC") {
        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);   // centroid
        } else continue;
        var to = ClassOf(q);
        if (to != null) plan.Add((id, to));
        else Log($"  SKIP {o.GetType().Name} @({q.X:F1},{q.Y:F1}) — no confident code match (backflow/unknown)");
    }
    else if (e.Layer == "V-WATR-ALIGN" && (o is Polyline || o is Line))
        plan.Add((id, "WATER_LINE"));
    else if (e.Layer == "V-WATR-TEXT" && o is DBText t) {
        var s = (t.TextString ?? "").ToUpperInvariant();
        string to = "WATER_LINE_TEXT";
        if (s.Contains(" FH") || s.Contains("FHA") || s.StartsWith("FH")) to = "FIRE_HYDRANT_TEXT";
        else if (s.Contains(" WV") || s.Contains("TSV")) to = "WATER_VALVE_TEXT";
        else if (s.Contains("VAULT") || s.Contains("METER") || s.Contains("BFP") || s.Contains("RPZ")) to = "WATER_VAULT_TEXT";
        plan.Add((id, to));
    }
}

int moved = 0; var tally = new Dictionary<string,int>();
foreach (var (id, to) in plan) {
    var e = (Autodesk.AutoCAD.DatabaseServices.Entity)Tx.GetObject(id, OpenMode.ForWrite);
    if (e.Layer == to) continue;
    e.Layer = to;
    var chk = (Autodesk.AutoCAD.DatabaseServices.Entity)Tx.GetObject(id, OpenMode.ForRead);
    if (chk.Layer != to) continue;
    tally[to] = tally.TryGetValue(to, out var n) ? n+1 : 1; moved++;
}
foreach (var kv in tally.OrderBy(k => k.Key)) Log($"  -> {kv.Key}: {kv.Value} entities (verified)");
Log($"WATER migration: {moved} entities moved. Backflow (RPZ) intentionally left — no HCWA layer.");

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-WATER (0 entities touched).
Entities
Duration
400 ms
Civil 3D
25.0.0.0

Log

  SKIP Polyline @(2296419.2,1280017.1) — no confident code match (backflow/unknown)
  SKIP Circle @(2296549.9,1280052.8) — no confident code match (backflow/unknown)
  SKIP Circle @(2296556.1,1280062.3) — no confident code match (backflow/unknown)
  SKIP Circle @(2296560.0,1280062.9) — no confident code match (backflow/unknown)
  SKIP Circle @(2296654.3,1280077.4) — no confident code match (backflow/unknown)
  SKIP Circle @(2296654.8,1280082.0) — no confident code match (backflow/unknown)
  SKIP Circle @(2296563.1,1280064.9) — no confident code match (backflow/unknown)
  SKIP Circle @(2296595.4,1280069.3) — no confident code match (backflow/unknown)
  -> FIRE_HYDRANT: 2 entities (verified)
  -> FIRE_HYDRANT_TEXT: 3 entities (verified)
  -> FIRE_HYDRANT_VALVE: 2 entities (verified)
  -> WATER_LINE: 4 entities (verified)
  -> WATER_LINE_TEXT: 11 entities (verified)
  -> WATER_VALVE: 1 entities (verified)
  -> WATER_VALVE_TEXT: 5 entities (verified)
  -> WATER_VAULT: 2 entities (verified)
  -> WATER_VAULT_TEXT: 4 entities (verified)
WATER migration: 34 entities moved. Backflow (RPZ) intentionally left — no HCWA layer.

Notes

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

No notes yet.