forked from 1b-agent/opencadstudio-upstream
perf: keep heavy work off UI thread
This commit is contained in:
1 parent
12bf126646
commit
deec48ad99
75 files changed
+11702
-518
No files matched your search
@@ -0,0 +1,99 @@
|
||||
//! Shared broad phase for interactive modify commands.
|
||||
//!
|
||||
//! The scene already narrows the cursor pick. Commands still need fast access
|
||||
//! to the picked analytic entity and, for intersection-heavy operations such
|
||||
//! as TRIM, to nearby boundary entities. Keeping this compact command-local
|
||||
//! index avoids cloning/scanning the complete drawing on every mouse move.
|
||||
|
||||
use acadrust::{EntityType, Handle};
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
use crate::scene::convert::tess::entity_world_aabb_f64;
|
||||
use crate::scene::pick::quadtree::QuadTree;
|
||||
|
||||
pub(super) struct ModifyEntityIndex {
|
||||
by_handle: FxHashMap<Handle, usize>,
|
||||
tree: Option<QuadTree>,
|
||||
unbounded: Vec<Handle>,
|
||||
}
|
||||
|
||||
impl ModifyEntityIndex {
|
||||
pub(super) fn build(entities: &[EntityType]) -> Self {
|
||||
let mut by_handle = FxHashMap::default();
|
||||
let mut bounded = Vec::new();
|
||||
let mut unbounded = Vec::new();
|
||||
let mut world = [
|
||||
f64::INFINITY,
|
||||
f64::INFINITY,
|
||||
f64::NEG_INFINITY,
|
||||
f64::NEG_INFINITY,
|
||||
];
|
||||
|
||||
for (index, entity) in entities.iter().enumerate() {
|
||||
let handle = entity.common().handle;
|
||||
by_handle.insert(handle, index);
|
||||
if let Some(aabb) = entity_world_aabb_f64(entity) {
|
||||
world[0] = world[0].min(aabb[0]);
|
||||
world[1] = world[1].min(aabb[1]);
|
||||
world[2] = world[2].max(aabb[2]);
|
||||
world[3] = world[3].max(aabb[3]);
|
||||
bounded.push((handle, aabb));
|
||||
} else {
|
||||
unbounded.push(handle);
|
||||
}
|
||||
}
|
||||
|
||||
let tree = if bounded.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let span = (world[2] - world[0]).max(world[3] - world[1]).max(1.0);
|
||||
let pad = span * 1.0e-9 + 1.0e-6;
|
||||
let mut tree = QuadTree::new([
|
||||
world[0] - pad,
|
||||
world[1] - pad,
|
||||
world[2] + pad,
|
||||
world[3] + pad,
|
||||
]);
|
||||
for (handle, aabb) in bounded {
|
||||
tree.insert(handle, aabb);
|
||||
}
|
||||
Some(tree)
|
||||
};
|
||||
|
||||
Self {
|
||||
by_handle,
|
||||
tree,
|
||||
unbounded,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn get<'a>(
|
||||
&self,
|
||||
entities: &'a [EntityType],
|
||||
handle: Handle,
|
||||
) -> Option<&'a EntityType> {
|
||||
self.by_handle
|
||||
.get(&handle)
|
||||
.and_then(|index| entities.get(*index))
|
||||
}
|
||||
|
||||
pub(super) fn nearby_handles(
|
||||
&self,
|
||||
entities: &[EntityType],
|
||||
handle: Handle,
|
||||
) -> Option<FxHashSet<Handle>> {
|
||||
let entity = self.get(entities, handle)?;
|
||||
let aabb = entity_world_aabb_f64(entity)?;
|
||||
let span = (aabb[2] - aabb[0]).max(aabb[3] - aabb[1]).max(1.0);
|
||||
let pad = span * 1.0e-10 + 1.0e-7;
|
||||
let query = [aabb[0] - pad, aabb[1] - pad, aabb[2] + pad, aabb[3] + pad];
|
||||
let mut handles: FxHashSet<Handle> = self
|
||||
.tree
|
||||
.as_ref()
|
||||
.map(|tree| tree.query_rect(query).into_iter().collect())
|
||||
.unwrap_or_default();
|
||||
handles.extend(self.unbounded.iter().copied());
|
||||
Some(handles)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user