← Inbox

C3D-0306 · 260610 Tara Blvd: centre the category tags in their boxes at 0.33 done

Rebuilds the fixture boxes from the loose FIXTURE-layer lines (union-find over shared endpoints), assigns each category tag to the box containing it (or the nearest centre within 6 ft), then sets every tag to height 0.33, MiddleCenter attachment, box centre location, rotation along the boxs long axis, and a wrap width matching the box. Tags with no box are reported and left alone.

Script file
C3D-0306.cs
Target
260610 - 6736 Tara Blvd R2.dwg · model space
Author
claude
Approved
yes · auto-auth
Timeout
60s

C# payload

// Centre every category tag inside the fixture box it sits in, at height 0.33.
//
// The fixture boxes are drawn as loose FIXTURE-layer lines, not closed polylines, so the boxes
// are rebuilt here by walking those lines into connected components and taking each component's
// bounding box. That is the same reconstruction used to measure the fixture areas.
//
// A tag is assigned to the box whose bbox contains its current insertion point; if none contains
// it, the nearest box centre within 6 ft wins. Tags with no box are left alone and reported.
// Attachment is set to MiddleCenter and Location to the box centre, so the tag is centred both
// ways regardless of rotation.
const double H = 0.33;
string[] CATS = { "Fresh Fruits & Vegetables", "Fresh Uncooked Meats", "Dairy Products",
                  "Canned Foods", "Frozen Foods", "Dry groceries and baked goods",
                  "Non-Alcoholic beverages", "dairy", "meats", "CANNED FOODS" };

var ms = (BlockTableRecord)Tx.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(Db), OpenMode.ForWrite);

// ---- rebuild the fixture boxes from FIXTURE lines
var pts = new List<Point2d>();
var segs = new List<Tuple<Point2d,Point2d>>();
foreach (ObjectId id in ms) {
    var ln = Tx.GetObject(id, OpenMode.ForRead) as Line;
    if (ln == null) continue;
    if (!ln.Layer.Equals("FIXTURE", StringComparison.OrdinalIgnoreCase)) continue;
    var a = new Point2d(Math.Round(ln.StartPoint.X,3), Math.Round(ln.StartPoint.Y,3));
    var b = new Point2d(Math.Round(ln.EndPoint.X,3),   Math.Round(ln.EndPoint.Y,3));
    segs.Add(Tuple.Create(a,b));
}
Log("FIXTURE lines: " + segs.Count);

// union-find over endpoints
var idx = new Dictionary<Point2d,int>();
Func<Point2d,int> key = p => { if (!idx.ContainsKey(p)) { idx[p] = idx.Count; } return idx[p]; };
foreach (var s in segs) { key(s.Item1); key(s.Item2); }
var parent = new int[idx.Count];
for (int i = 0; i < parent.Length; i++) parent[i] = i;
Func<int,int> find = null;
find = x => { while (parent[x] != x) { parent[x] = parent[parent[x]]; x = parent[x]; } return x; };
foreach (var s in segs) { int a = find(key(s.Item1)), b = find(key(s.Item2)); if (a != b) parent[a] = b; }

var groups = new Dictionary<int, List<Point2d>>();
foreach (var kv in idx) {
    int r = find(kv.Value);
    if (!groups.ContainsKey(r)) groups[r] = new List<Point2d>();
    groups[r].Add(kv.Key);
}
var boxes = new List<Tuple<double,double,double,double>>();   // x0,y0,x1,y1
foreach (var g in groups.Values) {
    if (g.Count < 4) continue;
    double x0 = 1e30, y0 = 1e30, x1 = -1e30, y1 = -1e30;
    foreach (var p in g) { if (p.X<x0)x0=p.X; if (p.Y<y0)y0=p.Y; if (p.X>x1)x1=p.X; if (p.Y>y1)y1=p.Y; }
    if ((x1-x0) < 0.5 || (y1-y0) < 0.5) continue;
    boxes.Add(Tuple.Create(x0,y0,x1,y1));
}
Log("fixture boxes rebuilt: " + boxes.Count);
foreach (var b in boxes)
    Log(string.Format("   box ({0:F2},{1:F2})-({2:F2},{3:F2})  {4:F2} x {5:F2} = {6:F2} sf",
        b.Item1, b.Item2, b.Item3, b.Item4, b.Item3-b.Item1, b.Item4-b.Item2,
        (b.Item3-b.Item1)*(b.Item4-b.Item2)));

// ---- collect the tags
var tagIds = new List<ObjectId>();
foreach (ObjectId id in ms) {
    var mt = Tx.GetObject(id, OpenMode.ForRead) as MText;
    if (mt == null) continue;
    string c = mt.Contents.Replace("\\P"," ").Replace("\n"," ").Trim();
    bool hit = false;
    foreach (var k in CATS) if (c.IndexOf(k, StringComparison.OrdinalIgnoreCase) >= 0) { hit = true; break; }
    if (!hit) continue;
    tagIds.Add(id);
}
Log("");
Log("category tags found: " + tagIds.Count);

int moved = 0, orphan = 0;
foreach (var id in tagIds) {
    var mt = (MText)Tx.GetObject(id, OpenMode.ForWrite);
    double px = mt.Location.X, py = mt.Location.Y;

    // the box containing this tag, else the nearest centre within 6 ft
    Tuple<double,double,double,double> box = null;
    foreach (var b in boxes)
        if (px >= b.Item1-0.01 && px <= b.Item3+0.01 && py >= b.Item2-0.01 && py <= b.Item4+0.01) { box = b; break; }
    if (box == null) {
        double best = 6.0;
        foreach (var b in boxes) {
            double cx = (b.Item1+b.Item3)/2, cy = (b.Item2+b.Item4)/2;
            double d = Math.Sqrt((cx-px)*(cx-px)+(cy-py)*(cy-py));
            if (d < best) { best = d; box = b; }
        }
    }
    if (box == null) {
        orphan++;
        Log(string.Format("  NO BOX [{0}] at ({1:F2},{2:F2}) \"{3}\" - left alone",
            mt.Handle, px, py, mt.Contents.Replace("\n"," ")));
        continue;
    }

    double bcx = (box.Item1+box.Item3)/2, bcy = (box.Item2+box.Item4)/2;
    double bw = box.Item3-box.Item1, bh = box.Item4-box.Item2;

    mt.TextHeight = H;
    mt.Attachment = AttachmentPoint.MiddleCenter;
    // run the text along the long axis of the box
    mt.Rotation = (bh > bw) ? Math.PI/2 : 0.0;
    // wrap width: the box's long dimension, minus a small margin
    mt.Width = Math.Max(bw, bh) - 0.2;
    mt.Location = new Point3d(bcx, bcy, 0);
    moved++;

    var back = (MText)Tx.GetObject(id, OpenMode.ForRead);
    Log(string.Format("  [{0}] -> ({1:F3},{2:F3}) h={3:F2} rot={4:F0} in box {5:F2}x{6:F2} \"{7}\"",
        back.Handle, back.Location.X, back.Location.Y, back.TextHeight,
        back.Rotation*180/Math.PI, bw, bh, back.Contents.Replace("\n"," ")));
}

Log("");
Log(string.Format("centred {0} tags at h={1:F2}, {2} had no box (verified above)", moved, H, orphan));
Ed.Regen();

Result

Status
success
Drawing file
C:\Users\sanja\OneDrive\_SurveyDisco\260610 - 6736 Tara Blvd, Jonesboro, GA 30236, USA\260610 - 6736 Tara Blvd R2.dwg
Message
Executed C3D-0306 (0 entities touched).
Entities
Duration
609 ms
Civil 3D
25.0.0.0

Log

FIXTURE lines: 75
fixture boxes rebuilt: 12
   box (2261062.93,1391849.19)-(2261087.43,1391857.19)  24.50 x 8.00 = 196.00 sf
   box (2261096.31,1391819.44)-(2261103.83,1391857.19)  7.52 x 37.74 = 283.68 sf
   box (2261062.93,1391815.19)-(2261072.43,1391831.19)  9.50 x 16.00 = 152.00 sf
   box (2261078.93,1391823.69)-(2261081.93,1391842.19)  3.00 x 18.50 = 55.50 sf
   box (2261078.43,1391842.19)-(2261082.43,1391843.19)  4.00 x 1.00 = 4.00 sf
   box (2261070.93,1391823.69)-(2261073.93,1391842.19)  3.00 x 18.50 = 55.50 sf
   box (2261070.43,1391842.19)-(2261074.43,1391843.19)  4.00 x 1.00 = 4.00 sf
   box (2261086.93,1391823.69)-(2261089.93,1391842.19)  3.00 x 18.50 = 55.50 sf
   box (2261086.43,1391842.19)-(2261090.43,1391843.19)  4.00 x 1.00 = 4.00 sf
   box (2261067.21,1391847.19)-(2261070.21,1391849.19)  3.00 x 2.00 = 6.00 sf
   box (2261068.93,1391846.19)-(2261075.43,1391849.19)  6.50 x 3.00 = 19.50 sf
   box (2261083.43,1391846.19)-(2261087.43,1391851.19)  4.00 x 5.00 = 20.00 sf

category tags found: 15
  [21BE7] -> (2261080.427,1391832.943) h=0.33 rot=90 in box 3.00x18.50 "Dry groceries and baked goods"
  [21BE8] -> (2261080.427,1391832.943) h=0.33 rot=90 in box 3.00x18.50 "Dry groceries and baked goods"
  [21BEC] -> (2261088.427,1391832.943) h=0.33 rot=90 in box 3.00x18.50 "Non-Alcoholic beverages"
  [21BED] -> (2261088.427,1391832.943) h=0.33 rot=90 in box 3.00x18.50 "Dry groceries and baked goods"
  [21BEF] -> (2261067.677,1391823.193) h=0.33 rot=90 in box 9.50x16.00 "Dry groceries and\Pbaked goods"
  [21BF2] -> (2261067.677,1391823.193) h=0.33 rot=90 in box 9.50x16.00 "Frozen Foods"
  [21BF4] -> (2261072.177,1391847.693) h=0.33 rot=0 in box 6.50x3.00 "Frozen Foods"
  [21BF6] -> (2261100.069,1391838.315) h=0.33 rot=90 in box 7.52x37.74 "Non-Alcoholic beverages"
  [21C06] -> (2261072.427,1391832.943) h=0.33 rot=90 in box 3.00x18.50 "CANNED FOODS"
  [21C99] -> (2261088.427,1391832.943) h=0.33 rot=90 in box 3.00x18.50 "Dry groceries and\Pbaked goods"
  NO BOX [21CB9] at (2261063.73,1391838.39) "Frozen Foods" - left alone
  [21CC1] -> (2261067.677,1391823.193) h=0.33 rot=90 in box 9.50x16.00 "dairy"
  [21CD6] -> (2261067.677,1391823.193) h=0.33 rot=90 in box 9.50x16.00 "dairy"
  [21CDE] -> (2261067.677,1391823.193) h=0.33 rot=90 in box 9.50x16.00 "meats"
  [21D40] -> (2261075.177,1391853.193) h=0.33 rot=0 in box 24.50x8.00 "Non-Alcoholic beverages"

centred 14 tags at h=0.33, 1 had no box (verified above)

Notes

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

No notes yet.