forked from 1b-agent/opencadstudio-upstream
perf(io,scene): drop redundant purge walk, fuse world-offset scan
Phase 1.1: resolve_xrefs now purges corrupt entities inline as it merges each xref and returns the dropped count, removing the second full-document purge_corrupt_entities walk in the FileOpened handler. Every xref-bearing open saves one O(N) entities() pass. Phase 2.4: split compute_world_offset into offset_prep / offset_centroid / world_offset_from_centers; centroid accumulation now rides the existing cache-handle walk in build_derived_caches. Two O(N) entity walks collapse into one, with identical MSPACE-membership filtering preserved. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
b466747074
commit
3098523b8d
7 files changed
+149
-120
No files matched your search
+1
-1
@@ -256,7 +256,7 @@ fn finite_vec3(v: &acadrust::types::Vector3) -> bool {
|
||||
}
|
||||
|
||||
/// Returns true if the entity looks like parser garbage and should be dropped.
|
||||
fn is_entity_corrupt(e: &EntityType) -> bool {
|
||||
pub(crate) fn is_entity_corrupt(e: &EntityType) -> bool {
|
||||
use acadrust::entities::EntityType as E;
|
||||
// Reject polylines at or above this vertex count. Even valid drawings
|
||||
// rarely use this many — and parser desync produces exactly-100_000-vertex
|
||||
|
||||
+20
-5
@@ -35,8 +35,12 @@ pub struct XrefInfo {
|
||||
/// `base_dir`, and populate each xref block with entities from the
|
||||
/// referenced file.
|
||||
///
|
||||
/// Returns a list of [`XrefInfo`] describing each xref block found.
|
||||
pub fn resolve_xrefs(doc: &mut CadDocument, base_dir: &Path) -> Vec<XrefInfo> {
|
||||
/// Returns a list of [`XrefInfo`] describing each xref block found, plus the
|
||||
/// number of corrupt xref entities dropped during merge. Purging happens
|
||||
/// inline as each xref's entities are merged — xref content is parser output
|
||||
/// just like the host doc, so it gets the same corrupt-entity guard. Folding
|
||||
/// it in here avoids a second full-document `entities()` walk after resolve.
|
||||
pub fn resolve_xrefs(doc: &mut CadDocument, base_dir: &Path) -> (Vec<XrefInfo>, usize) {
|
||||
// Auto-resolve every xref — frustum + LOD culling keep GPU cost bounded.
|
||||
let xref_entries: Vec<(String, String, Handle)> = doc
|
||||
.block_records
|
||||
@@ -46,6 +50,7 @@ pub fn resolve_xrefs(doc: &mut CadDocument, base_dir: &Path) -> Vec<XrefInfo> {
|
||||
.collect();
|
||||
|
||||
let mut result = Vec::new();
|
||||
let mut dropped = 0usize;
|
||||
|
||||
for (block_name, raw_path, br_handle) in xref_entries {
|
||||
let resolved = resolve_path(&raw_path, base_dir);
|
||||
@@ -56,7 +61,7 @@ pub fn resolve_xrefs(doc: &mut CadDocument, base_dir: &Path) -> Vec<XrefInfo> {
|
||||
Err(_) => XrefStatus::NotFound,
|
||||
Ok(xref_doc) => {
|
||||
ensure_block_entities(doc, &block_name);
|
||||
merge_xref_into_block(doc, &block_name, br_handle, xref_doc);
|
||||
dropped += merge_xref_into_block(doc, &block_name, br_handle, xref_doc);
|
||||
XrefStatus::Loaded
|
||||
}
|
||||
},
|
||||
@@ -71,7 +76,7 @@ pub fn resolve_xrefs(doc: &mut CadDocument, base_dir: &Path) -> Vec<XrefInfo> {
|
||||
});
|
||||
}
|
||||
|
||||
result
|
||||
(result, dropped)
|
||||
}
|
||||
|
||||
/// Try to build an absolute path from a raw xref path string.
|
||||
@@ -135,12 +140,13 @@ fn ensure_block_entities(doc: &mut CadDocument, block_name: &str) {
|
||||
/// — which doesn't know about the xref's layers — and silently falls
|
||||
/// back to WHITE / 1 px line weight. AutoCAD's BIND command uses the
|
||||
/// same naming scheme.
|
||||
/// Returns the number of corrupt entities skipped during the merge.
|
||||
fn merge_xref_into_block(
|
||||
doc: &mut CadDocument,
|
||||
xref_block_name: &str,
|
||||
br_handle: Handle,
|
||||
xref_doc: CadDocument,
|
||||
) {
|
||||
) -> usize {
|
||||
let prefix = xref_block_name;
|
||||
|
||||
// Carry the xref's INSUNITS onto the host BlockRecord. Used at INSERT
|
||||
@@ -223,7 +229,15 @@ fn merge_xref_into_block(
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
let mut dropped = 0usize;
|
||||
for mut entity in entities {
|
||||
// Drop parser-garbage entities (bad normals / vertex counts / inf
|
||||
// coords) before they enter the host doc — they trigger huge
|
||||
// allocations and unbounded recursion in the wire pipeline.
|
||||
if super::is_entity_corrupt(&entity) {
|
||||
dropped += 1;
|
||||
continue;
|
||||
}
|
||||
// Remap layer / linetype names so the host's resolver hits the
|
||||
// copies we just inserted.
|
||||
{
|
||||
@@ -262,6 +276,7 @@ fn merge_xref_into_block(
|
||||
set_handle(&mut entity, Handle::NULL);
|
||||
let _ = doc.add_entity(entity);
|
||||
}
|
||||
dropped
|
||||
}
|
||||
|
||||
fn is_sentinel_linetype(name: &str) -> bool {
|
||||
|
||||
Reference in new issue
Block a user