C3D-HCWA-TANGENT2 · HCWA: re-snap tangents to all 10 manholes done
Re-run endpoint snapping now that manholes 101 and 102 are symbolized
C# payload
// HCWA migration 4/5: SEWER TANGENTS. HCWA: "All tangents between sewer manholes need to be drawn
// with a single line. Lines must not continue for more than one tangent." + "All tangents must be
// snapped at endpoints intersecting at the exact center of the manhole."
// Explodes any multi-segment polyline on SEWER_LINE into one Line per tangent, then snaps every
// SEWER_LINE endpoint to the nearest manhole center within tolerance.
var bt = (BlockTable)Tx.GetObject(Db.BlockTableId, OpenMode.ForRead);
var ms = (BlockTableRecord)Tx.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
// manhole centers (circles now on SEWER_MANHOLE)
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));
}
Log($"manhole centers found: {mh.Count}");
// 1) explode multi-segment polylines into per-tangent lines
var kill = new List<ObjectId>(); int madeLines = 0;
foreach (ObjectId id in ms) {
var o = Tx.GetObject(id, OpenMode.ForRead);
if (!(o is Polyline pl) || pl.Layer != "SEWER_LINE") continue;
if (pl.NumberOfVertices < 3) continue; // already a single tangent
for (int i = 0; i < pl.NumberOfVertices - 1; i++) {
var a = pl.GetPoint2dAt(i); var b = pl.GetPoint2dAt(i+1);
var ln = new Line(new Point3d(a.X,a.Y,0), new Point3d(b.X,b.Y,0)) { Layer = "SEWER_LINE" };
ms.AppendEntity(ln); Tx.AddNewlyCreatedDBObject(ln, true); madeLines++;
}
kill.Add(id);
Log($" exploded polyline v={pl.NumberOfVertices} -> {pl.NumberOfVertices-1} tangents");
}
foreach (var id in kill) { var e = (Autodesk.AutoCAD.DatabaseServices.Entity)Tx.GetObject(id, OpenMode.ForWrite); e.Erase(); }
// 2) snap endpoints to manhole centers (tolerance 6')
const double TOL = 6.0;
int snapped = 0;
Point3d Snap(Point3d p, ref bool did) {
var q = new Point2d(p.X, p.Y); double bd = double.MaxValue; Point2d best = q;
foreach (var m in mh) { double d = q.GetDistanceTo(m); if (d < bd) { bd = d; best = m; } }
if (bd > 0.0001 && bd <= TOL) { did = true; return new Point3d(best.X, best.Y, p.Z); }
return p;
}
foreach (ObjectId id in ms) {
var o = Tx.GetObject(id, OpenMode.ForRead);
if (!(o is Line l) || l.Layer != "SEWER_LINE") continue;
bool a = false, b = false;
var ns = Snap(l.StartPoint, ref a); var ne = Snap(l.EndPoint, ref b);
if (!a && !b) continue;
var w = (Line)Tx.GetObject(id, OpenMode.ForWrite);
if (a) w.StartPoint = ns;
if (b) w.EndPoint = ne;
snapped++;
}
Log($"tangents created: {madeLines}, lines with endpoints snapped to MH centers: {snapped}");
// 3) report directionality (HCWA: uphill node -> downhill node). Report only; no auto-flip,
// because inverts live in text, not on the geometry.
int n = 0;
foreach (ObjectId id in ms) {
var o = Tx.GetObject(id, OpenMode.ForRead);
if (o is Line l && l.Layer == "SEWER_LINE") n++;
}
Log($"SEWER_LINE tangents now: {n}. Directionality (uphill->downhill) must be verified against inverts — see SEWER_MANHOLE_TEXT.");
Result
Log
manhole centers found: 10 tangents created: 0, lines with endpoints snapped to MH centers: 0 SEWER_LINE tangents now: 12. Directionality (uphill->downhill) must be verified against inverts — see SEWER_MANHOLE_TEXT.
Notes
What worked, what didn't, job-specific gotchas — flagged notes feed the recipes.
No notes yet.