C3D-PARCELLBL · Label 19 PARCEL lines: bearing + distance done
MText bearing+distance at each PARCEL line midpoint (rotated, upright) on C-PROP-LINE-TEXT. Idempotent. C3D-22.
C# payload
// Label the 19 Line entities on layer "PARCEL" with bearing + distance.
// MText at each line midpoint, rotated to the line, on layer C-PROP-LINE-TEXT.
// Idempotent: skip a line if an MText already sits within 1' of its midpoint on the label layer.
using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
var db = Db;
const string SRC_LAYER = "PARCEL";
const string LBL_LAYER = "C-PROP-LINE-TEXT";
const double TXT_HT = 5.0; // model units (survey feet); tune later, it's a draft
EnsureLayer(LBL_LAYER, 2);
string Bearing(Point3d a, Point3d b)
{
double dx=b.X-a.X, dy=b.Y-a.Y;
string ns = dy>=0 ? "N" : "S";
string ew = dx>=0 ? "E" : "W";
double q = Math.Atan2(Math.Abs(dx), Math.Abs(dy)) * 180.0/Math.PI; // angle off the N-S axis
int deg=(int)q; double mf=(q-deg)*60; int min=(int)mf; int sec=(int)Math.Round((mf-min)*60);
if(sec==60){sec=0;min++;} if(min==60){min=0;deg++;}
return $"{ns}{deg:00}°{min:00}'{sec:00}\"{ew}";
}
int labeled=0, skipped=0;
using (var tr = db.TransactionManager.StartTransaction())
{
var ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite);
// gather existing label midpoints (idempotency)
var existing = new List<Point3d>();
foreach (ObjectId id in ms)
{
var e = tr.GetObject(id, OpenMode.ForRead);
if (e is MText m && string.Equals(m.Layer, LBL_LAYER, StringComparison.OrdinalIgnoreCase))
existing.Add(m.Location);
}
// collect the PARCEL lines first (don't add while iterating the same btr open-for-read set)
var lines = new List<Line>();
foreach (ObjectId id in ms)
{
var e = tr.GetObject(id, OpenMode.ForRead) as Autodesk.AutoCAD.DatabaseServices.Entity;
if (e is Line ln && string.Equals(e.Layer, SRC_LAYER, StringComparison.OrdinalIgnoreCase))
lines.Add(ln);
}
Log($"PARCEL lines found: {lines.Count}");
foreach (var ln in lines)
{
var mid = new Point3d((ln.StartPoint.X+ln.EndPoint.X)/2, (ln.StartPoint.Y+ln.EndPoint.Y)/2, 0);
bool dupe=false;
foreach (var p in existing) if (p.DistanceTo(mid) < 1.0) { dupe=true; break; }
if (dupe) { skipped++; continue; }
double ang = Math.Atan2(ln.EndPoint.Y-ln.StartPoint.Y, ln.EndPoint.X-ln.StartPoint.X);
if (ang > Math.PI/2 || ang < -Math.PI/2) ang += Math.PI; // keep text upright
string txt = $"{Bearing(ln.StartPoint, ln.EndPoint)} {ln.Length:0.00}'";
var mt = new MText();
mt.SetDatabaseDefaults();
mt.Layer = LBL_LAYER;
mt.Location = mid;
mt.TextHeight = TXT_HT;
mt.Rotation = ang;
mt.Attachment = AttachmentPoint.MiddleCenter;
mt.Contents = txt;
ms.AppendEntity(mt);
tr.AddNewlyCreatedDBObject(mt, true);
existing.Add(mid);
labeled++;
}
tr.Commit();
}
Log($"DONE. labeled={labeled}, skipped(existing)={skipped}. Layer '{LBL_LAYER}'. Re-run is idempotent.");
Result
Log
PARCEL lines found: 19 DONE. labeled=19, skipped(existing)=0. Layer 'C-PROP-LINE-TEXT'. Re-run is idempotent.
Notes
What worked, what didn't, job-specific gotchas — flagged notes feed the recipes.
No notes yet.