refactor(entities): Solid3D/Region/Body accessor trio in entities/solid3d.rs
The same three-arm `match entity { Solid3D | Region | Body }` block
appeared at five callsites — twice in tessellate.rs (point_of_reference,
fallback wires) and three times in scene/mod.rs (mesh tess dispatch,
apply_grip pre/post position).
Add three accessors in entities/solid3d.rs:
point_of_reference(e) → Option<&Vector3>
fallback_wires(e) → Option<&[Wire]>
tessellate_volume(e, color, facet_res) → Option<MeshLodSet>
Callsites shrink from 5–8 lines to one call. The apply_grip path
collapses two parallel pre/post matches plus the entity-list `matches!`
guard.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
5da32ff202
commit
e66905e9b1
3 changed files with 74 additions and 79 deletions
|
|
@ -251,3 +251,52 @@ impl PropertyEditable for Body {
|
||||||
|
|
||||||
fn apply_geom_prop(&mut self, _field: &str, _value: &str) {}
|
fn apply_geom_prop(&mut self, _field: &str, _value: &str) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Accessors for the Solid3D / Region / Body trio ─────────────────────────
|
||||||
|
//
|
||||||
|
// These three entity types share a common subset of fields (ACIS data
|
||||||
|
// + point_of_reference + wires fallback). Code that needs to treat them
|
||||||
|
// uniformly (mesh tess dispatch, fallback wires, grip translate) used
|
||||||
|
// to repeat a three-arm `match entity` block at every callsite — the
|
||||||
|
// helpers below collapse those to a single call.
|
||||||
|
|
||||||
|
use acadrust::{types::Vector3, EntityType};
|
||||||
|
use crate::scene::mesh_model::MeshLodSet;
|
||||||
|
use crate::scene::solid3d_tess;
|
||||||
|
|
||||||
|
/// `point_of_reference` of an ACIS-backed volume entity, if applicable.
|
||||||
|
pub fn point_of_reference(e: &EntityType) -> Option<&Vector3> {
|
||||||
|
match e {
|
||||||
|
EntityType::Solid3D(s) => Some(&s.point_of_reference),
|
||||||
|
EntityType::Region(r) => Some(&r.point_of_reference),
|
||||||
|
EntityType::Body(b) => Some(&b.point_of_reference),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Pre-stored edge-wire fallback list (used when the SAT/SAB kernel
|
||||||
|
/// can't produce a mesh — drawings authored by SOLVIEW / 3DPLOT carry
|
||||||
|
/// these explicitly).
|
||||||
|
pub fn fallback_wires(e: &EntityType) -> Option<&[acadrust::entities::Wire]> {
|
||||||
|
match e {
|
||||||
|
EntityType::Solid3D(s) => Some(&s.wires),
|
||||||
|
EntityType::Region(r) => Some(&r.wires),
|
||||||
|
EntityType::Body(b) => Some(&b.wires),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run the appropriate `solid3d_tess::tessellate_*` for the entity,
|
||||||
|
/// returning `None` for non-volume entities or when the kernel fails.
|
||||||
|
pub fn tessellate_volume(
|
||||||
|
e: &EntityType,
|
||||||
|
color: [f32; 4],
|
||||||
|
facet_res: f64,
|
||||||
|
) -> Option<MeshLodSet> {
|
||||||
|
match e {
|
||||||
|
EntityType::Solid3D(s) => solid3d_tess::tessellate_solid3d(s, color, facet_res),
|
||||||
|
EntityType::Region(r) => solid3d_tess::tessellate_region(r, color, facet_res),
|
||||||
|
EntityType::Body(b) => solid3d_tess::tessellate_body(b, color, facet_res),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -213,13 +213,8 @@ pub fn build_derived_caches(doc: &CadDocument) -> DerivedCaches {
|
||||||
.filter_map(|&handle| {
|
.filter_map(|&handle| {
|
||||||
let e = doc.get_entity(handle)?;
|
let e = doc.get_entity(handle)?;
|
||||||
let color = tess_util::aci_to_rgba(&e.common().color);
|
let color = tess_util::aci_to_rgba(&e.common().color);
|
||||||
let model = match e {
|
crate::entities::solid3d::tessellate_volume(e, color, facet_res)
|
||||||
EntityType::Solid3D(s) => solid3d_tess::tessellate_solid3d(s, color, facet_res),
|
.map(|m| (handle, m))
|
||||||
EntityType::Region(r) => solid3d_tess::tessellate_region(r, color, facet_res),
|
|
||||||
EntityType::Body(b) => solid3d_tess::tessellate_body(b, color, facet_res),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
model.map(|m| (handle, m))
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|
@ -2377,20 +2372,14 @@ impl Scene {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let facet_res = self.document.header.facet_resolution;
|
let facet_res = self.document.header.facet_resolution;
|
||||||
let mesh_seed = match &entity {
|
let mesh_seed = if matches!(
|
||||||
EntityType::Solid3D(s3d) => {
|
&entity,
|
||||||
|
EntityType::Solid3D(_) | EntityType::Region(_) | EntityType::Body(_)
|
||||||
|
) {
|
||||||
let color = self.render_style(&entity).0;
|
let color = self.render_style(&entity).0;
|
||||||
solid3d_tess::tessellate_solid3d(s3d, color, facet_res)
|
crate::entities::solid3d::tessellate_volume(&entity, color, facet_res)
|
||||||
}
|
} else {
|
||||||
EntityType::Region(r) => {
|
None
|
||||||
let color = self.render_style(&entity).0;
|
|
||||||
solid3d_tess::tessellate_region(r, color, facet_res)
|
|
||||||
}
|
|
||||||
EntityType::Body(b) => {
|
|
||||||
let color = self.render_style(&entity).0;
|
|
||||||
solid3d_tess::tessellate_body(b, color, facet_res)
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Auto-create an ImageDefinition object for new RasterImage entities
|
// Auto-create an ImageDefinition object for new RasterImage entities
|
||||||
|
|
@ -3230,15 +3219,8 @@ impl Scene {
|
||||||
self.meshes = entries
|
self.meshes = entries
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.filter_map(|(handle, entity, color)| {
|
.filter_map(|(handle, entity, color)| {
|
||||||
let model = match &entity {
|
crate::entities::solid3d::tessellate_volume(&entity, color, facet_res)
|
||||||
EntityType::Solid3D(s) => {
|
.map(|m| (handle, m))
|
||||||
solid3d_tess::tessellate_solid3d(s, color, facet_res)
|
|
||||||
}
|
|
||||||
EntityType::Region(r) => solid3d_tess::tessellate_region(r, color, facet_res),
|
|
||||||
EntityType::Body(b) => solid3d_tess::tessellate_body(b, color, facet_res),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
model.map(|m| (handle, m))
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|
@ -3642,24 +3624,11 @@ impl Scene {
|
||||||
// For Solid3D / Region / Body, record the old point_of_reference so we
|
// For Solid3D / Region / Body, record the old point_of_reference so we
|
||||||
// can translate the pre-tessellated MeshModel by the same delta after
|
// can translate the pre-tessellated MeshModel by the same delta after
|
||||||
// the grip is applied (the ACIS data itself is not modified).
|
// the grip is applied (the ACIS data itself is not modified).
|
||||||
let old_por: Option<[f64; 3]> = match self.document.get_entity(handle) {
|
let old_por: Option<[f64; 3]> = self
|
||||||
Some(EntityType::Solid3D(s)) => Some([
|
.document
|
||||||
s.point_of_reference.x,
|
.get_entity(handle)
|
||||||
s.point_of_reference.y,
|
.and_then(crate::entities::solid3d::point_of_reference)
|
||||||
s.point_of_reference.z,
|
.map(|p| [p.x, p.y, p.z]);
|
||||||
]),
|
|
||||||
Some(EntityType::Region(r)) => Some([
|
|
||||||
r.point_of_reference.x,
|
|
||||||
r.point_of_reference.y,
|
|
||||||
r.point_of_reference.z,
|
|
||||||
]),
|
|
||||||
Some(EntityType::Body(b)) => Some([
|
|
||||||
b.point_of_reference.x,
|
|
||||||
b.point_of_reference.y,
|
|
||||||
b.point_of_reference.z,
|
|
||||||
]),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(entity) = self.document.get_entity_mut(handle) {
|
if let Some(entity) = self.document.get_entity_mut(handle) {
|
||||||
dispatch::apply_grip(entity, grip_id, apply);
|
dispatch::apply_grip(entity, grip_id, apply);
|
||||||
|
|
@ -3667,24 +3636,11 @@ impl Scene {
|
||||||
|
|
||||||
// Translate MeshModel vertices by the same delta the grip applied.
|
// Translate MeshModel vertices by the same delta the grip applied.
|
||||||
if let Some(old) = old_por {
|
if let Some(old) = old_por {
|
||||||
let new_por: Option<[f64; 3]> = match self.document.get_entity(handle) {
|
let new_por: Option<[f64; 3]> = self
|
||||||
Some(EntityType::Solid3D(s)) => Some([
|
.document
|
||||||
s.point_of_reference.x,
|
.get_entity(handle)
|
||||||
s.point_of_reference.y,
|
.and_then(crate::entities::solid3d::point_of_reference)
|
||||||
s.point_of_reference.z,
|
.map(|p| [p.x, p.y, p.z]);
|
||||||
]),
|
|
||||||
Some(EntityType::Region(r)) => Some([
|
|
||||||
r.point_of_reference.x,
|
|
||||||
r.point_of_reference.y,
|
|
||||||
r.point_of_reference.z,
|
|
||||||
]),
|
|
||||||
Some(EntityType::Body(b)) => Some([
|
|
||||||
b.point_of_reference.x,
|
|
||||||
b.point_of_reference.y,
|
|
||||||
b.point_of_reference.z,
|
|
||||||
]),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
if let Some(new) = new_por {
|
if let Some(new) = new_por {
|
||||||
let dx = (new[0] - old[0]) as f32;
|
let dx = (new[0] - old[0]) as f32;
|
||||||
let dy = (new[1] - old[1]) as f32;
|
let dy = (new[1] - old[1]) as f32;
|
||||||
|
|
|
||||||
|
|
@ -413,13 +413,7 @@ pub fn tessellate(
|
||||||
let mut wm = WireModel::solid(name, wire_pts, color, selected);
|
let mut wm = WireModel::solid(name, wire_pts, color, selected);
|
||||||
// Add insertion snap at point_of_reference.
|
// Add insertion snap at point_of_reference.
|
||||||
let [ox, oy, oz] = world_offset;
|
let [ox, oy, oz] = world_offset;
|
||||||
let por = match entity {
|
if let Some(p) = crate::entities::solid3d::point_of_reference(entity) {
|
||||||
EntityType::Solid3D(s) => Some(&s.point_of_reference),
|
|
||||||
EntityType::Region(r) => Some(&r.point_of_reference),
|
|
||||||
EntityType::Body(b) => Some(&b.point_of_reference),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
if let Some(p) = por {
|
|
||||||
let sp = Vec3::new((p.x - ox) as f32, (p.y - oy) as f32, (p.z - oz) as f32);
|
let sp = Vec3::new((p.x - ox) as f32, (p.y - oy) as f32, (p.z - oz) as f32);
|
||||||
wm.snap_pts.push((sp, SnapHint::Insertion));
|
wm.snap_pts.push((sp, SnapHint::Insertion));
|
||||||
}
|
}
|
||||||
|
|
@ -632,13 +626,9 @@ fn fallback_geometry(entity: &EntityType, world_offset: [f64; 3]) -> Geometry {
|
||||||
/// produces no mesh (e.g. binary SAB data or unsupported geometry).
|
/// produces no mesh (e.g. binary SAB data or unsupported geometry).
|
||||||
fn solid_wire_fallback(entity: &EntityType, world_offset: [f64; 3]) -> Vec<[f32; 3]> {
|
fn solid_wire_fallback(entity: &EntityType, world_offset: [f64; 3]) -> Vec<[f32; 3]> {
|
||||||
let [ox, oy, oz] = world_offset;
|
let [ox, oy, oz] = world_offset;
|
||||||
let wires: &[acadrust::entities::Wire] = match entity {
|
let Some(wires) = crate::entities::solid3d::fallback_wires(entity) else {
|
||||||
EntityType::Solid3D(s) => &s.wires,
|
return vec![];
|
||||||
EntityType::Region(r) => &r.wires,
|
|
||||||
EntityType::Body(b) => &b.wires,
|
|
||||||
_ => return vec![],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if wires.is_empty() {
|
if wires.is_empty() {
|
||||||
return vec![];
|
return vec![];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue