← Inbox

C3D-0303 · 260610 Tara Blvd: TXT2MTXT + Arial + category tags (retry) done

Retry of C3D-0302 which threw on a duplicate dictionary key - the category map is case-insensitive so candy and Candy collided. Same work: 25 DBText to MText preserving placement, everything onto GF_050 (real arial.ttf), category tags from the 7 sheet categories under each merchandise label, verified.

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

C# payload

// 260610 Tara Blvd store plan:
//   1. convert every DBText in the store to MText (TXT2MTXT equivalent, done in the API so
//      position/height/rotation/layer are preserved exactly)
//   2. put ALL of it - converted and pre-existing MText - on real Arial
//   3. add a category tag under each fixture label, from the 7 sheet categories
//
// FONT: the style named "ARIAL" maps to swissb.ttf ("Swis721 BT"), NOT Arial. The only style on
// real arial.ttf is GF_050. Using GF_050 so the text is genuinely Arial.
//
// The 7 categories, verbatim from the sheet MText [21991]:
//   Fresh Fruits & Vegetables / Fresh Uncooked Meats, seafood, poultry / Dairy Products /
//   Canned Foods / Frozen Foods / Dry groceries and baked goods / Non-Alcoholic beverages
// Anything that is not merchandise (aisle, exit, gameroom, ...) gets no tag.
const string FONT = "GF_050";
double X0 = 2261060, X1 = 2261110, Y0 = 1391805, Y1 = 1391860;

var tst = (TextStyleTable)Tx.GetObject(Db.TextStyleTableId, OpenMode.ForRead);
if (!tst.Has(FONT)) { Log("text style " + FONT + " missing"); return; }
ObjectId styleId = tst[FONT];
{
    var ts = (TextStyleTableRecord)Tx.GetObject(styleId, OpenMode.ForRead);
    string tt = ""; try { tt = ts.Font.TypeFace; } catch { }
    Log("font style: " + ts.Name + "  file=" + ts.FileName + "  TTF=\"" + tt + "\"");
}

// label -> category. Only merchandise gets a tag.
var cat = new Dictionary<string,string>(StringComparer.OrdinalIgnoreCase) {
    { "fruit",               "Fresh Fruits & Vegetables" },
    { "frozen food",         "Frozen Foods" },
    { "ice cream",           "Frozen Foods" },
    { "cabnits",             "Frozen Foods" },
    { "drinks",              "Non-Alcoholic beverages" },
    { "NON-ALCOHOIC DRINKS", "Non-Alcoholic beverages" },
    { "chips",               "Dry groceries and baked goods" },
    { "candy",               "Dry groceries and baked goods" },
    { "snacks",              "Dry groceries and baked goods" },
    { "Food",                "Dry groceries and baked goods" },
};

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

// ---- collect first; converting while iterating the same BTR is not safe
var work = new List<ObjectId>();
foreach (ObjectId id in ms) {
    var ent = Tx.GetObject(id, OpenMode.ForRead) as Autodesk.AutoCAD.DatabaseServices.Entity;
    if (ent == null) continue;
    if (!(ent is DBText) && !(ent is MText)) continue;
    double x, y;
    var d0 = ent as DBText; var m0 = ent as MText;
    if (d0 != null) { x = d0.Position.X; y = d0.Position.Y; } else { x = m0.Location.X; y = m0.Location.Y; }
    if (x < X0 || x > X1 || y < Y0 || y > Y1) continue;
    work.Add(id);
}
Log("store text entities: " + work.Count);

int converted = 0, restyled = 0, tagged = 0;
var tags = new List<Tuple<Point3d,double,double,string,string>>();   // pos, height, rot, layer, category

foreach (ObjectId id in work) {
    var ent = Tx.GetObject(id, OpenMode.ForWrite) as Autodesk.AutoCAD.DatabaseServices.Entity;
    if (ent == null) continue;

    string content; Point3d pos; double hgt, rot; string layer = ent.Layer;

    var dt = ent as DBText;
    if (dt != null) {
        content = dt.TextString; pos = dt.Position; hgt = dt.Height; rot = dt.Rotation;
        // build the MText replacement at the same place
        var nm = new MText();
        nm.SetDatabaseDefaults();
        nm.TextStyleId = styleId;
        nm.TextHeight = hgt;
        nm.Location = pos;
        nm.Rotation = rot;
        nm.Attachment = AttachmentPoint.BottomLeft;
        nm.Layer = layer;
        nm.Contents = content;
        ms.AppendEntity(nm);
        Tx.AddNewlyCreatedDBObject(nm, true);
        dt.Erase();
        converted++;
        Log(string.Format("  DBText [{0}] -> MText [{1}] \"{2}\"", dt.Handle, nm.Handle, content));
    } else {
        var mt = (MText)ent;
        content = mt.Contents; pos = mt.Location; hgt = mt.TextHeight; rot = mt.Rotation;
        mt.TextStyleId = styleId;
        restyled++;
        Log(string.Format("  MText [{0}] restyled \"{1}\"", mt.Handle, content.Replace("\n"," / ")));
    }

    string c;
    if (cat.TryGetValue(content.Trim(), out c))
        tags.Add(Tuple.Create(pos, hgt, rot, layer, c));
}

// ---- category tags, placed just under each merchandise label
foreach (var t in tags) {
    var pos = t.Item1; double hgt = t.Item2, rot = t.Item3;
    double th = hgt * 0.55;
    // offset perpendicular to the text direction so rotated labels stay readable
    double dx = Math.Sin(rot) * (th * 1.6), dy = -Math.Cos(rot) * (th * 1.6);
    var tag = new MText();
    tag.SetDatabaseDefaults();
    tag.TextStyleId = styleId;
    tag.TextHeight = th;
    tag.Location = new Point3d(pos.X + dx, pos.Y + dy, 0);
    tag.Rotation = rot;
    tag.Attachment = AttachmentPoint.BottomLeft;
    tag.Layer = t.Item4;
    tag.Contents = t.Item5;
    ms.AppendEntity(tag);
    Tx.AddNewlyCreatedDBObject(tag, true);
    tagged++;
    Log(string.Format("  TAG [{0}] ({1:F2},{2:F2}) \"{3}\"", tag.Handle, tag.Location.X, tag.Location.Y, t.Item5));
}

// ---- verify: nothing left as DBText, everything on the Arial style
int leftDb = 0, wrongStyle = 0, total = 0;
foreach (ObjectId id in ms) {
    var ent = Tx.GetObject(id, OpenMode.ForRead) as Autodesk.AutoCAD.DatabaseServices.Entity;
    if (ent == null || ent.IsErased) continue;
    var d = ent as DBText; var m = ent as MText;
    if (d == null && m == null) continue;
    double x, y;
    if (d != null) { x = d.Position.X; y = d.Position.Y; } else { x = m.Location.X; y = m.Location.Y; }
    if (x < X0 || x > X1 || y < Y0 || y > Y1) continue;
    total++;
    if (d != null) leftDb++;
    ObjectId sid = d != null ? d.TextStyleId : m.TextStyleId;
    if (sid != styleId) wrongStyle++;
}
Log("");
Log(string.Format("converted {0} DBText -> MText, restyled {1} existing MText, added {2} category tags",
    converted, restyled, tagged));
Log(string.Format("VERIFY: {0} text entities in the store, DBText remaining = {1}, not on {2} = {3}",
    total, leftDb, FONT, wrongStyle));
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-0303 (0 entities touched).
Entities
Duration
1167 ms
Civil 3D
25.0.0.0

Log

font style: GF_050  file=arial.ttf  TTF="Arial"
store text entities: 28
  DBText [209A3] -> MText [21BCE] "Aisle"
  DBText [209A5] -> MText [21BCF] "Aisle"
  DBText [209C6] -> MText [21BD0] "locker"
  DBText [20F68] -> MText [21BD1] "Food"
  DBText [20F78] -> MText [21BD2] "Candy"
  DBText [20F90] -> MText [21BD3] "chips"
  DBText [20F98] -> MText [21BD4] "chips"
  DBText [20FA0] -> MText [21BD5] "candy"
  DBText [20FAE] -> MText [21BD6] "drinks"
  DBText [20FB6] -> MText [21BD7] "wine"
  DBText [20FBE] -> MText [21BD8] "snacks"
  DBText [20FC6] -> MText [21BD9] "Food"
  DBText [20FD4] -> MText [21BDA] "HSE products"
  DBText [20FE2] -> MText [21BDB] "chips"
  DBText [20FEA] -> MText [21BDC] "fruit"
  DBText [20FF2] -> MText [21BDD] "chips"
  DBText [20FFA] -> MText [21BDE] "frozen food"
  DBText [21017] -> MText [21BDF] "cabnits"
  DBText [2101F] -> MText [21BE0] "checkout counters"
  DBText [21027] -> MText [21BE1] "elec room"
  DBText [2102F] -> MText [21BE2] "gameroom"
  DBText [21037] -> MText [21BE3] "bathroom"
  DBText [2103F] -> MText [21BE4] "exit"
  DBText [21047] -> MText [21BE5] "entrance"
  DBText [21054] -> MText [21BE6] "t-shirts"
  MText [21B9C] restyled "ice cream"
  MText [21BBA] restyled "ice cream"
  MText [21BC2] restyled "NON-ALCOHOIC DRINKS"
  TAG [21BE7] (2261080.51,1391825.96) "Dry groceries and baked goods"
  TAG [21BE8] (2261081.84,1391839.16) "Dry groceries and baked goods"
  TAG [21BE9] (2261078.77,1391841.91) "Dry groceries and baked goods"
  TAG [21BEA] (2261070.78,1391842.00) "Dry groceries and baked goods"
  TAG [21BEB] (2261086.72,1391842.04) "Dry groceries and baked goods"
  TAG [21BEC] (2261089.94,1391839.19) "Non-Alcoholic beverages"
  TAG [21BED] (2261088.39,1391826.06) "Dry groceries and baked goods"
  TAG [21BEE] (2261073.97,1391825.91) "Dry groceries and baked goods"
  TAG [21BEF] (2261071.36,1391823.88) "Dry groceries and baked goods"
  TAG [21BF0] (2261079.52,1391823.87) "Fresh Fruits & Vegetables"
  TAG [21BF1] (2261087.38,1391823.79) "Dry groceries and baked goods"
  TAG [21BF2] (2261065.31,1391821.63) "Frozen Foods"
  TAG [21BF3] (2261063.60,1391847.55) "Frozen Foods"
  TAG [21BF4] (2261073.16,1391848.30) "Frozen Foods"
  TAG [21BF5] (2261098.82,1391828.09) "Frozen Foods"
  TAG [21BF6] (2261098.92,1391846.81) "Non-Alcoholic beverages"

converted 25 DBText -> MText, restyled 3 existing MText, added 16 category tags
VERIFY: 44 text entities in the store, DBText remaining = 0, not on GF_050 = 0

Notes

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

No notes yet.