← Inbox

C3D-MATCHLBL · Match bearing labels to TRACT A/B segments (read-only) error

Assign each bearing label to the tract boundary segment it annotates (A parcel exploded, B polyline). Reports handle+layer+tract+distance.

Script file
C3D-MATCHLBL.cs
Target
active document · model space
Author
claude
Approved
yes · claude (read-only)
Timeout
60s

C# payload

// READ-ONLY: match each bearing label to the tract boundary it annotates.
// Build A and B boundary segment lists (A = Parcel segments; B = Polyline segments).
// For every bearing-type label (GeneralSegmentLabel/NoteLabel + MText/DBText with bearing chars),
// find the nearest boundary segment across A and B; assign to that tract if within ~15'. Report each
// label: handle, type, layer, assigned tract, distance.
using System;
using System.Linq;
using System.Collections.Generic;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.Civil.ApplicationServices;
using Autodesk.Civil.DatabaseServices;

var db = Db;

// collect boundary segments as (p1,p2) for A and B
var segA = new List<(Point3d a, Point3d b)>();
var segB = new List<(Point3d a, Point3d b)>();

using (var tr = db.TransactionManager.StartTransaction())
{
    var ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);

    // B: polyline on SS-BOUNDARY TRACT B
    foreach (ObjectId id in ms)
    {
        var e = tr.GetObject(id, OpenMode.ForRead) as Autodesk.AutoCAD.DatabaseServices.Entity;
        if (e is Polyline pl && string.Equals(e.Layer,"SS-BOUNDARY TRACT B",StringComparison.OrdinalIgnoreCase))
        {
            int n = pl.NumberOfVertices;
            for (int i=0;i<n;i++){ var p1=pl.GetPoint3dAt(i); var p2=pl.GetPoint3dAt((i+1)%n); segB.Add((p1,p2)); }
        }
    }

    // A: Parcel on SS-BOUNDARY TRACT A — explode to component curves for segment geometry.
    var cdoc = CivilDocument.GetCivilDocument(db);
    foreach (ObjectId sid in cdoc.GetSiteIds())
    {
        var site=(Site)tr.GetObject(sid,OpenMode.ForRead);
        foreach (ObjectId pid in site.GetParcelIds())
        {
            var p=(Parcel)tr.GetObject(pid,OpenMode.ForRead);
            if (!string.Equals(p.Layer,"SS-BOUNDARY TRACT A",StringComparison.OrdinalIgnoreCase)) continue;
            var dbo = new DBObjectCollection();
            try { p.Explode(dbo); } catch (System.Exception ex) { Log($"parcel A explode note: {ex.Message}"); }
            foreach (DBObject o in dbo)
            {
                if (o is Line l) segA.Add((l.StartPoint, l.EndPoint));
                else if (o is Arc ar) { segA.Add((ar.StartPoint, ar.EndPoint)); }
                else if (o is Polyline pp){ int n=pp.NumberOfVertices; for(int i=0;i<n-1;i++) segA.Add((pp.GetPoint3dAt(i),pp.GetPoint3dAt(i+1))); }
            }
        }
    }
    Log($"segA(Parcel)={segA.Count}  segB(Polyline)={segB.Count}");

    double DistToSeg(Point3d pt, Point3d a, Point3d b)
    {
        var ab=b-a; double len2=ab.LengthSqrd; if(len2==0) return pt.DistanceTo(a);
        double t=((pt-a).DotProduct(ab))/len2; t=Math.Max(0,Math.Min(1,t));
        var proj=a+ab*t; return pt.DistanceTo(proj);
    }

    int aN=0,bN=0,un=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 cand = tn=="GeneralSegmentLabel" || tn=="NoteLabel";
        string s=null; if(e is MText m) s=m.Text; else if(e is DBText t) s=t.TextString;
        if((tn=="MText"||tn=="DBText") && s!=null && (s.Contains("°")||s.Contains("\""))) cand=true;
        if(!cand) continue;
        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;}
        double dA=segA.Count>0?segA.Min(sg=>DistToSeg(pos,sg.a,sg.b)):9e9;
        double dB=segB.Count>0?segB.Min(sg=>DistToSeg(pos,sg.a,sg.b)):9e9;
        string who; double d;
        if(Math.Min(dA,dB)>40){ who="(none)"; d=Math.Min(dA,dB); un++; }
        else if(dA<=dB){ who="A"; d=dA; aN++; } else { who="B"; d=dB; bN++; }
        Log($"   {tn} h={e.Handle} layer='{e.Layer}' -> {who} (d={d:0.0}')");
    }
    Log($"ASSIGNED: A={aN} B={bN} none={un}");
    tr.Commit();
}

Result

Status
error
Drawing file
C:\Users\sanja\OneDrive\_SurveyDisco\260619 - 3625 Stonewall Tell Rd, Atlanta, GA 30349, USA\260619 - 3625 Stonewall Tell Rd.dwg
Message
Compile error: (46,22): error CS0104: 'DBObject' is an ambiguous reference between 'Autodesk.AutoCAD.DatabaseServices.DBObject' and 'Autodesk.Civil.DatabaseServices.DBObject'
Entities
Duration
438 ms
Civil 3D
25.0.0.0

Notes

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

No notes yet.