Skip to content

Commit c232df2

Browse files
sth-vclaude
andcommitted
feat: add configurable bounds parameter to newton_csx
newton_csx now accepts optional bounds=(t_lo, t_hi, u_lo, u_hi, v_lo, v_hi) for clamping parameters to a sub-region instead of [0,1]^3. Phase 2 continues using unbounded Newton + "converged outside cell → prune" which is faster: Newton quickly escapes to the nearest intersection, the result is checked against the cell range, and empty cells are pruned without wasting iterations at clamped boundaries. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8e5a58c commit c232df2

1 file changed

Lines changed: 23 additions & 7 deletions

File tree

mmcore/numeric/intersection/_bezier_common.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -288,22 +288,38 @@ def newton_csx(
288288
step_tol: float = 1e-14,
289289
max_it: int = 30,
290290
lm_damp: float = 1e-12,
291+
bounds: tuple = None,
291292
):
292293
"""LM-damped Newton for G(t,u,v) = C(t) - S(u,v) = 0.
293294
294295
Runs until residual < tol, step < step_tol, line search fails, or max_it.
295296
297+
Parameters
298+
----------
299+
bounds : tuple, optional
300+
If given, (t_lo, t_hi, u_lo, u_hi, v_lo, v_hi) — parameters are
301+
clamped to these ranges instead of [0,1]. Useful in Phase 2 where
302+
only the current cell's range is relevant.
303+
296304
Returns
297305
-------
298306
t, u, v : float
299-
Best parameters found (clamped to [0, 1]).
307+
Best parameters found (clamped to bounds).
300308
G : ndarray
301309
Final residual vector.
302310
last_step : tuple[float, float, float]
303-
Last accepted (dt, du, dv) step — the caller can compare against
304-
parametric tolerances to decide if Newton has converged
305-
in the parameter-space sense.
311+
Last accepted (dt, du, dv) step.
306312
"""
313+
if bounds is not None:
314+
t_lo, t_hi, u_lo, u_hi, v_lo, v_hi = bounds
315+
else:
316+
t_lo, t_hi, u_lo, u_hi, v_lo, v_hi = 0.0, 1.0, 0.0, 1.0, 0.0, 1.0
317+
318+
def _clamp(x, lo, hi):
319+
if x <= lo: return lo
320+
if x >= hi: return hi
321+
return x
322+
307323
t, u, v = float(t0), float(u0), float(v0)
308324
last_dt, last_du, last_dv = 1.0, 1.0, 1.0
309325

@@ -332,9 +348,9 @@ def newton_csx(
332348
step = 1.0
333349
accepted = False
334350
for _ls in range(8):
335-
tn = _clamp01(t + step * delta[0])
336-
un = _clamp01(u + step * delta[1])
337-
vn = _clamp01(v + step * delta[2])
351+
tn = _clamp(t + step * delta[0], t_lo, t_hi)
352+
un = _clamp(u + step * delta[1], u_lo, u_hi)
353+
vn = _clamp(v + step * delta[2], v_lo, v_hi)
338354
Gn = (eval_curve(C, tn, rational=rational)
339355
- eval_surface(S, un, vn, rational=rational))
340356
if float(np.dot(Gn, Gn)) <= g2:

0 commit comments

Comments
 (0)