C3D-0357 · Deep drawing index (retry 3, DBObject qualified) [C3D-INDEX3] done
Retry of C3D-0356 - DBObject was ambiguous between the AutoCAD and Civil namespaces; now fully qualified. Read-only annotation index to C:\Civil3DControl\index\<drawing>.annotations.json.
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 (Autodesk.AutoCAD.DatabaseServices.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
Log
drawing: C:\Users\sanja\OneDrive\_SurveyDisco\260714 - 285 Huckaby Rd, Brooks, GA 30205, USA\260714 - 285 Huckaby Rd R4.dwg
WROTE C:\Civil3DControl\index\260714 - 285 Huckaby Rd R4.annotations.json (24972 bytes)
indexed: 5 dimensions, 118 text, 30 labels, 0 leaders = 153 total
--- dimensions ---
{"h":"213E1","kind":"AlignedDimension","space":"model","layer":"V-NODE-TEXT","style":"Standard","text":"","measurement":40.4549,"textpos":[2206501.026,1207313.335],"textrot":0.0000,"xline1":[2206379.572,1207312.932],"xline2":[2206420.027,1207313.145],"dimline":[2206420.027,1207313.145]}
{"h":"21BA3","kind":"AlignedDimension","space":"model","layer":"SS-V-POWER-EASEMENT","style":"Standard","text":"100'","measurement":99.5858,"textpos":[2203662.892,1207010.310],"textrot":0.0000,"xline1":[2203676.439,1207058.225],"xline2":[2203649.346,1206962.396],"dimline":[2203649.346,1206962.396]}
{"h":"21C55","kind":"AlignedDimension","space":"model","layer":"SS-V-POWER-EASEMENT","style":"Standard","text":"122.0'","measurement":122.0246,"textpos":[2206226.843,1207015.378],"textrot":0.0000,"xline1":[2206226.902,1207076.390],"xline2":[2206226.784,1206954.366],"dimline":[2206226.784,1206954.366]}
{"h":"21C7B","kind":"AlignedDimension","space":"model","layer":"SS-V-POWER-EASEMENT","style":"Standard","text":"168.1'","measurement":168.1058,"textpos":[2206224.141,1207267.345],"textrot":0.0000,"xline1":[2206224.141,1207143.510],"xline2":[2206224.141,1207311.616],"dimline":[2206224.141,1207311.616]}
{"h":"21CFD","kind":"AlignedDimension","space":"model","layer":"SS-V-POWER-EASEMENT","style":"Standard","text":"150'","measurement":150.0016,"textpos":[2203813.700,1207375.243],"textrot":1.5708,"xline1":[2204082.870,1207450.904],"xline2":[2204083.238,1207300.903],"dimline":[2203813.884,1207300.242]}Notes
What worked, what didn't, job-specific gotchas — flagged notes feed the recipes.
No notes yet.