← Inbox

C3D-0074 · READ-ONLY: current labels against true line lengths [LBL-VS-LENGTH] done

Reads every SEWER_LINE line with its measured length and assigns each SEWER_LINE_TEXT label to its nearest line, reporting the labels as they read now (the user has edited some), including the slope labels. No changes.

Script file
C3D-0074.cs
Target
260612 · model space
Author
claude
Approved
yes · reviewer
Timeout
240s

C# payload

// READ-ONLY. For every sewer line: its true length, and the labels currently sitting on it.
// The user has edited labels since they were placed, so read them fresh - do not reuse the
// values from the placement ticket.
//
// Each SEWER_LINE_TEXT MText is assigned to the nearest line by perpendicular distance to that
// line's midpoint region, then reported under that line. Both the length label and the slope
// label (the one containing '%') are surfaced so either can be checked.
// Nothing is modified.
var ms = (BlockTableRecord)Tx.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(Db), OpenMode.ForRead);
Func<Func<string>, string> safe = f => { try { return f(); } catch (System.Exception ex) { return "<" + ex.GetType().Name + ">"; } };

// 1) the lines
var lines = new List<object[]>();   // handle, x1,y1, x2,y2, length
foreach (ObjectId id in ms) {
    var o = Tx.GetObject(id, OpenMode.ForRead);
    var ent = o as Autodesk.AutoCAD.DatabaseServices.Entity;
    if (ent == null || safe(() => ent.Layer) != "SEWER_LINE") continue;
    var ln = o as Line;
    if (ln == null) continue;
    lines.Add(new object[] { o.Handle.ToString(), ln.StartPoint.X, ln.StartPoint.Y,
                             ln.EndPoint.X, ln.EndPoint.Y, ln.Length });
}

// 2) every label on the text layers, assigned to its closest line
var labels = new Dictionary<string, List<string>>();
int stray = 0;
foreach (ObjectId id in ms) {
    var o = Tx.GetObject(id, OpenMode.ForRead);
    var mt = o as MText;
    if (mt == null) continue;
    string lay = safe(() => mt.Layer);
    if (lay != "SEWER_LINE_TEXT") continue;

    double lx = mt.Location.X, ly = mt.Location.Y;
    string best = null; double bd = 1e18;
    foreach (var L in lines) {
        double x1 = (double)L[1], y1 = (double)L[2], x2 = (double)L[3], y2 = (double)L[4];
        double vx = x2 - x1, vy = y2 - y1;
        double len2 = vx*vx + vy*vy;
        double t = len2 > 0 ? ((lx-x1)*vx + (ly-y1)*vy) / len2 : 0.0;
        if (t < 0) t = 0; if (t > 1) t = 1;
        double px = x1 + t*vx, py = y1 + t*vy;
        double d = Math.Sqrt((lx-px)*(lx-px) + (ly-py)*(ly-py));
        if (d < bd) { bd = d; best = (string)L[0]; }
    }
    string txt = mt.Contents.Replace(@"\P", " ").Trim();
    if (best == null || bd > 40.0) { stray++; Log("  STRAY LABEL [" + o.Handle + "] \"" + txt + "\" nearest " + best + " at " + bd.ToString("F1") + "ft"); continue; }
    if (!labels.ContainsKey(best)) labels[best] = new List<string>();
    labels[best].Add(txt + "  (" + bd.ToString("F1") + "ft off)");
}

Log("");
Log("=== SEWER LINES: true length + current labels ===");
lines.Sort((a,b) => String.Compare((string)a[0], (string)b[0]));
foreach (var L in lines) {
    string h = (string)L[0];
    Log("");
    Log(String.Format("[{0}]  LENGTH = {1:F2}", h, (double)L[5]));
    if (!labels.ContainsKey(h)) { Log("     (no labels)"); continue; }
    foreach (var s in labels[h]) Log("     " + s);
}
Log("");
Log("lines=" + lines.Count + "  stray labels=" + stray);

Result

Status
success
Drawing file
C:\Users\sanja\OneDrive\_SurveyDisco\260613 - 5030 E Lake Pkwy, Stockbridge, GA 30281, USA\260612 - CSTORE WATER ABS 30.dwg
Message
Executed C3D-0074 (0 entities touched).
Entities
Duration
363 ms
Civil 3D
25.0.0.0

Log


=== SEWER LINES: true length + current labels ===

[2E95F]  LENGTH = 12.07
     12.07'  (2.0ft off)

[2EC86]  LENGTH = 132.52
     131.42'  (2.0ft off)
     15.79%  (3.2ft off)

[2EC87]  LENGTH = 133.21
     133.04'  (2.0ft off)
     N/A  (3.2ft off)

[2EC88]  LENGTH = 55.14
     55.11'  (2.0ft off)
     N/A  (3.2ft off)

[2EC89]  LENGTH = 86.31
     86.31'  (6.4ft off)
     0.59%  (3.2ft off)
     2.25%  (1.1ft off)

[2EC8A]  LENGTH = 30.97
     30.96'  (2.0ft off)
     6.98%  (3.2ft off)

[2EC8B]  LENGTH = 133.46
     133.45'  (1.7ft off)
     1.29%  (4.6ft off)

[2EC8C]  LENGTH = 80.46
     80.39'  (6.4ft off)
     15.60%  (3.2ft off)

[2EC8D]  LENGTH = 161.58
     161.58'  (2.0ft off)
     12.37%  (3.2ft off)

[2EC8E]  LENGTH = 359.02
     358.92'  (2.0ft off)
     1.16%  (3.2ft off)

[2EC8F]  LENGTH = 80.02
     79.84'  (2.0ft off)
     0.50%  (3.2ft off)

[2EC90]  LENGTH = 155.37
     155.36'  (2.0ft off)
     0.60%  (3.2ft off)

[2EC91]  LENGTH = 19.54
     19.53'  (2.0ft off)
     2.41%  (3.2ft off)

[2EC92]  LENGTH = 8.66
     8.66'  (2.0ft off)

lines=14  stray labels=0

Notes

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

No notes yet.