research(R3): floor ownership on an overlapping helical passage
Read-only study for L38: a synthetic FI Style 2 helix (3 m radius, 3.31 m pitch) shows Euclidean closest-centerline ownership is wrong when bore radius > pitch/2; a floor-near (+-0.125 m, within bore radius) nearest-floor-point owner gives 2.9 cm p-p on helix and style-like paths. The L38 0.94 m ripple period equals the 20-segment chord. L38's continuation applied it: floor ripple 0; wall ripple open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
1 parent
7f2d84d2c7
commit
945225d942
3 files changed
+309
No files matched your search
@@ -0,0 +1,66 @@
|
||||
# Research R3 — floor ownership on an overlapping helical passage
|
||||
|
||||
## Ranked recommendation and experiment
|
||||
|
||||
**Rank 1: resolve the floor owner only from floor-near route candidates.** For a voxel within half a 25 cm voxel of a candidate floor (`abs(candidateFloorZ - qz) <= 0.125 m`), require that candidate to be within the bore radius in XY, then choose the nearest 3D floor point; break exact ties by lower stable segment index. If no such candidate exists, keep the existing floor/player fallback. Keep the tube owner separate: this rule chooses the floor cap, not the tube SDF.
|
||||
|
||||
Do not use a strict `candidateFloorZ <= qz` test. At 12.5 cm sampling, a voxel can round just below its true floor; strict-below then excludes the correct segment and selects the previous segment. In the synthetic test this made a 23.8 cm peak-to-peak floor error. The half-voxel symmetric band retained the correct floor candidate.
|
||||
|
||||
The 0.938 m ripple period in L38 is also the expected chord spacing of a 3 m radius, 20-segment turn: `2 R sin(pi/20) = 0.9386 m`. That ties the observed period to the route control-point interval. The full audit still needs to confirm whether a local floor-owner band removes its ripple.
|
||||
|
||||
### Synthetic measurements
|
||||
|
||||
The helix used the L27 FI Style 2 main-path measurements: 3.0 m mean centerline radius, 3.31 m vertical pitch, 12.95 turns, and 20 route controls per turn. The requested 4.5 m bore radius models the enlarged mouth; the same run was repeated at the 3.0 m mid-bore radius. Queries follow the analytic floor path at 0.125 m arc-length spacing; each position is rounded to a 0.125 m grid. There are 1,984 probes. The table reports peak-to-peak and maximum absolute error of selected floor height minus analytic floor height.
|
||||
|
||||
| Ownership rule | 4.5 m bore p-p / max abs | 3.0 m bore p-p / max abs |
|
||||
|---|---:|---:|
|
||||
| Analytic closest helix centerline | 3.372 / 3.372 m | 3.329 / 3.329 m |
|
||||
| Segment closest centerline | 3.387 / 3.383 m | 3.329 / 3.325 m |
|
||||
| Nearest 3D floor point | 0.029 / 0.015 m | 0.029 / 0.015 m |
|
||||
| Floor strictly below voxel, within bore radius | 0.238 / 0.224 m | 0.238 / 0.224 m |
|
||||
| Floor within ±0.125 m and bore radius | 0.029 / 0.015 m | 0.029 / 0.015 m |
|
||||
| Highest floor below voxel, within bore radius | 0.282 / 0.224 m | 0.282 / 0.224 m |
|
||||
| Height-bin local segment ±1, nearest floor point | 0.029 / 0.015 m | 0.029 / 0.015 m |
|
||||
| Helix angle plus height turn index | 0.030 / 0.015 m | 0.030 / 0.015 m |
|
||||
|
||||
The exact-curve reference searches all local minima over the finite helix and refines them with golden-section minimization; the other segment rules reproduce the carver's XY chord projection and lateral Catmull–Rom smoothing. The analytic centerline rule is wrong for floor ownership: with `bore radius > pitch/2`, a floor sample is vertically closer to the centerline on a neighboring turn. The floor-point and height-window rules agree on this ideal route. The test does **not** reproduce L38's reported 8.6 cm floor ripple; it establishes the failure modes, but the proposed guard remains a candidate until the real FI Style 2 audit is rerun.
|
||||
|
||||
Three additional monotone-grade style-like paths were sampled at 0.125 m: straight, a sinusoidal worm, and a scalloped cascade. Height-bin local ownership had p-p errors `0.005 / 0.030 / 0.031 m` (max absolute `0.003 / 0.016 / 0.016 m`). Nearest centerline ownership had `0.097 / 0.116 / 0.121 m` p-p. The literal strict-below-plus-radius rule had `0.203 / 0.231 / 11.567 m` p-p; the cascade's horizontal loops make a far-lower segment eligible. This disproves a one-sided “below and within radius” rule for shared use.
|
||||
|
||||
Reproduction: `taskset -c 0-11 prlimit --as=6442450944 -- python3 Saved/Linux/research/r3_helix_owner.py`.
|
||||
|
||||
## Math and code placement
|
||||
|
||||
For route point `C(s)` and radius `r(s)`, the carve floor is `F(s) = C_z(s) - r(s) + 0.15 m`. The planner stores `C_z = playerZ + r - 1.38 m`, so `F = playerZ - 1.23 m`. The radius cancels and the floor remains monotone wherever authored `playerZ` is monotone. The straight, worm, spiral, and cascading styles change the XY route; the planner assigns their Z profile from cumulative horizontal route distance. Confirm monotonicity on a candidate range and use the existing nearest-floor fallback for flat or non-monotone mouth/landing spans.
|
||||
|
||||
In `ApplyResolvedStratePassageCarves` (`Standalone/Core/src/ShapeWorldInternal.h`), add a `nearFloorCandidate` alongside `nearestFloorCandidate`. In the existing segment visitor, after computing `routeFloorQ` and horizontal distance squared, accept it into the new candidate only when `abs(routeFloorQ - qz) <= 0.125*qPerMetre` and horizontal distance squared is at most the interpolated radius squared. Select minimum floor-point distance, with stable segment-index tie-break. Apply that candidate only when valid; preserve the existing fallback otherwise. The current wide `carveBegin/carveEnd` range is around the `floorProfile`, so its monotone bounds already cover this band; alternatively, binary-search `F(s)` and visit the bracket segment plus its neighbors.
|
||||
|
||||
This is style-independent: the profile comes from route control points, not helix angle, generator type, or RNG. The incremental version costs a few comparisons and one squared-distance comparison for segments already visited. A narrowed search costs one binary search plus at most three segment evaluations. Neither needs `atan2`, trigonometric roots, iteration to convergence, or mutable state. Fixed-point comparisons and the stable segment tie-break preserve worker-count and peer determinism.
|
||||
|
||||
## Alternatives and distance-field literature
|
||||
|
||||
For a circular helix `gamma(t) = (R cos t, R sin t, b t)` and query `(rho cos phi, rho sin phi, z)`,
|
||||
|
||||
`D²(t) = rho² + R² + (b t - z)² - 2 R rho cos(t - phi)`.
|
||||
|
||||
Stationary points solve `u + e sin(u) = M`, with `u = t - phi`, `e = R rho / b²`, and `M = z/b - phi`. There is no elementary closed form. For the finite, radius-varying route, a safe reference solver brackets stationary candidates over turns, evaluates those roots and both endpoints, and compares distances. A recent 2026 preprint proves a principal-branch minimizer for an ideal infinite circular helix, despite multiple stationary roots, but it is not peer reviewed and does not cover our finite Catmull-smoothed route. Even a perfect Euclidean closest point is the wrong floor owner when the floor cap is offset below the centerline.
|
||||
|
||||
For floor probes on an ideal helix, an angle/height turn index can be written directly. With pitch `p = 2 pi b`, centerline height `z0 + b t`, and floor `z0 + b t - r + lift`, take `phi = atan2(qy-axisY, qx-axisX)` and
|
||||
|
||||
`n = round((qz - z0 - b phi + r - lift) / p)`, `t = phi + 2 pi n`.
|
||||
|
||||
Clamp or test the finite endpoints. This is cheap for a known helix and gives 0.030 m p-p error in the synthetic case, but it needs axis/pitch/radius metadata and has no direct equivalent for Straight, Worm, or Cascading. Use height only to disambiguate a local route interval in the shared path.
|
||||
|
||||
A hard union of independently floor-limited coils is mathematically the union of their void sets (use `min` for negative-inside SDFs; this code's positive-air density reverses that to `max`). It does not preserve a single walkable tread. The 3 m mid-bore and 3.31 m pitch satisfy `2r > pitch`, so adjacent swept tubes intersect and the union opens a route through the intervening floor/support. At the 4.5 m mouth the overlap is larger. Smooth min/max adds a fillet in the band where the fields are close; the polynomial smooth-min can shift the zero surface by up to `k/4`, which can easily exceed the 1.5 cm floor budget. Keep smooth CSG away from the hard floor cap.
|
||||
|
||||
CAD formulations for canal/pipe surfaces reduce distance queries to one-parameter root finding; they do not provide a cheap generic shortcut for this floor-owner query. Line-swept-sphere methods are closer to the current tube field, while high-curvature arbitrary cross-section sweeps may not have a globally smooth continuous distance field. Our control-point sweep is already a compact approximation, so changing the candidate ownership is lower cost than replacing it with a denser exact sweep representation.
|
||||
|
||||
References:
|
||||
|
||||
- [Closest Points on a Circular Helix and Kepler's Equation (2026 preprint)](https://www.preprints.org/manuscript/202608.1202) — stationary equation, multiple roots, and principal-branch result; the paper labels itself non-peer-reviewed.
|
||||
- [Efficient point-projection to freeform curves and surfaces](https://doi.org/10.1016/j.cagd.2011.04.002) — geometric culling followed by numerical projection; treats monotone spiral curves specially.
|
||||
- [Fast Distance Computation Between a Point and Cylinders, Cones, Line-Swept Spheres and Cone-Spheres](https://doi.org/10.1080/10867651.2004.10504892) and [Minimum distance between a canal surface and a simple surface](https://doi.org/10.1016/S0010-4485(02)00123-9) — swept-sphere and varying-radius canal-surface distance queries.
|
||||
- [Iñigo Quílez, Smooth Minimum](https://archive.ph/9Z4dZ) and [distance-function modeling](https://vodacek.zvb.cz/archiv/101.html) — hard min/max operations, polynomial smooth-min formula, blend band, and distance-field caveats.
|
||||
- [Synthesizing Geologically Coherent Cave Networks](https://diglib.eg.org/items/a4e7985c-af52-4b55-bd1a-eeeff6c47422) — uses compact sweep primitives for straighter conduits and sampled-sphere unions for tortuous conduits to keep a continuous 1-Lipschitz field; the latter costs more memory.
|
||||
- [Feng and Crane, A Heat Method for Generalized Signed Distance](https://nzfeng.github.io/research/SignedHeatMethod/index.html) — robust generalized distance for broken/noisy/self-intersecting geometry; it solves global sparse systems, a dense offline option rather than a cheap independent per-voxel owner query.
|
||||
- Local context: `Standalone/Research/WorldAssemblerM3/Linux27/REPORT.md`, `Standalone/Research/WorldAssemblerM3/Linux38/REPORT.md`, `Standalone/Core/src/ResolvedLayoutInternal.h`, and `Standalone/Core/src/ShapeWorldInternal.h`.
|
||||
@@ -0,0 +1,212 @@
|
||||
import math
|
||||
import bisect
|
||||
|
||||
DS = 0.125
|
||||
PITCH = 3.31 # L27 measured FI Style 2 main helix pitch (m/turn)
|
||||
HELIX_R = 3.0 # measured mean centerline radius (m)
|
||||
BORE_R = 4.5 # conservative authored near-mouth bore radius (m)
|
||||
LIFT = 0.15
|
||||
TURNS = 12.95
|
||||
SEGMENTS_PER_TURN = 20
|
||||
GRID = 0.125
|
||||
|
||||
|
||||
def snap(v):
|
||||
return round(v / GRID) * GRID
|
||||
|
||||
|
||||
def catmull(p0, p1, p2, p3, t):
|
||||
t2, t3 = t*t, t*t*t
|
||||
return 0.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t2+(-p0+3*p1-3*p2+p3)*t3)
|
||||
|
||||
|
||||
def helix_run(radius=HELIX_R, pitch=PITCH, turns=TURNS, bore=BORE_R):
|
||||
n = math.ceil(turns * SEGMENTS_PER_TURN)
|
||||
theta_end = turns * 2*math.pi
|
||||
k = pitch/(2*math.pi)
|
||||
# At control i, z is the centerline height; its floor is z - bore + LIFT.
|
||||
pts = []
|
||||
for i in range(n+1):
|
||||
th = theta_end*i/n
|
||||
pts.append((radius*math.cos(th), radius*math.sin(th), k*th))
|
||||
length_per_rad = math.hypot(radius, k)
|
||||
count = math.ceil(theta_end*length_per_rad/DS)
|
||||
samples = []
|
||||
for j in range(count+1):
|
||||
th = theta_end*j/count
|
||||
true_floor = k*th-bore+LIFT
|
||||
q = (snap(radius*math.cos(th)), snap(radius*math.sin(th)), snap(true_floor))
|
||||
samples.append((th, true_floor, q))
|
||||
return pts, samples, bore, (lambda th: th)
|
||||
|
||||
|
||||
def other_run(kind, bore=1.5):
|
||||
# Monotone-grade non-helix controls: straight, bounded worm, and scalloped cascade.
|
||||
length = 80.0
|
||||
n = math.ceil(length / 0.75)
|
||||
pts = []
|
||||
xy = []
|
||||
for i in range(n+1):
|
||||
s = length*i/n
|
||||
if kind == 'straight':
|
||||
x, y = s, 0.0
|
||||
elif kind == 'worm':
|
||||
x, y = s, 2.0*math.sin(s/5.0)+0.35*math.sin(s/1.7)
|
||||
elif kind == 'cascading':
|
||||
th = s/5.0
|
||||
r = 10.0-1.3*abs(math.sin(4.0*th))
|
||||
x, y = r*math.cos(th), r*math.sin(th)
|
||||
else:
|
||||
raise ValueError(kind)
|
||||
xy.append((x,y))
|
||||
arc=[0.0]
|
||||
for i in range(1,len(xy)):
|
||||
arc.append(arc[-1]+math.hypot(xy[i][0]-xy[i-1][0],xy[i][1]-xy[i-1][1]))
|
||||
for i,(x,y) in enumerate(xy):
|
||||
pts.append((x,y,-0.19*arc[i]))
|
||||
samples=[]
|
||||
total=arc[-1]
|
||||
count=math.ceil(total/DS)
|
||||
for j in range(count+1):
|
||||
s=total*j/count
|
||||
i=0
|
||||
while i+1<len(arc) and arc[i+1]<s: i+=1
|
||||
if i+1>=len(arc): i=len(arc)-2
|
||||
t=(s-arc[i])/(arc[i+1]-arc[i])
|
||||
x=pts[i][0]*(1-t)+pts[i+1][0]*t
|
||||
y=pts[i][1]*(1-t)+pts[i+1][1]*t
|
||||
z=pts[i][2]*(1-t)+pts[i+1][2]*t
|
||||
f=z-bore+LIFT
|
||||
samples.append((s,f,(snap(x),snap(y),snap(f))))
|
||||
return pts,samples,bore,None
|
||||
|
||||
|
||||
def project_candidates(pts, q, bore):
|
||||
qx,qy,qz=q
|
||||
out=[]
|
||||
for i in range(len(pts)-1):
|
||||
a,b=pts[i],pts[i+1]
|
||||
dx,dy=b[0]-a[0],b[1]-a[1]
|
||||
h2=dx*dx+dy*dy
|
||||
if h2<1e-12:
|
||||
dz=b[2]-a[2]
|
||||
den=dx*dx+dy*dy+dz*dz
|
||||
t=max(0.0,min(1.0,((qx-a[0])*dx+(qy-a[1])*dy+(qz-a[2])*dz)/den))
|
||||
else:
|
||||
t=max(0.0,min(1.0,((qx-a[0])*dx+(qy-a[1])*dy)/h2))
|
||||
cx=a[0]+t*dx
|
||||
cy=a[1]+t*dy
|
||||
# Match ShapeWorldInternal.h: smooth only the lateral coordinates with Catmull-Rom.
|
||||
if i>2 and i+12<len(pts)-1:
|
||||
p0,p1,p2,p3=pts[i-1],a,b,pts[i+2]
|
||||
cx=catmull(p0[0],p1[0],p2[0],p3[0],t)
|
||||
cy=catmull(p0[1],p1[1],p2[1],p3[1],t)
|
||||
cz=a[2]+t*(b[2]-a[2])
|
||||
floor=cz-bore+LIFT
|
||||
hx,hy=qx-cx,qy-cy
|
||||
h2=hx*hx+hy*hy
|
||||
fd2=h2+(qz-floor)*(qz-floor)
|
||||
cd2=h2+(qz-cz)*(qz-cz)
|
||||
out.append((floor,fd2,cd2,h2,i,t,cx,cy))
|
||||
return out
|
||||
|
||||
|
||||
def metrics(label, pts, samples, bore, helix_info=None):
|
||||
names=['nearest centerline','nearest floor point','below+within-radius (strict)',
|
||||
'below+within-radius (+0.125m)','topmost floor below',
|
||||
'near-floor band (±0.125m)',
|
||||
'height-bin local segment (±1)','angle+height']
|
||||
if helix_info:
|
||||
names.insert(1,'analytic closest helix centerline')
|
||||
errors={n:[] for n in names}
|
||||
owners={n:[] for n in names}
|
||||
for loc,true_floor,q in samples:
|
||||
c=project_candidates(pts,q,bore)
|
||||
# Stable tie: lower segment index after score.
|
||||
a=min(c,key=lambda x:(x[2],x[4]))
|
||||
b=min(c,key=lambda x:(x[1],x[4]))
|
||||
filt=[x for x in c if x[0]<=q[2]+1e-12 and math.sqrt(x[3])<=bore]
|
||||
fc=min(filt,key=lambda x:(x[1],x[4])) if filt else b
|
||||
filt_tol=[x for x in c if x[0]<=q[2]+0.125+1e-12 and math.sqrt(x[3])<=bore]
|
||||
ft=min(filt_tol,key=lambda x:(x[1],x[4])) if filt_tol else b
|
||||
below=[x for x in c if x[0]<=q[2]+1e-12 and math.sqrt(x[3])<=bore]
|
||||
top=max(below,key=lambda x:(x[0],-x[4])) if below else b
|
||||
near=[x for x in c if abs(x[0]-q[2])<=0.125+1e-12 and math.sqrt(x[3])<=bore]
|
||||
nf=min(near,key=lambda x:(x[1],x[4])) if near else b
|
||||
floors=[p[2]-bore+LIFT for p in pts]
|
||||
if floors[0] < floors[-1]:
|
||||
i=max(0,min(len(pts)-2,bisect.bisect_right(floors,q[2])-1))
|
||||
else:
|
||||
neg=[-v for v in floors]
|
||||
i=max(0,min(len(pts)-2,bisect.bisect_right(neg,-q[2])-1))
|
||||
local=[x for x in c if abs(x[4]-i)<=1]
|
||||
hb=min(local,key=lambda x:(x[1],x[4])) if local else b
|
||||
if helix_info:
|
||||
radius,pitch,theta_end=helix_info
|
||||
phi=math.atan2(q[1],q[0])
|
||||
# Select the angle-aligned turn whose analytic floor is closest to voxel height.
|
||||
theta_z=(q[2]+bore-LIFT)/(pitch/(2*math.pi))
|
||||
k0=round((theta_z-phi)/(2*math.pi))
|
||||
th=max(0.0,min(theta_end,phi+2*math.pi*k0))
|
||||
hfloor=(pitch/(2*math.pi))*th-bore+LIFT
|
||||
howner=k0
|
||||
else:
|
||||
hfloor=b[0]
|
||||
howner=b[4]
|
||||
selected=[(names[0],a[0],a[4])]
|
||||
if helix_info:
|
||||
radius,pitch,theta_end=helix_info
|
||||
qx,qy,qz=q
|
||||
def dist2(th):
|
||||
cx=radius*math.cos(th); cy=radius*math.sin(th); cz=pitch*th/(2*math.pi)
|
||||
return (qx-cx)**2+(qy-cy)**2+(qz-cz)**2
|
||||
step=math.pi/16.0
|
||||
count=math.ceil(theta_end/step)
|
||||
vals=[dist2(min(theta_end,i*step)) for i in range(count+1)]
|
||||
best=(vals[0],0.0)
|
||||
if (vals[-1],theta_end)<best: best=(vals[-1],theta_end)
|
||||
gr=(math.sqrt(5.0)-1.0)/2.0
|
||||
for i in range(1,count):
|
||||
if vals[i]>vals[i-1] or vals[i]>vals[i+1]: continue
|
||||
lo=max(0.0,(i-1)*step); hi=min(theta_end,(i+1)*step)
|
||||
x1=hi-gr*(hi-lo); x2=lo+gr*(hi-lo)
|
||||
f1,f2=dist2(x1),dist2(x2)
|
||||
for _ in range(30):
|
||||
if f1<=f2:
|
||||
hi,x2,f2=x2,x1,f1; x1=hi-gr*(hi-lo); f1=dist2(x1)
|
||||
else:
|
||||
lo,x1,f1=x1,x2,f2; x2=lo+gr*(hi-lo); f2=dist2(x2)
|
||||
th=(lo+hi)*0.5; value=dist2(th)
|
||||
if value<best[0]: best=(value,th)
|
||||
exact_floor=pitch*best[1]/(2*math.pi)-bore+LIFT
|
||||
selected.append((names[1],exact_floor,best[1]))
|
||||
selected += [(names[2],b[0],b[4]),(names[3],fc[0],fc[4]),
|
||||
(names[4],ft[0],ft[4]),(names[5],top[0],top[4]),
|
||||
(names[6],nf[0],nf[4]),(names[7],hb[0],hb[4]),
|
||||
(names[8],hfloor,howner)]
|
||||
else:
|
||||
selected += [(names[1],b[0],b[4]),(names[2],fc[0],fc[4]),
|
||||
(names[3],ft[0],ft[4]),(names[4],top[0],top[4]),
|
||||
(names[5],nf[0],nf[4]),(names[6],hb[0],hb[4]),
|
||||
(names[7],hfloor,howner)]
|
||||
for name,f,owner in selected:
|
||||
errors[name].append(f-true_floor)
|
||||
owners[name].append(owner)
|
||||
print(f'[{label}] probes={len(samples)} grid={GRID:.3f} m bore_radius={bore:.2f} m')
|
||||
for name in names:
|
||||
es=errors[name]
|
||||
pp=max(es)-min(es)
|
||||
rms=math.sqrt(sum(e*e for e in es)/len(es))
|
||||
mae=sum(abs(e) for e in es)/len(es)
|
||||
flips=sum(owners[name][i]!=owners[name][i-1] for i in range(1,len(owners[name])))
|
||||
print(f' {name:39s} ripple_pp={pp:8.4f} max_abs={max(map(abs,es)):8.4f} rms={rms:8.4f} owner_steps={flips}')
|
||||
|
||||
|
||||
pts,samples,bore,_=helix_run()
|
||||
metrics('FI-style2 helix',pts,samples,bore,(HELIX_R,PITCH,TURNS*2*math.pi))
|
||||
# Mid-run bore from the published route is 3 m; this checks the mouth-radius stress case above.
|
||||
pts3,samples3,bore3,_=helix_run(bore=3.0)
|
||||
metrics('FI-style2 mid-bore control',pts3,samples3,bore3,(HELIX_R,PITCH,TURNS*2*math.pi))
|
||||
for style in ('straight','worm','cascading'):
|
||||
p,s,b,_=other_run(style)
|
||||
metrics(style,p,s,b)
|
||||
@@ -0,0 +1,31 @@
|
||||
# Shared notes (researcher R3 <-> implementer L38 continued), newest at bottom
|
||||
|
||||
## R3 — ranked floor ownership and first synthetic results (2026-10-23)
|
||||
|
||||
**Rank 1: keep the bore owner and floor owner separate. For floor samples, select the nearest floor point only from a local height band `abs(candidateFloorQ - qz) <= 0.125 m` (half the 25 cm voxel) and `horizontalDistance <= boreRadius`; break ties by stable lower segment index. If the band is empty, retain the existing floor/player fallback.** The shared route floor is monotone in control-point order: the carver's `point.z - point.radius + playerCenterAboveFloor` cancels the radius offset in the planner and equals authored `playerZ`, which is interpolated monotonically by cumulative route distance. A binary search on that profile can restrict the near-floor segment range to the crossing segment and its neighbors, with no style/generator branch. This is an ownership guard, not yet a claim that it passes the real L38 ripple audit.
|
||||
|
||||
**Synthetic floor-error ripple (peak-to-peak / max absolute, metres; 1,984 floor probes, 0.125 m sampling, 3.0 m centerline radius, 3.31 m vertical pitch, 20 route controls/turn, 12.95 turns; bore radius 4.5 m, repeated at the 3.0 m mid-bore):**
|
||||
|
||||
| Rule | FI-style2 p-p / max-abs | Read |
|
||||
|---|---:|---|
|
||||
| Exact analytic closest helix centerline | 3.372 / 3.372 | Wrong floor coil when distance to centerline is used for floor ownership. |
|
||||
| Segment closest centerline | 3.387 / 3.383 | Same wrong-turn failure. |
|
||||
| Nearest 3D floor point, unconstrained | 0.029 / 0.015 | Correct on this ideal route; max-abs is just under the 1.5 cm gate, but p-p is not. |
|
||||
| Strict `floor <= qz`, within bore radius | 0.238 / 0.224 | Fails: voxel rounding excludes the true floor when it lies up to half a voxel above `qz`, so ownership drops to a lower segment. |
|
||||
| Near-floor band `abs(floor-qz)<=0.125`, within radius | 0.029 / 0.015 | Matches nearest floor point here; prevents the strict-below one-segment drop. |
|
||||
| Highest floor below `qz`, within radius | 0.282 / 0.224 | Fails; a one-sided “topmost below” rule is unstable at voxel boundaries. |
|
||||
| Height-bin control segment ±1, then nearest floor point | 0.029 / 0.015 | Same as floor-point nearest on this ideal route; deterministic, style-independent guard. |
|
||||
| Angle + height coil index | 0.030 / 0.015 | Works for this uniform helix after endpoint clamping; costs axis/angle/turn math and is style-specific. |
|
||||
|
||||
On synthetic straight / worm / cascading paths, height-bin local ownership measured p-p `0.005 / 0.030 / 0.031 m` (max abs `0.003 / 0.016 / 0.016 m`), versus centerline ownership `0.097 / 0.116 / 0.121 m`. Strict below-plus-radius reached `11.57 m` p-p on the looping cascade. This rejects that literal rule for shared use. The smooth ideal test does **not** reproduce L38's reported 8.6 cm floor ripple; it establishes the wrong-turn and voxel-boundary failure modes. Re-run the actual FI Style 2 floor/wall audit before accepting the guard.
|
||||
|
||||
The reported 0.938 m ripple period matches the expected control chord for the 3 m, 20-segment helix: `2*3*sin(pi/20) = 0.9386 m`; that points to per-control-segment ownership/smoothing as the repeat interval.
|
||||
|
||||
**Rank 2:** analytic helix closest point is useful as a reference/control, not the runtime shared owner. For `gamma(t)=(R cos t,R sin t,b t)` and query cylindrical coordinates `(rho,phi,z)`, stationary points solve `u + e sin(u) = M`, where `u=t-phi`, `e=R rho/b^2`, `M=z/b-phi`. There is no elementary closed form; the equation can have multiple roots per turn when `e>1`, so robust finite-route search brackets candidates and includes endpoints. Here `b=3.31/(2 pi)=0.527 m/rad`; floor queries have large `e`, and exact closest centerline is the wrong semantic owner because the bore floor lies farther below the centerline than the turn pitch permits.
|
||||
|
||||
For an ideal helix floor probe, angle/height gives `n=round((qz-z0-b*phi+r-lift)/pitch)`, `t=phi+2*pi*n`, where `phi=atan2(qy-axisY,qx-axisX)` and `lift=0.15m`. This avoids Euclidean coil ownership but needs helix axis/pitch metadata and a finite-end clamp; keep it as a reference, not the shared implementation.
|
||||
|
||||
**Rank 3:** hard union of floor-limited coils is geometrically valid only if a merged void is intended. With 3 m mid-bore radius and 3.31 m pitch, neighboring swept tubes overlap (`2r > pitch`); a union opens the overlap and can erase the upper coil's tread/support. A smooth union expands/rounds that seam and shifts the zero surface by up to `k/4` for the polynomial smooth-min. Do not use it to decide floor ownership.
|
||||
|
||||
Sources and details will be collected in `Standalone/Research/WorldAssemblerM3/Research3/REPORT.md`.
|
||||
|
||||
Reference in new issue
Block a user