forked from 1b-agent/opencadstudio-upstream
refactor(render): reuse block_has_hatch in synced_hatch_models
The hatch-free-block skip added in the previous commit duplicated the existing `block_has_hatch` helper (already used by `insert_hatches_for_click`). Drop the parallel `block_contains_hatch` and call the shared, memoised helper instead — same result, one implementation. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
0ce918da68
commit
845194e05b
1 file changed
+7
-63
+7
-63
@@ -409,55 +409,6 @@ impl Scene {
|
||||
self.bump_geometry();
|
||||
}
|
||||
|
||||
/// Whether a block definition holds at least one HATCH, directly or through
|
||||
/// a nested INSERT. Memoized by block-record handle — `None` marks a block
|
||||
/// currently being visited so a cyclic block reference resolves to `false`
|
||||
/// instead of recursing forever. Lets `synced_hatch_models` skip the costly
|
||||
/// explode of hatch-free blocks (a read-only type scan, no entity clones).
|
||||
fn block_contains_hatch(
|
||||
&self,
|
||||
block_handle: Handle,
|
||||
memo: &mut HashMap<Handle, Option<bool>>,
|
||||
) -> bool {
|
||||
if let Some(v) = memo.get(&block_handle) {
|
||||
return v.unwrap_or(false);
|
||||
}
|
||||
memo.insert(block_handle, None);
|
||||
let mut has = false;
|
||||
if let Some(br) = self
|
||||
.document
|
||||
.block_records
|
||||
.iter()
|
||||
.find(|b| b.handle == block_handle)
|
||||
{
|
||||
for &h in &br.entity_handles {
|
||||
match self.document.get_entity(h) {
|
||||
Some(EntityType::Hatch(_)) => {
|
||||
has = true;
|
||||
break;
|
||||
}
|
||||
Some(EntityType::Insert(nins)) => {
|
||||
let nbh = self
|
||||
.document
|
||||
.block_records
|
||||
.iter()
|
||||
.find(|b| b.name.eq_ignore_ascii_case(&nins.block_name))
|
||||
.map(|b| b.handle);
|
||||
if let Some(nbh) = nbh {
|
||||
if self.block_contains_hatch(nbh, memo) {
|
||||
has = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
memo.insert(block_handle, Some(has));
|
||||
has
|
||||
}
|
||||
|
||||
pub(super) fn synced_hatch_models(&self) -> Vec<HatchModel> {
|
||||
let layout_block = self.current_layout_block_handle();
|
||||
|
||||
@@ -549,10 +500,11 @@ impl Scene {
|
||||
// to scan the result for hatch fills. On xref-heavy drawings whose
|
||||
// blocks hold thousands of solids and NO hatches, that cloned ~all block
|
||||
// content on every open for nothing (~20 s on a 5-xref BIM aggregate).
|
||||
// Pre-scan each block's entity types (no clone) and skip the explode for
|
||||
// blocks that contain no hatch, transitively. Blocks that DO contain a
|
||||
// hatch still explode exactly as before, so the output is unchanged.
|
||||
let mut hatch_block_memo: HashMap<Handle, Option<bool>> = HashMap::default();
|
||||
// Skip the explode for blocks with no hatch (transitively) via the same
|
||||
// memoised `block_has_hatch` scan the pick path uses. Blocks that DO
|
||||
// contain a hatch still explode exactly as before, so output is unchanged.
|
||||
let mut hatch_block_memo: std::collections::HashMap<String, bool> =
|
||||
std::collections::HashMap::new();
|
||||
for entity in self.document.entities() {
|
||||
let EntityType::Insert(ins) = entity else {
|
||||
continue;
|
||||
@@ -567,16 +519,8 @@ impl Scene {
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if let Some(bh) = self
|
||||
.document
|
||||
.block_records
|
||||
.iter()
|
||||
.find(|b| b.name.eq_ignore_ascii_case(&ins.block_name))
|
||||
.map(|b| b.handle)
|
||||
{
|
||||
if !self.block_contains_hatch(bh, &mut hatch_block_memo) {
|
||||
continue;
|
||||
}
|
||||
if !self.block_has_hatch(&ins.block_name, &mut hatch_block_memo) {
|
||||
continue;
|
||||
}
|
||||
let selected = self.selected.contains(&ins.common.handle);
|
||||
// XCLIP: clip this insert's exploded hatch fills to the boundary,
|
||||
|
||||
Reference in new issue
Block a user