C3D-0152 · Thin the as-built labels to one per feature [ASBUILT-THIN] done
The previous pass labelled every polyline, giving two overlapping WALL labels and five CONC labels on the shared X-DRIV-CONC layer. Keeps the single 0.08 label nearest the longest polyline on each layer and erases the duplicates, then reports the surviving count per layer.
C# payload
// ONE LABEL PER FEATURE. The previous pass put a label on every polyline: 2 WALL (overlapping
// wall lines 0.8 ft apart) and 5 CONC (driveway, pad, apron and drive-sidewalk pieces all share
// X-DRIV-CONC). Keep the label on the LONGEST polyline of each feature and erase the rest.
//
// "Feature" = layer here, since the layer is what names the thing. Only the 0.08 labels created
// by the previous ticket are considered; nothing else is touched.
const double H = 0.08;
var ms = (BlockTableRecord)Tx.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(Db), OpenMode.ForWrite);
// longest polyline per layer = where the single label belongs
var longest = new Dictionary<string, double>();
var longestPt = new Dictionary<string, Point3d>();
foreach (ObjectId id in ms) {
var pl = Tx.GetObject(id, OpenMode.ForRead) as Polyline;
if (pl == null || pl.IsErased) continue;
if (!longest.ContainsKey(pl.Layer) || pl.Length > longest[pl.Layer]) {
longest[pl.Layer] = pl.Length;
try { longestPt[pl.Layer] = pl.GetPointAtDist(pl.Length/2.0); } catch { longestPt[pl.Layer] = pl.StartPoint; }
}
}
// group the 0.08 labels by layer, keep the one nearest that layer's longest polyline midpoint
var byLayer = new Dictionary<string, List<ObjectId>>();
foreach (ObjectId id in ms) {
var mt = Tx.GetObject(id, OpenMode.ForRead) as MText;
if (mt == null || mt.IsErased) continue;
if (Math.Abs(mt.TextHeight - H) > 1e-6) continue;
if (!byLayer.ContainsKey(mt.Layer)) byLayer[mt.Layer] = new List<ObjectId>();
byLayer[mt.Layer].Add(id);
}
int erased = 0, kept = 0;
foreach (var kv in byLayer) {
string lay = kv.Key;
ObjectId keep = ObjectId.Null; double best = 1e18;
foreach (ObjectId id in kv.Value) {
var mt = (MText)Tx.GetObject(id, OpenMode.ForRead);
double d = longestPt.ContainsKey(lay) ? mt.Location.DistanceTo(longestPt[lay]) : 0.0;
if (d < best) { best = d; keep = id; }
}
foreach (ObjectId id in kv.Value) {
var mt = (MText)Tx.GetObject(id, OpenMode.ForRead);
if (id == keep) {
kept++;
Log(String.Format(" KEEP \"{0}\" on {1,-18} at {2:F2},{3:F2}", mt.Contents, lay, mt.Location.X, mt.Location.Y));
} else {
Log(String.Format(" erase \"{0}\" on {1,-18} at {2:F2},{3:F2}", mt.Contents, lay, mt.Location.X, mt.Location.Y));
Tx.GetObject(id, OpenMode.ForWrite).Erase();
erased++;
}
}
}
Log("");
Log("kept: " + kept + " erased: " + erased);
var final = new Dictionary<string,int>();
foreach (ObjectId id in ms) {
var mt = Tx.GetObject(id, OpenMode.ForRead) as MText;
if (mt == null || mt.IsErased) continue;
if (Math.Abs(mt.TextHeight - H) > 1e-6) continue;
if (!final.ContainsKey(mt.Layer)) final[mt.Layer] = 0;
final[mt.Layer]++;
}
foreach (var kv in final) Log(" " + kv.Key + " : " + kv.Value + " label(s)");
Log("(verified)");
Ed.Regen();
Result
Log
KEEP "WALL" on V-STRC-WALL at 2238240.08,1325110.00 erase "WALL" on V-STRC-WALL at 2238239.63,1325109.33 KEEP "CONC" on X-DRIV-CONC at 2238210.22,1325139.07 erase "CONC" on X-DRIV-CONC at 2238187.40,1325151.58 erase "CONC" on X-DRIV-CONC at 2238230.95,1325139.79 erase "CONC" on X-DRIV-CONC at 2238260.85,1325122.44 erase "CONC" on X-DRIV-CONC at 2238275.24,1325161.02 KEEP "SIDEWALK" on SS-V-ROAD-EPVM at 2238232.65,1325138.60 KEEP "FENCE" on SS-X-FENCE at 2238320.85,1325110.30 kept: 4 erased: 5 V-STRC-WALL : 1 label(s) X-DRIV-CONC : 1 label(s) SS-V-ROAD-EPVM : 1 label(s) SS-X-FENCE : 1 label(s) (verified)
Notes
What worked, what didn't, job-specific gotchas — flagged notes feed the recipes.
No notes yet.