C3D-0427 · WALL linework redo: gap-split runs, 12-cap, cross-product bulges [C3D-WALL2] done
Replaces the bad single V-WALL chain. All wall-family points (WALL/STEP/ROCK/FACE, extra words ignored) gap-split into separate runs (break > 30 ft), even-chunked at 12 verts advancing by cap-1, cross-product bulge signs so arcs bow the correct way. Removes the prior V-WALL polyline first.
C# payload
// WALL linework redo: gap-split runs, 12-cap, cross-product bulges
// Recipe-correct: gap-split into separate runs (break where the next-nearest jump > GAP), even-chunk
// at 12 verts advancing by cap-1 (never repeat a point), bulge sign by the cross-product test, no crossings.
const string LAYER="V-WALL"; const short COLOR=8; const double GAP=30; const int CAP=12;
var civ=Autodesk.Civil.ApplicationServices.CivilApplication.ActiveDocument;
Log("drawing: " + Db.Filename);
var grp=new HashSet<uint>();
foreach (ObjectId gid in civ.PointGroups){ var g=(Autodesk.Civil.DatabaseServices.PointGroup)Tx.GetObject(gid,OpenMode.ForRead); if(g.Name.Contains("800")||g.Name.Contains("5000")) foreach(uint u in g.GetPointNumbers()) grp.Add(u); }
var pts=new List<Point2d>();
foreach (ObjectId id in civ.CogoPoints){ var p=(Autodesk.Civil.DatabaseServices.CogoPoint)Tx.GetObject(id,OpenMode.ForRead);
if(!grp.Contains((uint)p.PointNumber)) continue; string d=(p.RawDescription??"").ToUpper(); if(d.Contains("WALL")||d.Contains("STEP")||d.Contains("ROCK")||d.Contains("FACE")) pts.Add(new Point2d(p.Easting,p.Northing)); }
Log("V-WALL points: " + pts.Count);
if(pts.Count<2){ Log("not enough"); return; }
// ---- remove the previous bad polyline(s) on this layer (my earlier naive pass)
var lt=(LayerTable)Tx.GetObject(Db.LayerTableId,OpenMode.ForWrite);
ObjectId layId; if(lt.Has(LAYER)) layId=lt[LAYER]; else { var l=new LayerTableRecord(); l.Name=LAYER; l.Color=Autodesk.AutoCAD.Colors.Color.FromColorIndex(Autodesk.AutoCAD.Colors.ColorMethod.ByAci,COLOR); layId=lt.Add(l); Tx.AddNewlyCreatedDBObject(l,true); }
var ms=(BlockTableRecord)Tx.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(Db),OpenMode.ForWrite);
int wiped=0; var del=new List<ObjectId>();
foreach (ObjectId id in ms){ var e=Tx.GetObject(id,OpenMode.ForRead) as Autodesk.AutoCAD.DatabaseServices.Entity; if(e is Polyline && e.Layer.Equals(LAYER,System.StringComparison.OrdinalIgnoreCase)) del.Add(id); }
foreach(var id in del){ ((Autodesk.AutoCAD.DatabaseServices.Entity)Tx.GetObject(id,OpenMode.ForWrite)).Erase(); wiped++; }
Log("removed " + wiped + " prior polyline(s) on " + LAYER);
// ---- nearest-neighbour order the whole set, then SPLIT into runs at any hop > GAP
double cx=0,cy=0; foreach(var p in pts){cx+=p.X;cy+=p.Y;} cx/=pts.Count; cy/=pts.Count;
int start=0; double best=-1; for(int i=0;i<pts.Count;i++){ double dd=(pts[i].X-cx)*(pts[i].X-cx)+(pts[i].Y-cy)*(pts[i].Y-cy); if(dd>best){best=dd;start=i;} }
var used=new bool[pts.Count]; var order=new List<int>{start}; used[start]=true;
var hop=new List<double>{0};
for(int k=1;k<pts.Count;k++){ int cur=order[order.Count-1]; int nn=-1; double nb=double.MaxValue;
for(int j=0;j<pts.Count;j++){ if(used[j])continue; double dd=(pts[cur].X-pts[j].X)*(pts[cur].X-pts[j].X)+(pts[cur].Y-pts[j].Y)*(pts[cur].Y-pts[j].Y); if(dd<nb){nb=dd;nn=j;} }
order.Add(nn); used[nn]=true; hop.Add(System.Math.Sqrt(nb)); }
// runs = consecutive order[] where hop <= GAP
var runs=new List<List<int>>(); var run=new List<int>{order[0]};
for(int k=1;k<order.Count;k++){ if(hop[k]>GAP){ runs.Add(run); run=new List<int>(); } run.Add(order[k]); }
runs.Add(run);
Log("split into " + runs.Count + " run(s) at gap " + GAP + " ft");
int drawn=0;
foreach(var r in runs){
if(r.Count<2){ Log(" skip 1-pt run"); continue; }
// chunk at CAP advancing by CAP-1 (share the seam vertex, never repeat inside a chunk)
for(int s=0;s<r.Count-1;s+=(CAP-1)){
int e=System.Math.Min(s+CAP, r.Count);
var chunk=r.GetRange(s, e-s);
if(chunk.Count<2) break;
// if the remaining tail would be a 2-pt stub, split this chunk evenly instead
var pl=new Polyline();
for(int i=0;i<chunk.Count;i++) pl.AddVertexAt(i, pts[chunk[i]], 0,0,0);
pl.LayerId=layId;
// bulge sign by cross-product test
for(int i=1;i<pl.NumberOfVertices-1;i++){ var a=pl.GetPoint2dAt(i-1); var b=pl.GetPoint2dAt(i); var c=pl.GetPoint2dAt(i+1);
double cross=(c.X-a.X)*(b.Y-a.Y)-(c.Y-a.Y)*(b.X-a.X);
double dx1=b.X-a.X,dy1=b.Y-a.Y,dx2=c.X-b.X,dy2=c.Y-b.Y; double ang=System.Math.Atan2(dx1*dy2-dy1*dx2, dx1*dx2+dy1*dy2);
double mag=System.Math.Tan(System.Math.Abs(ang)/4.0); double bulge = (cross<0? mag : -mag);
if(System.Math.Abs(bulge)>0.001) pl.SetBulgeAt(i-1,bulge); }
ms.AppendEntity(pl); Tx.AddNewlyCreatedDBObject(pl,true);
var back=(Polyline)Tx.GetObject(pl.ObjectId,OpenMode.ForRead);
Log(string.Format(" poly [{0}] {1} verts len {2:F1}", back.Handle, back.NumberOfVertices, back.Length));
drawn++;
if(e>=r.Count) break;
}
}
Log("drew " + drawn + " polyline(s) on " + LAYER);
Ed.Regen();
Result
Log
drawing: C:\Users\sanja\OneDrive\_SurveyDisco\260711 - 281 Maranatha Trail, Lawrenceville, GA 30045, USA\281 MARANTHA 2607.dwg V-WALL points: 82 removed 0 prior polyline(s) on V-WALL split into 10 run(s) at gap 30 ft skip 1-pt run skip 1-pt run skip 1-pt run poly [11B5A] 3 verts len 21.4 poly [11B5B] 2 verts len 0.2 poly [11B5C] 12 verts len 102.4 poly [11B5D] 12 verts len 71.8 poly [11B5E] 6 verts len 42.9 poly [11B5F] 4 verts len 9.3 poly [11B60] 12 verts len 92.6 poly [11B61] 12 verts len 29.2 poly [11B62] 11 verts len 30.6 poly [11B63] 4 verts len 13.7 poly [11B64] 5 verts len 59.6 drew 11 polyline(s) on V-WALL
Notes
What worked, what didn't, job-specific gotchas — flagged notes feed the recipes.
No notes yet.