fix(algo): accept reversed NURBS sub-spans and run lens interior search as a last resort#1099
Conversation
…ch as a last resort Two coupled fixes from the deepened-notch dig: 1. topology: domain_with_endpoints now also accepts a REVERSED validated sub-span on a clearly open NURBS curve, returning t0 > t1 so start-to-end interpolation stays truthful. Closed curves keep the full-domain fallback: a reversed projection pair there is usually a seam-crossing forward sub-arc, and interpolating backward would trace the complement arc. 2. algo: a cylinder/cone wall can reach classification with a closed curved inner wire (e.g. a pre-existing notch outline kept through the generic split path) but no precomputed interior, because only the internal-loops splitter ran the dedicated remainder search; the curved-lens flag then aborted the analytic split unconditionally. Run cylinder_cone_remainder_interior as a last resort at the consumption point in fill_images_faces; abort only when even the dense grid finds no contained point. On the deepened-notch raw repro the pair takes posBad 10 -> 6 and resolves both mirrored micro-edge junction chains. The remaining 6 unpaired edges are one root (cone face not split by marched cone-plane sections), documented in the roadmap row updated here. Full workspace green; d4 canary green.
WASM Binary Size
|
There was a problem hiding this comment.
Pull request overview
Updates core modeling behavior to better respect endpoint-trimmed NURBS conventions during edge evaluation, and improves robustness of analytic face classification for cylinder/cone “curved-lens” walls by ensuring an interior point can still be found when earlier split paths didn’t compute one.
Changes:
- Topology:
EdgeCurve::domain_with_endpoints(NURBS) now accepts validated reversed sub-spans on clearly open curves (returningt0 > t1), while preserving full-domain fallback for (nearly) closed curves. - Algo:
fill_images_facesnow runscylinder_cone_remainder_interioras a last-resort interior search for curved-lens cylinder/cone walls with no precomputed interior, aborting only if the dense search still finds no contained point. - Builder plumbing: exposes/re-exports
cylinder_cone_remainder_interiorfor use at the consumption point.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| crates/topology/src/edge.rs | Accept reversed validated NURBS sub-spans on open curves; update/extend unit tests for reversed-open vs reversed-closed behavior. |
| crates/algo/src/builder/fill_images_faces.rs | Runs remainder-interior search as a last-resort for curved-lens walls to avoid unconditional analytic aborts when interior wasn’t precomputed. |
| crates/algo/src/builder/face_splitter/special_cases.rs | Adjusts visibility of cylinder_cone_remainder_interior so it can be invoked from fill_images_faces. |
| crates/algo/src/builder/face_splitter/mod.rs | Re-exports cylinder_cone_remainder_interior with builder-scoped visibility. |
| .claude/skills/roadmap/SKILL.md | Updates internal roadmap notes to reflect the revised understanding and fix path. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// kept wall well clear of every lens. Returns `None` if the surface evaluator | ||
| /// or boundary v-range is unusable, so the caller keeps the unset interior. | ||
| fn cylinder_cone_remainder_interior(remainder: &SplitSubFace) -> Option<Point3> { | ||
| pub fn cylinder_cone_remainder_interior(remainder: &SplitSubFace) -> Option<Point3> { |
Greptile SummaryTwo coupled fixes to the NURBS endpoint-trimmed convention work.
Confidence Score: 4/5Safe to merge; the two changes are tightly scoped and the fallback paths (full-domain for ambiguous closed curves, mesh-fallback when the dense grid still finds nothing) are unchanged. Both fixes are well-reasoned and backed by updated unit tests. The only observation is that WELD_EPS serves as both the on-curve projection tolerance and the open/closed curve boundary detector without a comment explaining the shared scale; a future maintainer could change one meaning unintentionally. crates/topology/src/edge.rs lines 127-132 — the dual use of WELD_EPS is worth a clarifying comment before the constant is ever adjusted. Important Files Changed
Reviews (1): Last reviewed commit: "fix(algo): accept reversed NURBS sub-spa..." | Re-trigger Greptile |
| let dt = pb.parameter - pa.parameter; | ||
| let curve_open = (p0 - p1).length() >= WELD_EPS; | ||
| if pa.distance < WELD_EPS | ||
| && pb.distance < WELD_EPS | ||
| && pb.parameter - pa.parameter > 1e-6 * (d1 - d0) | ||
| && dt.abs() > 1e-6 * (d1 - d0) | ||
| && (dt > 0.0 || curve_open) |
There was a problem hiding this comment.
WELD_EPS used for two distinct roles without comment
WELD_EPS = 1e-5 is introduced as the "NURBS sub-span on-curve band" distance, i.e., how far a projected endpoint may sit off the curve before being distrusted. It is then reused on line 128 to determine whether the underlying curve itself is open or nearly-closed — a conceptually different test. The two roles happen to share the same numeric scale, but the coincidence is not explained. A reader maintaining this later may tighten the on-curve band (e.g., to match vertex tolerance) without realising it also changes the open/closed classification boundary, or vice versa. A short inline comment stating why the same value is appropriate for both would prevent this drift.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
🤖 I have created a release *beep* *boop* --- ## [2.126.12](v2.126.11...v2.126.12) (2026-07-17) ### Bug Fixes * **algo:** accept reversed NURBS sub-spans and run lens interior search as a last resort ([#1099](#1099)) ([95b899a](95b899a)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Release `brepkit-wasm` 2.126.12 with a robustness fix in the geometry algorithm: handles reversed NURBS sub-spans and adds a last-resort lens interior search to reduce missed solutions. - **Bug Fixes** - Accept reversed NURBS sub-spans during evaluation. - Add lens interior search fallback for edge cases. <sup>Written for commit 87fb8e6. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/andymai/brepkit/pull/1100?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> Co-authored-by: brepkit[bot] <265643962+brepkit[bot]@users.noreply.github.com>
Summary
Second landing of the NURBS endpoint-trimmed convention work (#1097), from the snapClip deepened-notch dig. Two coupled fixes:
1. Reversed sub-spans on open curves (topology)
domain_with_endpointsnow also accepts a REVERSED validated sub-span on a clearly open NURBS curve, returningt₀ > t₁so start→end interpolation stays truthful. Closed curves keep the full-domain fallback: a reversed projection pair there is usually a seam-crossing forward sub-arc, and interpolating backward would trace the complement arc. Unit tests updated: reversed-on-open now trims (and evaluates back to its endpoints); a new closed-fitted-loop test pins the reversed-pair fallback.2. Curved-lens interior search as a last resort (algo)
A cylinder/cone wall can reach classification carrying a closed curved inner wire — e.g. a pre-existing notch outline kept through the generic split path — with no precomputed interior, because only the internal-loops splitter ran the dedicated remainder search. The curved-lens flag then aborted the analytic split unconditionally ("no contained interior for curved-lens wall").
fill_images_facesnow runscylinder_cone_remainder_interioras a last resort at the consumption point; the abort remains, but only when even the dense 256×17 grid finds no contained point.These are coupled: reversed spans re-shape the deepened-notch split so a legitimate pre-existing lens hole lands on a generic-split wall, which without fix 2 aborts the whole analytic cut.
Verification
compute_mesh_lod, passes standalone).edge.rs.Summary by cubic
Accept reversed NURBS sub-spans on open curves and add a last-resort interior search for curved-lens walls to avoid false analytic-split aborts. This fixes deepened-notch cases and reduces unpaired edges (posBad 10 → 6).
EdgeCurve::domain_with_endpointsaccepts validated reversed spans on clearly open NURBS curves, returningt0 > t1; closed curves still fall back to the full domain.fill_images_faces, runcylinder_cone_remainder_interioras a last resort for cylinder/cone walls with curved inner wires but no precomputed interior; abort only if the dense grid finds no interior point.Written for commit ad59fff. Summary will update on new commits.