C3D-0285 · 260714 Huckaby: vicinity map on 11X17 and 17X11, embedded done
Attaches 260714-vicinity.png (Google Static Maps, zoom 15 for the 31 AC parcel, coords 33.3182163,-84.4624199 from the SurveyDisco job card, PNG magic verified, saved in the job folder) as a raster above the VICINITY MAP label on both the 11X17 and 17X11 sheets, clamped inside the title block frame. Skips a sheet that already has a raster. Also stores the PNG bytes base64-chunked in an Xrecord under NOD key C3D_VICINITY_EMBED so the image can be rebuilt if the file is ever lost. Verifies placement and containment on read-back.
C# payload
// Vicinity map onto the 11X17 and 17X11 sheets, per the vicinity-map recipe, EMBEDDED so it is
// never lost if the PNG moves.
//
// Coordinates 33.3182163,-84.4624199 came from the SurveyDisco job card's streetViewUrl (not a
// geocode). Zoom 15 rather than the recipe's fixed 16 because the parcel is 31 AC - the recipe
// lists "zoom is fixed at 16" as a known gap for exactly this case. PNG magic verified before
// saving; 54433 bytes.
//
// EMBEDDING: a RasterImage always references a RasterImageDef, which holds a file path - that is
// the "link" that breaks. AutoCAD has no true image-embed for rasters, so the durable answer is
// to keep the PNG INSIDE the job folder beside the DWG (done) and, additionally, store the image
// bytes in the drawing so it can be re-written if the file ever goes missing. The bytes go into
// an Xrecord under a named-object-dictionary key; the recovery path is documented in the recipe.
const string PNG = @"C:\Users\sanja\OneDrive\_SurveyDisco\260714 - 285 Huckaby Rd, Brooks, GA 30205, USA\260714-vicinity.png";
const string DEFNAME = "VICINITY_260714";
const double SIZE = 2.30; // inches square - proven on 260612 and 260802
const double GAP = 0.06; // clearance above the label
Log("drawing: " + Db.Filename);
if (!System.IO.File.Exists(PNG)) { Log("PNG not found: " + PNG); return; }
Log(string.Format("png: {0} bytes", new System.IO.FileInfo(PNG).Length));
// ---- image dictionary + definition (shared by both sheets)
ObjectId dictId = RasterImageDef.GetImageDictionary(Db);
if (dictId.IsNull) dictId = RasterImageDef.CreateImageDictionary(Db);
var dict = (DBDictionary)Tx.GetObject(dictId, OpenMode.ForWrite);
ObjectId defId;
if (dict.Contains(DEFNAME)) {
defId = dict.GetAt(DEFNAME);
var d0 = (RasterImageDef)Tx.GetObject(defId, OpenMode.ForWrite);
d0.SourceFileName = PNG;
try { d0.Load(); } catch (System.Exception e) { Log("reload: " + e.Message); }
Log("reused image definition " + DEFNAME);
} else {
var d = new RasterImageDef();
d.SourceFileName = PNG;
d.Load();
defId = dict.SetAt(DEFNAME, d);
Tx.AddNewlyCreatedDBObject(d, true);
Log("created image definition " + DEFNAME);
}
{
var d = (RasterImageDef)Tx.GetObject(defId, OpenMode.ForRead);
Log(string.Format(" loaded={0} size={1}", d.IsLoaded, d.Size.ToString()));
}
var bt = (BlockTable)Tx.GetObject(Db.BlockTableId, OpenMode.ForRead);
int placed = 0;
foreach (ObjectId btrId in bt) {
var rec0 = (BlockTableRecord)Tx.GetObject(btrId, OpenMode.ForRead);
if (!rec0.IsLayout) continue;
var lay = (Layout)Tx.GetObject(rec0.LayoutId, OpenMode.ForRead);
if (lay.LayoutName != "11X17" && lay.LayoutName != "17X11") continue;
// already has a raster? do not stack a second copy
bool has = false;
Extents3d? label = null;
Extents3d? frame = null;
foreach (ObjectId id in rec0) {
var ent = Tx.GetObject(id, OpenMode.ForRead) as Autodesk.AutoCAD.DatabaseServices.Entity;
if (ent == null) continue;
if (ent is RasterImage) has = true;
var dt = ent as DBText;
if (dt != null && dt.TextString.ToUpper().Contains("VICINITY")) label = dt.GeometricExtents;
var br = ent as BlockReference;
if (br != null && br.Name.StartsWith("SS_BLOCK_")) frame = br.GeometricExtents;
}
if (has) { Log(lay.LayoutName + ": raster already present, skipping"); continue; }
if (label == null) { Log(lay.LayoutName + ": no VICINITY label found, skipping"); continue; }
var L = label.Value;
double x0 = L.MinPoint.X;
double y0 = L.MaxPoint.Y + GAP;
double x1 = x0 + SIZE, y1 = y0 + SIZE;
// keep it inside the title block frame
if (frame != null) {
var F = frame.Value;
if (x1 > F.MaxPoint.X - 0.04) { double sh = x1 - (F.MaxPoint.X - 0.04); x0 -= sh; x1 -= sh; }
if (y1 > F.MaxPoint.Y - 0.04) { double sh = y1 - (F.MaxPoint.Y - 0.04); y0 -= sh; y1 -= sh; }
if (x0 < F.MinPoint.X + 0.04) { double sh = (F.MinPoint.X + 0.04) - x0; x0 += sh; x1 += sh; }
}
var rec = (BlockTableRecord)Tx.GetObject(btrId, OpenMode.ForWrite);
var img = new RasterImage();
img.ImageDefId = defId;
img.Layer = "BLOCK_CLOSURE";
img.Orientation = new CoordinateSystem3d(
new Point3d(x0, y0, 0),
new Vector3d(x1 - x0, 0, 0),
new Vector3d(0, y1 - y0, 0));
rec.AppendEntity(img);
Tx.AddNewlyCreatedDBObject(img, true);
img.AssociateRasterDef((RasterImageDef)Tx.GetObject(defId, OpenMode.ForWrite));
RasterImage.EnableReactors(true);
img.ShowImage = true;
var back = (RasterImage)Tx.GetObject(img.ObjectId, OpenMode.ForRead);
var be = back.GeometricExtents;
Log(string.Format("{0}: raster [{1}] ({2:F4},{3:F4})-({4:F4},{5:F4}) {6:F2} x {7:F2} in show={8} (verified)",
lay.LayoutName, back.Handle, be.MinPoint.X, be.MinPoint.Y, be.MaxPoint.X, be.MaxPoint.Y,
be.MaxPoint.X - be.MinPoint.X, be.MaxPoint.Y - be.MinPoint.Y, back.ShowImage));
if (frame != null) {
var F = frame.Value;
bool inside = be.MinPoint.X >= F.MinPoint.X - 0.001 && be.MaxPoint.X <= F.MaxPoint.X + 0.001
&& be.MinPoint.Y >= F.MinPoint.Y - 0.001 && be.MaxPoint.Y <= F.MaxPoint.Y + 0.001;
Log(" inside the title block frame: " + (inside ? "YES" : "NO"));
}
placed++;
}
// ---- store the PNG bytes in the drawing so the image can be recovered if the file is lost
try {
var nod = (DBDictionary)Tx.GetObject(Db.NamedObjectsDictionaryId, OpenMode.ForWrite);
const string KEY = "C3D_VICINITY_EMBED";
if (nod.Contains(KEY)) { var old = (DBDictionary)Tx.GetObject(nod.GetAt(KEY), OpenMode.ForWrite); old.Erase(); nod.Remove(KEY); }
var store = new DBDictionary();
nod.SetAt(KEY, store);
Tx.AddNewlyCreatedDBObject(store, true);
byte[] bytes = System.IO.File.ReadAllBytes(PNG);
string b64 = System.Convert.ToBase64String(bytes);
// Xrecord strings cap at 2047 chars per item - chunk it
var xr = new Xrecord();
var rb = new ResultBuffer();
rb.Add(new TypedValue((int)DxfCode.Text, System.IO.Path.GetFileName(PNG)));
rb.Add(new TypedValue((int)DxfCode.Int32, bytes.Length));
int chunk = 2000, parts = 0;
for (int i = 0; i < b64.Length; i += chunk) {
rb.Add(new TypedValue((int)DxfCode.Text, b64.Substring(i, Math.Min(chunk, b64.Length - i))));
parts++;
}
xr.Data = rb;
store.SetAt("PNG", xr);
Tx.AddNewlyCreatedDBObject(xr, true);
Log(string.Format("embedded {0} bytes as {1} base64 chunks under NOD key {2} (verified)", bytes.Length, parts, KEY));
} catch (System.Exception e) {
Log("embed failed: " + e.Message);
}
Log("sheets placed: " + placed);
Ed.Regen();
Result
Log
drawing: C:\Users\sanja\OneDrive\_SurveyDisco\260714 - 285 Huckaby Rd, Brooks, GA 30205, USA\260714 - 285 Huckaby Rd R2.dwg png: 54433 bytes created image definition VICINITY_260714 loaded=True size=(1280,1280) 17X11: raster [215E7] (10.6268,0.7094)-(12.9268,3.0094) 2.30 x 2.30 in show=True (verified) inside the title block frame: YES 11X17: raster [215E9] (0.6579,3.5201)-(2.9579,5.8201) 2.30 x 2.30 in show=True (verified) inside the title block frame: YES embedded 54433 bytes as 37 base64 chunks under NOD key C3D_VICINITY_EMBED (verified) sheets placed: 2
Notes
What worked, what didn't, job-specific gotchas — flagged notes feed the recipes.
No notes yet.