C3D-TRACTAB · Read TRACT A/B layers + their bearing labels (read-only) done
Contents of SS-BOUNDARY TRACT A/B and where each tract's bearing labels live (type+layer), to bold the boundary + bearings per tract.
C# payload
// READ-ONLY: what's on SS-BOUNDARY TRACT A and TRACT B, and where the bearing labels for each tract live.
// For each tract layer: list entities (type + geometry). Then find bearing/distance labels near each
// tract (GeneralSegmentLabel/NoteLabel/MText/DBText containing ° or bearing chars) with their layer +
// position, so we know which labels belong to A vs B and what layer to bold/move.
using System;
using System.Linq;
using System.Collections.Generic;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
var db = Db;
// Tract centroids from recon
var A = new Point2d(2166741.9, 1330610.1);
var B = new Point2d(2166659.9, 1330379.4);
// 1) contents of each tract boundary layer
using (var tr = db.TransactionManager.StartTransaction())
{
var ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
foreach (var layer in new[]{"SS-BOUNDARY TRACT A","SS-BOUNDARY TRACT B"})
{
Log($"== LAYER '{layer}' ==");
foreach (ObjectId id in ms)
{
var e = tr.GetObject(id, OpenMode.ForRead) as Autodesk.AutoCAD.DatabaseServices.Entity;
if (e == null || !string.Equals(e.Layer, layer, StringComparison.OrdinalIgnoreCase)) continue;
string extra="";
if (e is Polyline pl) extra=$" verts={pl.NumberOfVertices} len={pl.Length:0.0} closed={pl.Closed} lw={pl.ConstantWidth}";
else if (e is Line ln) extra=$" len={ln.Length:0.0}";
Log($" {e.GetType().Name} lw={e.LineWeight}{extra}");
}
}
tr.Commit();
}
// 2) bearing-type labels: classify near A vs B by proximity, report their layer + type + position
using (var tr = db.TransactionManager.StartTransaction())
{
var ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
var aLbl = new SortedDictionary<string,int>(StringComparer.OrdinalIgnoreCase);
var bLbl = new SortedDictionary<string,int>(StringComparer.OrdinalIgnoreCase);
int aC=0, bC=0;
foreach (ObjectId id in ms)
{
var e = tr.GetObject(id, OpenMode.ForRead) as Autodesk.AutoCAD.DatabaseServices.Entity;
if (e == null) continue;
string tn = e.GetType().Name;
bool isLabelType = tn=="GeneralSegmentLabel" || tn=="NoteLabel" || tn=="MText" || tn=="DBText";
if (!isLabelType) continue;
// text content check for bearing-ish (° or quotes) — but Civil labels have no easy text; use type+proximity
string s=null;
if (e is MText m) s=m.Text; else if (e is DBText t) s=t.TextString;
bool bearingText = s!=null && (s.Contains("°") || s.Contains("\"") || s.Contains("E") || s.Contains("W"));
Point3d pos;
try { var ex=e.GeometricExtents; pos=new Point3d((ex.MinPoint.X+ex.MaxPoint.X)/2,(ex.MinPoint.Y+ex.MaxPoint.Y)/2,0); } catch { continue; }
// only consider labels reasonably near the tracts (within ~400')
double dA=pos.DistanceTo(new Point3d(A.X,A.Y,0)), dB=pos.DistanceTo(new Point3d(B.X,B.Y,0));
if (Math.Min(dA,dB) > 400) continue;
// GeneralSegmentLabel/NoteLabel are the survey bearing labels; MText/DBText only if bearingText
if (tn=="MText" || tn=="DBText") { if(!bearingText) continue; }
var key=$"{tn} @ {e.Layer}";
if (dA <= dB) { aLbl[key]=aLbl.TryGetValue(key,out var c)?c+1:1; aC++; }
else { bLbl[key]=bLbl.TryGetValue(key,out var c)?c+1:1; bC++; }
}
Log($"BEARING-TYPE LABELS NEAR TRACT A ({aC}):"); foreach(var kv in aLbl) Log($" {kv.Value}x {kv.Key}");
Log($"BEARING-TYPE LABELS NEAR TRACT B ({bC}):"); foreach(var kv in bLbl) Log($" {kv.Value}x {kv.Key}");
tr.Commit();
}
Result
Log
== LAYER 'SS-BOUNDARY TRACT A' == Parcel lw=ByLayer == LAYER 'SS-BOUNDARY TRACT B' == Polyline lw=ByLayer verts=8 len=1984.5 closed=True lw=0 BEARING-TYPE LABELS NEAR TRACT A (12): 2x GeneralSegmentLabel @ C-ANNO 8x MText @ C-ANNO 2x MText @ SS-BOUNDARY BEARING-TYPE LABELS NEAR TRACT B (7): 3x MText @ C-ANNO 3x MText @ SS-0-FRAME 1x MText @ SS-BOUNDARY
Notes
What worked, what didn't, job-specific gotchas — flagged notes feed the recipes.
No notes yet.