Repository navigation
Conversation
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
5b2e7cd to
39a5ef9
Compare
…ls: 2450, 39800) After its face pairs, a boolean tests every proto vertex against every proto edge (`RemoveCoincidentNoEdgeProtoVertex`) and removes a vertex that lies on an edge only when the vertex has no proto edges of its own. A plate minus N cylinders in one `boolean_lists` call has 2N proto vertices, each the end of its own closed proto edge, and 2N proto edges: nothing can be removed, and 4N^2 - 2N point solves run all the same. `WorkCounters::proto_vertex_point_solves` counts each solve where it runs. The new test asks for 0 at 25 and at 100 holes, with the cut's faces, edges and exact volume. It fails with 2450 and 39800. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…the proto edges With proto_vertex_miss_is_false on, remove_coincident_no_edge_proto_vertex answers false for a miss and for a hit on a proto vertex that has proto edges of its own. No outcome of the point solve gives another answer for such a vertex, so the function returns false before the solve. A plate minus N cylinders cut in one boolean_lists call ran 4N^2 - 2N of these solves (2450 at N = 25, 39800 at N = 100); it now runs 0. The body is the same: N + 6 faces, 3N + 12 edges, the exact volume. Under an already-fired cancel token the solve runs as it did before, so from the same caches the function returns what it returned. A skipped solve leaves its curve's cache cold, so a kernel cancelled later can report its `Cancelled` error from another check (another operation label); the boolean asks the token again after this step, and no boolean was found to change between success and error. With the flag off nothing changes. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
39a5ef9 to
92df673
Compare
Fixes #3260
With
proto_vertex_miss_is_falseon, a boolean no longer solves a proto vertex against a proto edge when the vertex has proto edges of its own: 0 point solves in place of 4N² − 2N for a plate minus N cylinders cut in one call. Every boolean that returned a body returns the same body. What a kernel cancelled mid-operation reports can differ (below).Related: #3248, pass B (proto vertices against proto edges). That issue proposes a box index so fewer pairs are visited; this PR is the other half and does not overlap with it: for the pairs that are visited, the solve is not run when the proto vertex has proto edges. Not measured on #3248's case (whether its proto vertices have proto edges of their own decides how much of its pass B this removes).
The problem
After its face pairs, a boolean tests every proto vertex against every proto edge (
RemoveCoincidentNoEdgeProtoVertex). A vertex found on an edge is removed only when it has no proto edges of its own. The point solve ran first all the same, for every pair.Cutting N cylinders out of a plate in one
boolean_listscall makes 2N section circles: 2N proto edges, each closed on its own proto vertex. Every vertex has an edge, so nothing can be removed, and 4N² − 2N solves ran for nothing.The change
topology/proto_topology/p1/proto.rs,remove_coincident_no_edge_proto_vertex: withproto_vertex_miss_is_false(WR-73, #848) on, a miss answersfalse, and a hit on a vertex that has proto edges answersfalsetoo. No outcome of the solve gives another answer for such a vertex, so the function returnsfalsebefore the solve. The checks before it (a deleted object, a missing curve) stay, in the same order.true, which ends the caller's loop, so the solve does decide something. That path goes when the flag is retired.WorkCounters::proto_vertex_point_solvescounts each solve, for the test.No new flag, no cache, no second attempt.
Counts
Plate
20 n x 20 n x 12minus N = n² cylinders r 4 in oneboolean_listscall, SolidCraft's fixes:The result has N + 6 faces, 3N + 12 edges and its exact volume, before and after.
What changes in the result
Cancellederror can differ. Skipping a solve also skips warming its curve's cache. A kernel cancelled later can therefore notice the cancel at a different check:CurveCache::tessellatewhere it wasgeom::global_solver::solve_branch.Ok(false)with the old solve's cache warming andCancelledwithout it. The manager's state is unchanged either way.resolve_intersections).Unportedraised only inside a solve that is no longer run, and whose answer was not read, would no longer end the boolean there. No boolean that reaches one is known: the site once suspected is not reachable, because the curve cache is built from a copy detached from its owner.If a changed
Cancelledlabel counts as a changed result here, say so and I will withdraw this: it cannot be kept identical without running the solve.Tests
plate_cut_solves_no_proto_vertex_that_has_proto_edges(committed first, failing with(2450, 39800)against(0, 0)).a_proto_vertex_with_proto_edges_is_not_solved: 0 solves for a vertex with edges on the curve or off it, 1 for an edge-less one, and under an already-fired cancel token the solve run for every vertex (3 solves, the old answers).Verification
On
92df6735a, rebased on maindc5cfd7e7, Linux (WSL Ubuntu 22.04):cargo fmt --all --check,cargo clippy --workspace --all-targets -- -D warnings,check_panic_sites.py,check_record_ids.py,check-frozen-archives.sh,cargo check -p solidcore --target wasm32-unknown-unknown: all exit 0.--all --goldens:goldens: 283 unit(s), 282 passed, 1 failed. The one iscurve.coniccasegen2235(values.r[4]: 3.776586443654626e-14 -> 3.552713678800501e-14), which differs the same way on unchanged main on that machine (checked onba55b2f71and on7b29ffdb5); this change does not touch it.(2450, 39800); at the head it passes with(0, 0).boolean_api,boolean_no_dangling_vertex_refs,issue_1120_boolean_slitspass. The focused lib tests (topology::proto_topology,boolean::topology_intersector,boolean::merge,kernel::tests) pass: 134.ba55b2f71, together with four other changes on one branch: the whole workspace suite (7181 passed, 113 skipped) and the kernel rig as CI runs it (1081 cases, 803 pass, 0 fail, 15 known-failing, none moved). Not re-run on this head: CI is the gate.Not attached
Not in this PR
🤖 Generated with Claude Code
Summary by CodeRabbit