fix(solid): skip display-cache wires when ACIS parses; real centres

The embedded solid display-cache wires are body-local (unplaced), and
R2013+ AcDs-backed solids used to misparse them into garbage points near
the origin — a clipped region rendered a stray fragment at (0,0,0). When
the ACIS payload parses, the mesh pipeline (fill + feature edges +
isolines, all body-placed) is the authoritative render, so the wires now
only serve as a last resort for unreadable ACIS data.

acadrust bump brings the decoded wireframe section and real reference
points: solids/regions report the file's stored bounding-box centre (or
a geometry-derived one) instead of (0,0,0), which feeds OCS grips,
Position properties and insertion snaps.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Fable 5 committed 2026-07-23 01:13:43 +03:00
1 parent 94609fc54a
commit f1c494b81e
3 files changed
+25 -1

No files matched your search

Generated
+1 -1
View File
@@ -74,7 +74,7 @@ checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618"
[[package]]
name = "acadrust"
version = "0.4.0"
source = "git+https://github.com/OpenAEC-Foundation/acadifc?branch=main#3832a9b6f598405f057e6e4e6d49db65f4d68834"
source = "git+https://github.com/OpenAEC-Foundation/acadifc?branch=main#4ef83a122446504a988ed8ed7904b1c1b5f1b51f"
dependencies = [
"ahash 0.8.12",
"anyhow",
+17
View File
@@ -263,6 +263,23 @@ pub fn fallback_wires(e: &EntityType) -> Option<&[acadrust::entities::Wire]> {
}
}
/// Whether the entity's ACIS payload parses into a SAT document. When it
/// does, the mesh pipeline (fill + feature edges + isolines, all body-placed)
/// is the authoritative render and the embedded display-cache wires must NOT
/// be drawn: they are body-local (unplaced), and for R2013+ AcDs-backed
/// solids the inline wire section misparses into garbage points near the
/// origin. The wires remain useful only as a last resort when the ACIS data
/// itself is unreadable.
pub fn acis_parses(e: &EntityType) -> bool {
match e {
EntityType::Solid3D(s) => s.acis_data.parse().is_some(),
EntityType::Region(r) => r.acis_data.parse().is_some(),
EntityType::Body(b) => b.acis_data.parse().is_some(),
EntityType::Surface(s) => s.acis_data.parse().is_some(),
_ => false,
}
}
/// Run the appropriate `solid3d_tess::tessellate_*` for the entity,
/// returning `None` for non-volume entities or when the kernel fails.
pub fn tessellate_volume(
+7
View File
@@ -1706,6 +1706,13 @@ fn solid_wire_fallback(entity: &EntityType) -> Vec<[f64; 3]> {
if wires.is_empty() {
return vec![];
}
// Parseable ACIS → the mesh pipeline draws the body (placed); the embedded
// display-cache wires are body-local and would render unplaced at the
// origin (garbage for AcDs-backed solids). Only unreadable ACIS falls
// back to them.
if crate::entities::solid3d::acis_parses(entity) {
return vec![];
}
let mut pts: Vec<[f64; 3]> = Vec::new();
for wire in wires {