← Inbox

C3D-0356 · Deep drawing index (retry, escape fn fixed) [C3D-INDEX2] error

Retry of C3D-0355 which failed to compile because the shell heredoc ate the backslash literals in the JSON-escape helper. The helper now builds backslash and quote via (char)92 and (char)34. Read-only: walks model space and every layout, writes every dimension/text/label/leader to C:\Civil3DControl\index\<drawing>.annotations.json with handle, kind, space, layer, style, text and geometry (for dims: measurement, text position/rotation, extension and dim-line points), and echoes all dimensions.

Script file
C3D-0356.cs
Target
260714 - 285 Huckaby Rd R3.dwg · model space
Author
claude
Approved
yes · auto-auth
Timeout
180s

C# payload

// DEEP DRAWING INDEX (read-only). Every annotation object in model space and every layout,
// written as JSON to the plugin box so Claude can grep it instead of guessing.
//
// Per object: handle, kind, owning space, text, layer, style, and the geometry that answers
// "is the number inside the arrows or along the line" - for dimensions that means the dim-line
// endpoints, the text position, and the measurement.
var civ = Autodesk.Civil.ApplicationServices.CivilApplication.ActiveDocument;
Log("drawing: " + Db.Filename);

string J(string s) {
    if (s == null) return "";
    char BS = (char)92;
    var sb = new System.Text.StringBuilder();
    foreach (char c in s) {
        if (c == BS) { sb.Append(BS); sb.Append(BS); }
        else if (c == (char)34) { sb.Append(BS); sb.Append(c); }
        else if (c == (char)10) { sb.Append(BS); sb.Append((char)110); }
        else if (c == (char)13) { }
        else if (c == (char)9) sb.Append((char)32);
        else sb.Append(c);
    }
    return sb.ToString();
}

var rows = new List<string>();
int nDim=0, nText=0, nLabel=0, nLeader=0, nOther=0;

System.Action<ObjectId,string> handle = (id, space) => {
    var o = Tx.GetObject(id, OpenMode.ForRead);
    var ent = o as Autodesk.AutoCAD.DatabaseServices.Entity;
    if (ent == null) return;
    string kind = o.GetType().Name;
    string layer = ent.Layer;

    var dim = o as Dimension;
    var mt  = o as MText;
    var dt  = o as DBText;

    // classify - only annotation-ish things
    bool isDim = dim != null;
    bool isTxt = mt != null || dt != null;
    bool isLbl = kind.IndexOf("Label", StringComparison.OrdinalIgnoreCase) >= 0;
    bool isLdr = (o is Leader) || (o is MLeader);
    if (!isDim && !isTxt && !isLbl && !isLdr) return;

    string text = "";
    if (dim != null) text = dim.DimensionText ?? "";       // "" means the measured value is shown
    else if (mt != null) text = mt.Contents;
    else if (dt != null) text = dt.TextString;
    else {
        // labels/leaders: explode to read what they display
        try {
            var col = new DBObjectCollection(); ent.Explode(col);
            foreach (DBObject p in col) {
                var m2 = p as MText; var d2 = p as DBText;
                if (m2 != null) text += " " + m2.Contents;
                else if (d2 != null) text += " " + d2.TextString;
            }
            text = text.Trim();
        } catch { }
    }

    string style = "";
    string geom = "";
    if (dim != null) {
        try {
            var st = (DimStyleTableRecord)Tx.GetObject(dim.DimensionStyle, OpenMode.ForRead);
            style = st.Name;
        } catch { }
        // measurement + placement
        double meas = 0; try { meas = dim.Measurement; } catch { }
        Point3d tp = dim.TextPosition;
        // dim-line endpoints depend on the concrete type
        string ends = "";
        var ad = o as AlignedDimension;
        var rd = o as RotatedDimension;
        if (ad != null) ends = string.Format("\"xline1\":[{0:F3},{1:F3}],\"xline2\":[{2:F3},{3:F3}],\"dimline\":[{4:F3},{5:F3}]",
            ad.XLine1Point.X, ad.XLine1Point.Y, ad.XLine2Point.X, ad.XLine2Point.Y, ad.DimLinePoint.X, ad.DimLinePoint.Y);
        else if (rd != null) ends = string.Format("\"xline1\":[{0:F3},{1:F3}],\"xline2\":[{2:F3},{3:F3}],\"dimline\":[{4:F3},{5:F3}],\"rot\":{6:F4}",
            rd.XLine1Point.X, rd.XLine1Point.Y, rd.XLine2Point.X, rd.XLine2Point.Y, rd.DimLinePoint.X, rd.DimLinePoint.Y, rd.Rotation);
        geom = string.Format("\"measurement\":{0:F4},\"textpos\":[{1:F3},{2:F3}],\"textrot\":{3:F4},{4}",
            meas, tp.X, tp.Y, dim.TextRotation, ends);
        nDim++;
    } else {
        Point3d p = mt != null ? mt.Location : (dt != null ? dt.Position : Point3d.Origin);
        double rot = mt != null ? mt.Rotation : (dt != null ? dt.Rotation : 0);
        double h   = mt != null ? mt.TextHeight : (dt != null ? dt.Height : 0);
        geom = string.Format("\"pos\":[{0:F3},{1:F3}],\"rot\":{2:F4},\"height\":{3:F3}", p.X, p.Y, rot, h);
        if (isTxt) nText++; else if (isLbl) nLabel++; else nLeader++;
    }

    string disp = text.Length > 120 ? text.Substring(0,120) : text;
    rows.Add(string.Format(
        "{{\"h\":\"{0}\",\"kind\":\"{1}\",\"space\":\"{2}\",\"layer\":\"{3}\",\"style\":\"{4}\",\"text\":\"{5}\",{6}}}",
        ent.Handle, kind, space, J(layer), J(style), J(disp), geom));
};

// model space
var ms = (BlockTableRecord)Tx.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(Db), OpenMode.ForRead);
foreach (ObjectId id in ms) handle(id, "model");

// every layout
var dict = (DBDictionary)Tx.GetObject(Db.LayoutDictionaryId, OpenMode.ForRead);
foreach (DBDictionaryEntry de in dict) {
    if (de.Key == "Model") continue;
    var lay = (Layout)Tx.GetObject(de.Value, OpenMode.ForRead);
    var btr = (BlockTableRecord)Tx.GetObject(lay.BlockTableRecordId, OpenMode.ForRead);
    foreach (ObjectId id in btr) handle(id, lay.LayoutName);
}

// write it to the plugin box
string dir = "C:" + ((char)92) + "Civil3DControl" + ((char)92) + "index";
System.IO.Directory.CreateDirectory(dir);
string baseName = System.IO.Path.GetFileNameWithoutExtension(Db.Filename);
string outPath = System.IO.Path.Combine(dir, baseName + ".annotations.json");
var sb2 = new System.Text.StringBuilder();
sb2.Append("{\"drawing\":\"").Append(J(Db.Filename)).Append("\",\"count\":").Append(rows.Count).Append(",\"items\":[\r\n");
for (int i = 0; i < rows.Count; i++) { sb2.Append(rows[i]); if (i < rows.Count-1) sb2.Append(","); sb2.Append("\r\n"); }
sb2.Append("]}\r\n");
System.IO.File.WriteAllText(outPath, sb2.ToString(), new System.Text.UTF8Encoding(false));

Log("WROTE " + outPath + "  (" + new System.IO.FileInfo(outPath).Length + " bytes)");
Log(string.Format("indexed: {0} dimensions, {1} text, {2} labels, {3} leaders  = {4} total",
    nDim, nText, nLabel, nLeader, rows.Count));
// echo the dimensions so we can see them here immediately
Log("");
Log("--- dimensions ---");
foreach (var r in rows) if (r.Contains("\"measurement\"")) Log("  " + r);

Result

Status
error
Drawing file
C:\Users\sanja\OneDrive\_SurveyDisco\260714 - 285 Huckaby Rd, Brooks, GA 30205, USA\260714 - 285 Huckaby Rd R4.dwg
Message
Compile error: (54,22): error CS0104: 'DBObject' is an ambiguous reference between 'Autodesk.AutoCAD.DatabaseServices.DBObject' and 'Autodesk.Civil.DatabaseServices.DBObject'
Entities
Duration
1521 ms
Civil 3D
25.0.0.0

Notes

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

No notes yet.