← Inbox

C3D-QACHECK · HCWA QA sweep (read-only) done

Verify layers, polygon closure, sewer tangents, text type and symbology against the HCWA standard

Script file
C3D-QACHECK.cs
Target
active document · model space
Author
claude
Approved
yes · claude (read-only inspection)
Timeout
60s

C# payload

// Read-only QA sweep against the HCWA As-built CAD Standards. Checks the mechanical, verifiable
// items so the worksheet reflects the drawing rather than assumptions.
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);

Log($"UNITS: INSUNITS={Db.Insunits}");

// 1) required HCWA layers present + populated?
string[] req = { "SEWER_LINE","SEWER_MANHOLE","SEWER_MANHOLE_TEXT","SEWER_LINE_TEXT","SEWER_EASEMENT",
 "SEWER_TAP","SEWER_END_OF_LINE","WATER_LINE","WATER_LINE_TEXT","WATER_VALVE","WATER_VALVE_TEXT",
 "FIRE_HYDRANT","FIRE_HYDRANT_TEXT","FIRE_HYDRANT_VALVE","WATER_METER","WATER_VAULT","WATER_SERVICE",
 "WATER_END_CAP","WATER_EASEMENT","ROAD_EDGE_OF_PAVEMENT","ROAD_RIGHT-OF-WAY","ROAD_TEXT",
 "PROJECT_BOUNDARY","PROPERTY_LINE","ADDRESS_TEXT","LOT_NUMBER_TEXT",
 "HORIZONTAL_AND_VERTICAL_CONTROL_POINT","UTILITY_EASEMENT" };
var count = new Dictionary<string,int>();
foreach (ObjectId id in ms) {
    var e = Tx.GetObject(id, OpenMode.ForRead) as Autodesk.AutoCAD.DatabaseServices.Entity;
    if (e == null) continue;
    count[e.Layer] = count.TryGetValue(e.Layer, out var n) ? n+1 : 1;
}
Log("--- required layers ---");
foreach (var r in req) {
    bool exists = lt.Has(r);
    int c = count.TryGetValue(r, out var n) ? n : 0;
    Log($"  {r,-38} exists={exists,-5} entities={c}");
}

// 2) polygon closure on poly-type layers
Log("--- polygon closure (HCWA: polygons must be closed) ---");
string[] polyLayers = { "ROAD_EDGE_OF_PAVEMENT","ROAD_RIGHT-OF-WAY","SEWER_EASEMENT","WATER_EASEMENT",
                        "PROJECT_BOUNDARY","PROPERTY_LINE","UTILITY_EASEMENT","WATER_VAULT" };
foreach (var L in polyLayers) {
    int open = 0, closed = 0;
    foreach (ObjectId id in ms) {
        var o = Tx.GetObject(id, OpenMode.ForRead);
        if (o is Polyline p && p.Layer == L) { if (p.Closed) closed++; else open++; }
    }
    if (open + closed > 0) Log($"  {L,-28} closed={closed} OPEN={open}{(open>0?"   <== FAIL":"")}");
}

// 3) sewer tangents: one line per tangent + endpoints on manhole centres
var mh = new List<Point2d>();
foreach (ObjectId id in ms) { var o = Tx.GetObject(id, OpenMode.ForRead);
    if (o is Circle c && c.Layer == "SEWER_MANHOLE") mh.Add(new Point2d(c.Center.X, c.Center.Y)); }
int tang = 0, multi = 0, snapped = 0, loose = 0;
foreach (ObjectId id in ms) {
    var o = Tx.GetObject(id, OpenMode.ForRead);
    if (o is Polyline p && p.Layer == "SEWER_LINE" && p.NumberOfVertices > 2) multi++;
    if (!(o is Line l) || l.Layer != "SEWER_LINE") continue;
    tang++;
    foreach (var pt in new[]{ l.StartPoint, l.EndPoint }) {
        double bd = double.MaxValue;
        foreach (var m in mh) { double d = new Point2d(pt.X, pt.Y).GetDistanceTo(m); if (d < bd) bd = d; }
        if (bd < 0.01) snapped++; else loose++;
    }
}
Log($"--- sewer ---");
Log($"  manholes symbolised: {mh.Count}");
Log($"  tangents (Line): {tang},  multi-tangent polylines remaining: {multi}");
Log($"  endpoints exactly on a manhole: {snapped},  not snapped: {loose}");

// 4) text: any MText left on HCWA layers? (HCWA wants single-line text)
int mtext = 0;
foreach (ObjectId id in ms) {
    var o = Tx.GetObject(id, OpenMode.ForRead);
    if (o is MText m2) {
        var u = m2.Layer.ToUpperInvariant();
        if (u.StartsWith("SEWER")||u.StartsWith("WATER")||u.StartsWith("ROAD")||u.StartsWith("FIRE")||u.StartsWith("ADDRESS")) mtext++;
    }
}
Log($"--- text ---");
Log($"  MText still on HCWA layers (should be 0): {mtext}");

// 5) symbols: HCWA wants inserts, not circles
int circMh = 0, circWat = 0, blocks = 0;
foreach (ObjectId id in ms) {
    var o = Tx.GetObject(id, OpenMode.ForRead);
    if (o is Circle c) {
        if (c.Layer == "SEWER_MANHOLE") circMh++;
        if (c.Layer.StartsWith("WATER") || c.Layer.StartsWith("FIRE")) circWat++;
    }
    if (o is BlockReference) blocks++;
}
Log($"--- symbology (HCWA wants Inserts) ---");
Log($"  manholes drawn as Circle: {circMh}  water/hydrant as Circle: {circWat}  BlockReferences: {blocks}");

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

Log

UNITS: INSUNITS=Feet
--- required layers ---
  SEWER_LINE                             exists=True  entities=12
  SEWER_MANHOLE                          exists=True  entities=10
  SEWER_MANHOLE_TEXT                     exists=True  entities=20
  SEWER_LINE_TEXT                        exists=True  entities=7
  SEWER_EASEMENT                         exists=True  entities=3
  SEWER_TAP                              exists=True  entities=0
  SEWER_END_OF_LINE                      exists=True  entities=0
  WATER_LINE                             exists=True  entities=4
  WATER_LINE_TEXT                        exists=True  entities=11
  WATER_VALVE                            exists=True  entities=1
  WATER_VALVE_TEXT                       exists=True  entities=5
  FIRE_HYDRANT                           exists=True  entities=2
  FIRE_HYDRANT_TEXT                      exists=True  entities=3
  FIRE_HYDRANT_VALVE                     exists=True  entities=2
  WATER_METER                            exists=True  entities=0
  WATER_VAULT                            exists=True  entities=2
  WATER_SERVICE                          exists=True  entities=6
  WATER_END_CAP                          exists=True  entities=1
  WATER_EASEMENT                         exists=True  entities=0
  ROAD_EDGE_OF_PAVEMENT                  exists=True  entities=1
  ROAD_RIGHT-OF-WAY                      exists=True  entities=0
  ROAD_TEXT                              exists=True  entities=1
  PROJECT_BOUNDARY                       exists=True  entities=0
  PROPERTY_LINE                          exists=True  entities=0
  ADDRESS_TEXT                           exists=True  entities=0
  LOT_NUMBER_TEXT                        exists=True  entities=0
  HORIZONTAL_AND_VERTICAL_CONTROL_POINT  exists=True  entities=0
  UTILITY_EASEMENT                       exists=True  entities=0
--- polygon closure (HCWA: polygons must be closed) ---
  ROAD_EDGE_OF_PAVEMENT        closed=1 OPEN=0
  WATER_VAULT                  closed=2 OPEN=0
--- sewer ---
  manholes symbolised: 10
  tangents (Line): 12,  multi-tangent polylines remaining: 0
  endpoints exactly on a manhole: 16,  not snapped: 8
--- text ---
  MText still on HCWA layers (should be 0): 0
--- symbology (HCWA wants Inserts) ---
  manholes drawn as Circle: 10  water/hydrant as Circle: 12  BlockReferences: 1

Notes

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

No notes yet.