forked from 1b-agent/opencadstudio-upstream
Read a one-loop region's profile from its exact edges
A region keeps one display wire per edge, so a region of several edges gave no polygon and could not be extruded (solid or surface), and a circle region was extruded from its display polygon. Profiles of a region with one boundary loop now come from the region's modeler edges. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2192baba02
commit
8fc4f42a4d
1 file changed
+24
-5
@@ -32,6 +32,9 @@ pub struct Profile {
|
|||||||
/// is handed over as the arcs it is made of rather than as one curve with
|
/// is handed over as the arcs it is made of rather than as one curve with
|
||||||
/// nowhere for the sweep to start.
|
/// nowhere for the sweep to start.
|
||||||
pub fn profile_of(entity: &EntityType) -> Option<Profile> {
|
pub fn profile_of(entity: &EntityType) -> Option<Profile> {
|
||||||
|
if let Some(profile) = region_loop(entity) {
|
||||||
|
return (profile.pieces.len() >= 3).then_some(profile);
|
||||||
|
}
|
||||||
let planar = entity_curve(entity).or_else(|| planar_polygon_entity(entity))?;
|
let planar = entity_curve(entity).or_else(|| planar_polygon_entity(entity))?;
|
||||||
if !planar.curve.is_closed() {
|
if !planar.curve.is_closed() {
|
||||||
return None;
|
return None;
|
||||||
@@ -46,6 +49,9 @@ pub fn profile_of(entity: &EntityType) -> Option<Profile> {
|
|||||||
/// An entity-level planar curve suitable for either a solid profile or an
|
/// An entity-level planar curve suitable for either a solid profile or an
|
||||||
/// open surface profile.
|
/// open surface profile.
|
||||||
pub fn extrusion_profile_of(entity: &EntityType) -> Option<(Profile, bool)> {
|
pub fn extrusion_profile_of(entity: &EntityType) -> Option<(Profile, bool)> {
|
||||||
|
if let Some(profile) = region_loop(entity) {
|
||||||
|
return Some((profile, true));
|
||||||
|
}
|
||||||
let planar = entity_curve(entity).or_else(|| planar_polygon_entity(entity))?;
|
let planar = entity_curve(entity).or_else(|| planar_polygon_entity(entity))?;
|
||||||
let closed = planar.curve.is_closed();
|
let closed = planar.curve.is_closed();
|
||||||
let pieces = profile_pieces(&planar.curve, closed)?;
|
let pieces = profile_pieces(&planar.curve, closed)?;
|
||||||
@@ -58,6 +64,22 @@ pub fn extrusion_profile_of(entity: &EntityType) -> Option<(Profile, bool)> {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A region of one boundary loop as that loop, read from the region's exact
|
||||||
|
/// 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<Profile> {
|
||||||
|
let EntityType::Region(_) = entity else { return None };
|
||||||
|
let (plane, loops, _) = super::presspull_model::profile_geometry(entity)?;
|
||||||
|
let [boundary] = loops.as_slice() else { return None };
|
||||||
|
let single = boundary.len() == 1;
|
||||||
|
let pieces = boundary
|
||||||
|
.iter()
|
||||||
|
.map(|piece| profile_pieces(piece, single))
|
||||||
|
.collect::<Option<Vec<_>>>()?
|
||||||
|
.concat();
|
||||||
|
Some(Profile { plane, pieces })
|
||||||
|
}
|
||||||
|
|
||||||
fn profile_pieces(curve: &Curve, closed: bool) -> Option<Vec<Curve>> {
|
fn profile_pieces(curve: &Curve, closed: bool) -> Option<Vec<Curve>> {
|
||||||
let pieces = match curve {
|
let pieces = match curve {
|
||||||
Curve::Polyline(_) => curve.segments(),
|
Curve::Polyline(_) => curve.segments(),
|
||||||
@@ -291,11 +313,8 @@ pub fn extruded_surface(
|
|||||||
direction: [f64; 3],
|
direction: [f64; 3],
|
||||||
taper_angle: f64,
|
taper_angle: f64,
|
||||||
) -> Option<Body> {
|
) -> Option<Body> {
|
||||||
// A region's surface is its one boundary loop, read from its exact edges.
|
if matches!(entity, EntityType::Region(region) if region.wires.len() > 1) {
|
||||||
if let EntityType::Region(_) = entity {
|
return None;
|
||||||
let (plane, loops, _) = super::presspull_model::profile_geometry(entity)?;
|
|
||||||
let [boundary] = loops.as_slice() else { return None };
|
|
||||||
return brep::extrude_surface_tapered(plane, boundary, direction, taper_angle);
|
|
||||||
}
|
}
|
||||||
let (profile, _) = extrusion_profile_of(entity)?;
|
let (profile, _) = extrusion_profile_of(entity)?;
|
||||||
brep::extrude_surface_tapered(
|
brep::extrude_surface_tapered(
|
||||||
|
|||||||
Reference in new issue
Block a user