C3D-0157 · READ-ONLY: as-built label positions after the manual nudge [ASB-AFTER] done
Measures each as-built label current location, rotation, attachment and height plus its perpendicular offset and side relative to the feature polyline it names, to diff against the baseline where all four sat exactly on the line. No changes.
C# payload
// AFTER snapshot: the user has nudged the as-built labels by hand. Measure where they ended up so
// the placement convention can be derived from the diff against the BEFORE baseline (all four
// started exactly ON their polyline, offset 0.00).
//
// Captures for each label: location, rotation, attachment, height, and its offset from the
// feature polyline it names - distance and which SIDE - since that offset is the thing being taught.
var ms = (BlockTableRecord)Tx.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(Db), OpenMode.ForWrite);
Log("drawing: " + Db.Filename);
var names = new Dictionary<string,string>();
names["SIDEWALK"] = "SS-V-ROAD-EPVM";
names["WALL"] = "V-STRC-WALL";
names["CONC"] = "X-DRIV-CONC";
names["FENCE"] = "SS-X-FENCE";
Log("");
Log("=== AFTER SNAPSHOT ===");
foreach (ObjectId id in ms) {
var mt = Tx.GetObject(id, OpenMode.ForRead) as MText;
if (mt == null || mt.IsErased) continue;
string c = mt.Contents.Trim().ToUpper();
if (!names.ContainsKey(c)) continue;
// nearest point on the feature polyline this label names
double best = 1e18; double side = 0; Point3d foot = mt.Location;
foreach (ObjectId pid in ms) {
var pl = Tx.GetObject(pid, OpenMode.ForRead) as Polyline;
if (pl == null || pl.IsErased || pl.Layer != names[c]) continue;
for (int i = 0; i < pl.NumberOfVertices - 1; i++) {
var A = pl.GetPoint2dAt(i); var B = pl.GetPoint2dAt(i+1);
double vx = B.X-A.X, vy = B.Y-A.Y, L2 = vx*vx+vy*vy;
double t = L2 > 0 ? ((mt.Location.X-A.X)*vx + (mt.Location.Y-A.Y)*vy)/L2 : 0;
if (t < 0) t = 0; if (t > 1) t = 1;
double qx = A.X+t*vx, qy = A.Y+t*vy;
double d = Math.Sqrt(Math.Pow(mt.Location.X-qx,2)+Math.Pow(mt.Location.Y-qy,2));
if (d < best) {
best = d; foot = new Point3d(qx,qy,0);
side = vx*(mt.Location.Y-A.Y) - vy*(mt.Location.X-A.X);
}
}
}
Log(String.Format("SNAP [{0}] \"{1}\" layer={2} h={3}", mt.Handle, mt.Contents, mt.Layer, mt.TextHeight));
Log(String.Format(" location {0:F4},{1:F4} rotation {2:F4} deg attach {3}",
mt.Location.X, mt.Location.Y, mt.Rotation*180.0/Math.PI, mt.Attachment));
Log(String.Format(" offset from {0}: {1:F4} ft, side {2} (foot {3:F4},{4:F4})",
names[c], best, side > 0 ? "LEFT" : "RIGHT", foot.X, foot.Y));
}
Ed.Regen();
Result
Log
drawing: C:\Users\sanja\OneDrive\_SurveyDisco\260802 - 4082 Sweetbriar Ln, Forest Park, GA 30297, USA\260802 - 4082 Sweetbriar Ln.dwg
=== AFTER SNAPSHOT ===
SNAP [20C89] "WALL" layer=0 h=0.8
location 2238239.0241,1325108.2649 rotation 339.0145 deg attach BottomCenter
offset from V-STRC-WALL: 1.2080 ft, side LEFT (foot 2238239.4567,1325109.3927)
SNAP [20C8F] "SIDEWALK" layer=0 h=0.8
location 2238235.1147,1325145.8381 rotation 66.9887 deg attach BottomCenter
offset from SS-V-ROAD-EPVM: 0.8404 ft, side RIGHT (foot 2238235.8944,1325145.5245)
SNAP [20C91] "FENCE" layer=0 h=0.8
location 2238321.5153,1325109.2537 rotation 30.0905 deg attach BottomCenter
offset from SS-X-FENCE: 1.2350 ft, side LEFT (foot 2238320.8961,1325110.3223)Notes
What worked, what didn't, job-specific gotchas — flagged notes feed the recipes.
No notes yet.