| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
@brunoperdigao the recent work on GPU snap candidate selection is great, but there are still some perfomance issues in section view. I opened a PR instead of an issue to offer some possible performance improvements, in the hope it could be helpful. The result is not yet fluid, but at least workable for some specific usecase. |
Sorry, something went wrong.
intersect_edges_v2 runs thousands of times per mouse move under the snapping tools and is also used for wall junctions in tool/model.py. On 3-element operands, numpy spends far more time in its dispatch machinery (normalize_axis_tuple, moveaxis) than on the arithmetic itself, so np.cross / np.linalg.norm / np.dot dominate the profile. Replace them with explicit scalar forms in this function only. They keep float64 precision, so results are unchanged: 3.8x faster on the function (68.95us -> 18.16us measured). Characterization tests were written against the previous implementation first and pin the closest-points results for skew, crossing, parallel, collinear, 2D and unnormalised-direction inputs, so the refactor is verified to be behaviour-preserving. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ray_cast_by_proximity copied obj.matrix_world once per vertex and twice per edge. The matrix cannot change while the loops run, so copy it once before them instead. Pure code motion: the copy is still taken (the loops must not alias the object's live matrix) and the None case is preserved for the custom_bmesh callers that pass obj=None. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The per-edge loop in ray_cast_by_proximity calls Cad.intersect_edges_v2 for every edge of the object under the cursor, and that call dominates the loop. Most edges are nowhere near the cursor and cannot pass its threshold test. Add a conservative bound: every point of an edge lies within half the edge length of its midpoint, whose distance to the ray the loop already computes for the Edge Center snap, so by the triangle inequality no point can be nearer than midpoint_distance - edge_length / 2. When that lower bound reaches the snap threshold the intersection cannot produce a hit. The predicate never rejects an edge that could snap, so snapping results are unchanged. Tested with a randomised search that samples points along every rejected edge and asserts none lies within the threshold. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
@carlopav Thanks for pointing that out. I'll take a look |
Sorry, something went wrong.
|
@carlopav I went through another path. I realized I forgot to integrate the cut geometry snaps to the new GPU system, and it seems to solve the issue. Could you please test and see how it goes. I've committed to the v0.8.0 branch |
Sorry, something went wrong.
|
@brunoperdigao I cannot find your new commits anywhere, are you sure you pushed them? |
Sorry, something went wrong.
Sorry, don't know what happened. Here it is now: https://github.com/IfcOpenShell/IfcOpenShell/commits/v0.8.0/ |
Sorry, something went wrong.
|
@brunoperdigao now that's fantastic! snap in section works like a charm on sectioned elements. Still not able to snap 2d geometry (a bed with a Curve2d representation over a floor) but that's another topic. I'd close the PR if you agree: the only possible commit is the first (71cfa36), but it doesn't probably makes much sense if the snap already works good... |
Sorry, something went wrong.
|
@carlopav Let me take a closer look at the commits later before you close. Since I was working with another approach I didn't actually take the time to see what parts can be implemented as well. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Context
The GPU snap detection that landed in 4cb6ce703..2b429dc60 replaces object discovery. Raycast.ray_cast_by_proximity survives it and is still the only CPU path that turns a detected object into Vertex / Edge Center / Edge snaps: detect_snapping_points calls it for the object under the cursor, and in plan/section views once per visible element carrying cut or fill decorator data.
These three changes reduce the cost of that function and of Cad.intersect_edges_v2, which it calls once per edge. They are independent of how candidates are found, so they apply equally before and after the GPU work.
Changes
One commit each, each independently revertible:
1. Speed up Cad.intersect_edges_v2. Replace np.cross / np.linalg.norm / np.dot with explicit scalar arithmetic. On 3-element operands numpy spends far more time in its dispatch machinery (normalize_axis_tuple, moveaxis) than on the arithmetic itself. Float64 throughout, so results are unchanged. Also used by wall junctions in tool/model.py.
2. Hoist matrix_world out of the proximity loops. It was copied once per vertex and twice per edge, and cannot change while the loops run. Pure code motion: the copy is still taken, and the obj=None path used by the custom_bmesh callers is preserved.
3. Skip the line-line intersection for edges that cannot snap. Every point of an edge lies within half its length of its midpoint, whose distance to the ray the loop already computes for the Edge Center snap. By the triangle inequality no point can be nearer to the ray than midpoint_distance - edge_length / 2; once that lower bound reaches the snap threshold, intersect_edges_v2 cannot produce a hit. The predicate never rejects an edge that could snap, so snapping results are unchanged.
Measurements
Being explicit about what is and isn't measured:
Where I would expect them to still matter most is plan and section views: the cut/fill block in detect_snapping_points came through the rewrite unchanged and still iterates every visible mesh element with cache data, rebuilding a bmesh per object per mouse move.
Tests
test/tool/test_cad.py test/tool/test_raycast.py — 23 passed. black --line-length 120 clean.
Related
Supersedes #9004, which fixed the object-origin sort in ray_cast_and_get_closest_to_camera_snaps. The GPU rewrite left that function in the file but nothing calls it any more, so the heuristic it corrected is no longer on a live path. I'll close #9004.
🤖 Generated with Claude Code
Real work comparison
Pre fix


After fix