C3D-0134 · IPF to centerline dimensions (test the recipe) [IPF-DIMS] done
Draws an AlignedDimension from every IPF point to the closest point on the nearest centerline - the perpendicular foot on a segment, clamped, taking the global minimum across all CL polylines. Skips pins that already carry a dimension so the two hand-drawn examples are untouched and a re-run adds nothing.
C# payload
// IPF -> centerline AlignedDimensions, per recipe ipf-to-centerline-dims.
//
// For every IPF point: compute the perpendicular foot on EVERY segment of EVERY centerline
// polyline, clamped to the segment, and take the global minimum. Draw an AlignedDimension from
// the pin to that foot. Matches the user's own two dims (pt103 -> 26.291 exactly).
//
// AlignedDimension - NOT MText/Leader - so the size is managed from paper space.
// Idempotent: a pin that already has a dimension starting or ending within 0.5 ft of it is skipped,
// so the user's two hand-drawn dims are left alone and a re-run adds nothing.
var ms = (BlockTableRecord)Tx.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(Db), OpenMode.ForWrite);
Log("drawing: " + Db.Filename);
const string DIM_LAYER = "0";
const string DIM_STYLE = "Standard";
// centerlines
var cls = new List<Point2d[]>();
foreach (ObjectId id in ms) {
var pl = Tx.GetObject(id, OpenMode.ForRead) as Polyline;
if (pl == null) continue;
string u = pl.Layer.ToUpper();
if (u.IndexOf("CNTR") < 0 && u.IndexOf("-CL") < 0) continue;
var v = new Point2d[pl.NumberOfVertices];
for (int i = 0; i < pl.NumberOfVertices; i++) v[i] = pl.GetPoint2dAt(i);
cls.Add(v);
Log("centerline [" + pl.Handle + "] " + pl.Layer + " verts=" + v.Length);
}
if (cls.Count == 0) { Log("ABORT: no centerline polylines found"); return; }
// existing dimension endpoints, so hand-drawn ones are not duplicated
var taken = new List<Point3d>();
foreach (ObjectId id in ms) {
var ad = Tx.GetObject(id, OpenMode.ForRead) as AlignedDimension;
if (ad == null) continue;
taken.Add(ad.XLine1Point); taken.Add(ad.XLine2Point);
}
Log("existing aligned dimensions endpoints: " + taken.Count);
int made = 0, skipped = 0;
foreach (ObjectId id in ms) {
var cp = Tx.GetObject(id, OpenMode.ForRead) as CogoPoint;
if (cp == null) continue;
string d = "";
try { d = (cp.RawDescription ?? "").ToUpper(); } catch { }
if (d.IndexOf("IPF") < 0) continue;
var P = new Point2d(cp.Easting, cp.Northing);
bool already = false;
foreach (var t in taken)
if (Math.Sqrt(Math.Pow(t.X - P.X, 2) + Math.Pow(t.Y - P.Y, 2)) < 0.5) { already = true; break; }
if (already) { skipped++; Log(" pt " + cp.PointNumber + " already dimensioned - skipped"); continue; }
double best = 1e18; Point2d foot = P;
foreach (var poly in cls) {
for (int i = 0; i < poly.Length - 1; i++) {
var A = poly[i]; var B = poly[i+1];
double vx = B.X - A.X, vy = B.Y - A.Y, L2 = vx*vx + vy*vy;
double t = L2 > 0 ? ((P.X - A.X)*vx + (P.Y - A.Y)*vy) / L2 : 0.0;
if (t < 0) t = 0; if (t > 1) t = 1;
var Q = new Point2d(A.X + t*vx, A.Y + t*vy);
double dd = Math.Sqrt(Math.Pow(P.X - Q.X, 2) + Math.Pow(P.Y - Q.Y, 2));
if (dd < best) { best = dd; foot = Q; }
}
}
// dimension line offset to the side, at the midpoint, so the text clears the linework
double mx = (P.X + foot.X) / 2.0, my = (P.Y + foot.Y) / 2.0;
double dx = foot.X - P.X, dy = foot.Y - P.Y, len = Math.Sqrt(dx*dx + dy*dy);
double nx = -dy/len, ny = dx/len;
var dimLine = new Point3d(mx + nx*6.0, my + ny*6.0, 0.0);
var ad2 = new AlignedDimension(
new Point3d(P.X, P.Y, 0.0),
new Point3d(foot.X, foot.Y, 0.0),
dimLine, "", Db.Dimstyle);
ad2.Layer = DIM_LAYER;
ms.AppendEntity(ad2);
Tx.AddNewlyCreatedDBObject(ad2, true);
made++;
Log(String.Format(" pt {0} \"{1}\" -> foot {2:F3},{3:F3} dist {4:F4}",
cp.PointNumber, cp.RawDescription, foot.X, foot.Y, best));
}
Log("");
Log("dimensions created: " + made + " skipped (already had one): " + skipped);
int total = 0;
foreach (ObjectId id in ms) {
var ad = Tx.GetObject(id, OpenMode.ForRead) as AlignedDimension;
if (ad != null && !ad.IsErased) total++;
}
Log("aligned dimensions in model space: " + total + " (verified)");
Ed.Regen();
Result
Log
drawing: C:\Users\sanja\OneDrive\_SurveyDisco\260802 - 4082 Sweetbriar Ln, Forest Park, GA 30297, USA\260802 - 4082 Sweetbriar Ln.dwg centerline [20AD7] SS-V-ROAD-CNTR verts=3 centerline [20AD8] SS-V-ROAD-CNTR verts=8 existing aligned dimensions endpoints: 4 pt 103 already dimensioned - skipped pt 102 "IPF 1\2 RB" -> foot 2238168.389,1325137.542 dist 24.4407 pt 101 "IPF 5\8 RB DISTRB" -> foot 2238369.251,1325137.012 dist 92.8418 pt 100 already dimensioned - skipped dimensions created: 2 skipped (already had one): 2 aligned dimensions in model space: 4 (verified)
Notes
What worked, what didn't, job-specific gotchas — flagged notes feed the recipes.
No notes yet.