forked from 1b-agent/opencadstudio-upstream
perf(snap): keep snap/hover responsive on block-heavy drawings
Snap and hover hit-testing scanned the whole model wire set every cursor move; a heavily block-instanced drawing explodes to millions of wires, so this stalled for over a second per move. Add a cached spatial grid (wire_grid) keyed on the geometry epoch and query only the cursor neighbourhood via Scene::hit_test_wires_near. Gate the O(in-range segments squared) intersection passes on the in-range POINT count, not the wire count — a handful of curved wires, each hundreds of tessellated points, blew the quadratic up while the wire count looked modest. Give zero-size entities away from the origin (POINTs) a real cullable AABB, and fall back to a block sub-wire's own world points when its entity bounding box is degenerate. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
f91e45a62a
commit
e1c19d8af3
6 files changed
+313
-15
No files matched your search
@@ -731,7 +731,7 @@ pub(super) fn on_tick(&mut self, t: Instant) -> Task<Message> {
|
||||
{
|
||||
self.tabs[i].scene.model_wires_for_viewport_arc(h, bounds.height)
|
||||
} else {
|
||||
self.tabs[i].scene.hit_test_wires()
|
||||
self.tabs[i].scene.hit_test_wires_near(raw, view_rot, bounds)
|
||||
};
|
||||
// Grip drag has no single rubber-band origin for a perp foot.
|
||||
self.snapper.from_point = None;
|
||||
@@ -853,7 +853,9 @@ pub(super) fn on_tick(&mut self, t: Instant) -> Task<Message> {
|
||||
{
|
||||
self.tabs[i].scene.model_wires_for_viewport_arc(h, bounds.height)
|
||||
} else {
|
||||
self.tabs[i].scene.hit_test_wires()
|
||||
self.tabs[i]
|
||||
.scene
|
||||
.hit_test_wires_near(snap_cursor, view_rot, bounds)
|
||||
};
|
||||
let needs_entity = self.tabs[i]
|
||||
.active_cmd
|
||||
@@ -1347,7 +1349,7 @@ pub(super) fn on_tick(&mut self, t: Instant) -> Task<Message> {
|
||||
{
|
||||
self.tabs[i].scene.model_wires_for_viewport_arc(h, bounds.height)
|
||||
} else {
|
||||
self.tabs[i].scene.hit_test_wires()
|
||||
self.tabs[i].scene.hit_test_wires_near(raw, view_rot, bounds)
|
||||
};
|
||||
self.snapper.grid_spacing = crate::ui::overlay::compute_grid_step(view_rot, bounds);
|
||||
// No rubber-band origin (perp/extension feet don't apply to a free drag).
|
||||
@@ -1801,7 +1803,9 @@ pub(super) fn on_tick(&mut self, t: Instant) -> Task<Message> {
|
||||
{
|
||||
self.tabs[i].scene.model_wires_for_viewport_arc(h, bounds.height)
|
||||
} else {
|
||||
self.tabs[i].scene.hit_test_wires()
|
||||
self.tabs[i]
|
||||
.scene
|
||||
.hit_test_wires_near(snap_cursor, view_rot, bounds)
|
||||
};
|
||||
let needs_tan = self.tabs[i]
|
||||
.active_cmd
|
||||
|
||||
Reference in new issue
Block a user