From 65910d1cad0d5f4a78b8b4672e54b15f1416bd76 Mon Sep 17 00:00:00 2001 From: ramox81 <184937705+ramox81@users.noreply.github.com> Date: Fri, 9 Oct 2026 18:32:35 +0300 Subject: [PATCH] Count a region's loops from its modeler edges The surface extrusion, the extrusion along a path, revolve history and embedded profiles refused a region whenever it had more than one display wire, which a region of several edges always has. They now refuse only a region with holes, and a region's loops for a solid extrusion come from its modeler edges. Co-Authored-By: Claude Opus 5.5 --- src/scene/model/sweep_model.rs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/scene/model/sweep_model.rs b/src/scene/model/sweep_model.rs index 5e41f3f72..16b66c16a 100644 --- a/src/scene/model/sweep_model.rs +++ b/src/scene/model/sweep_model.rs @@ -68,7 +68,10 @@ pub fn extrusion_profile_of(entity: &EntityType) -> Option<(Profile, bool)> { /// edges (its display wires hold one wire per edge), a lone closed edge split /// as a closed curve is. fn region_loop(entity: &EntityType) -> Option { - let EntityType::Region(_) = entity else { return None }; + let EntityType::Region(region) = entity else { return None }; + if !region.acis_data.has_data() { + return None; + } let (plane, loops, _) = super::presspull_model::profile_geometry(entity)?; let [boundary] = loops.as_slice() else { return None }; let single = boundary.len() == 1; @@ -80,6 +83,11 @@ fn region_loop(entity: &EntityType) -> Option { Some(Profile { plane, pieces }) } +/// Whether a region has more than one boundary loop. +fn region_with_holes(entity: &EntityType) -> bool { + matches!(entity, EntityType::Region(_)) && region_profiles(entity).is_some_and(|(_, loops)| loops.len() > 1) +} + fn profile_pieces(curve: &Curve, closed: bool) -> Option> { let pieces = match curve { Curve::Polyline(_) => curve.segments(), @@ -182,10 +190,16 @@ fn planar_polygon_entity(entity: &EntityType) -> Option { )) } +/// A region's boundary loops: from its modeler edges when it has them (its +/// display wires then hold one wire per edge), else from its wires. fn region_profiles(entity: &EntityType) -> Option<(Plane, Vec>)> { let EntityType::Region(region) = entity else { return None; }; + if region.acis_data.has_data() { + let (plane, loops, _) = super::presspull_model::profile_geometry(entity)?; + return (!loops.is_empty()).then_some((plane, loops)); + } let plane = planar_polygon_entity(entity)?.plane; let mut profiles = Vec::with_capacity(region.wires.len()); for wire in ®ion.wires { @@ -313,7 +327,7 @@ pub fn extruded_surface( direction: [f64; 3], taper_angle: f64, ) -> Option { - if matches!(entity, EntityType::Region(region) if region.wires.len() > 1) { + if region_with_holes(entity) { return None; } let (profile, _) = extrusion_profile_of(entity)?; @@ -330,7 +344,7 @@ pub fn extruded_along_path( path: &EntityType, taper_angle: f64, ) -> Option { - if matches!(entity, EntityType::Region(region) if region.wires.len() > 1) { + if region_with_holes(entity) { if taper_angle.abs() > 1e-12 { return None; } @@ -493,7 +507,7 @@ pub fn revolve_history( if !angle.is_finite() || angle.abs() <= 1e-12 || !start_angle.is_finite() - || matches!(entity, EntityType::Region(region) if region.wires.len() > 1) + || region_with_holes(entity) { return None; } @@ -649,7 +663,7 @@ pub fn embedded_path(entity: &EntityType) -> Option { } fn embedded_planar_entity(entity: &EntityType) -> Option<(EmbeddedEntity, [f64; 16])> { - if matches!(entity, EntityType::Region(region) if region.wires.len() > 1) { + if region_with_holes(entity) { return None; } if !matches!(entity, EntityType::Polyline3D(_)) {