pub fn curve_surface_intersect<S: Scalar>(
curve: &NurbCurve<S, 4>,
surface: &NurbSurface<S, 4>,
max_solutions: usize,
max_nodes: usize,
min_subdivision_size: S,
) -> GeopResult<Intersections<(S, Vector2<S>)>>Expand description
Points where curve crosses (or, in the coplanar case, lies within)
surface.
A DFS-with-priority-queue search (restored, against the current
[DisjointSet]-based solution representation, from an earlier
implementation removed by commit d75bff5): the outer loop always dives
from the shallowest still-unexplored (curve segment, surface patch)
pair (a level-ordered BinaryHeap, so the search spreads laterally
across the whole domain before going deep anywhere), each dive following
[dfs]’s own leftmost-branch-first policy and stashing every sibling
subtree it skips along the way back onto the queue at its own depth. For
an isolated, genuine crossing this behaves essentially like a plain
stack-based DFS (hull-overlap pruning quickly discards everything but
the local neighborhood of the crossing, regardless of traversal order).
But for a coincident or coplanar pair — where hull-overlap pruning can’t
narrow anything down, since the curve overlaps the surface almost
everywhere along the shared region — a plain LIFO stack tends to
exhaustively refine one small neighborhood (feeding [DisjointSet] a
long run of adjacent, could_be_equal candidates that all merge into
one ever-widening solution) before ever reaching a genuinely different
part of the domain. The breadth-first-by-level ordering here instead
guarantees an evenly-spread set of solutions across the whole shared
region — which is what actually lets a caller reliably treat “found
max_solutions distinct solutions” as a coincidence signal in the first
place; see e.g. booleans::remesh::remesh_edges_x_faces.
The search stops once max_solutions distinct solutions have been
found, or the queue empties (every subtree explored, genuinely fewer
solutions than max_solutions) — either way, Ok. If it instead
exhausts max_nodes mid-dive without reaching either of those, that’s a
genuinely unknown result: this returns an error rather than silently
reporting a possibly-incomplete solution set as if it were final. A
caller checking len() >= max_solutions to detect coincidence has no
way to tell “genuinely converged short of the budget” apart from “ran
out of nodes early” otherwise — and the latter is, if anything, itself
evidence of extended overlap (an isolated crossing converges in a
handful of nodes; only a broad shared region burns through a real
budget), so callers relying on that heuristic should treat this error
the same way they’d treat hitting max_solutions.