fix(acis): complete curved solid faces

Prevent partial sweeps and reversed boundary sampling from dropping surface segments and connector corners.
This commit is contained in:
Hakan Seven committed 2026-08-03 19:45:15 +03:00
1 parent f18ba87858
commit 2c5b7e76fb
2 files changed
+23 -13

No files matched your search

+6 -3
View File
@@ -374,9 +374,9 @@ fn loop_normal(pts: &[[f64; 3]]) -> [f64; 3] {
// ── Cone / cylinder face ─────────────────────────────────────────────────────
/// Build a cone/cylinder lateral surface as revolution faces. A plain closed
/// revolution uses the parametric sampler; a pierced one stays here so its
/// additional boundary loops can trim holes into the curved surface.
/// Build a pierced cone/cylinder lateral surface as revolution faces. A
/// single-loop face uses the parametric sampler, avoiding partial revolution
/// segments that can disappear when the profile crosses a coordinate plane.
fn cone_faces(
sat: &SatDocument,
face: &SatFace,
@@ -411,6 +411,9 @@ fn cone_faces(
};
let loops = collect_face_loops(sat, face, BOUNDARY_CHORD_FRAC);
if loops.len() == 1 {
return None;
}
let arcs: Vec<(f64, f64)> = loops
.iter()
.map(|lp| cone_boundary_arc(lp, [cx, cy, cz], axis, udir, vdir))
+17 -10
View File
@@ -1424,17 +1424,23 @@ pub(crate) fn append_coedge_points(
// The edge's own sense (relative to its curve) decides the ellipse
// winding; a reversed edge samples the opposite handedness.
let reversed = matches!(edge.sense(), Sense::Reversed);
let mut sampled = sample_ellipse_arc(
// Orient the parameter range before sampling. Reversing an
// endpoint-exclusive sample afterwards would drop the traversal
// start and retain its end, duplicating the next coedge's point and
// cutting the connector corner out of the face boundary.
let (start, end) = if fwd {
(edge.start_param(), edge.end_param())
} else {
(edge.end_param(), edge.start_param())
};
let sampled = sample_ellipse_arc(
&ellipse,
edge.start_param(),
edge.end_param(),
start,
end,
chord_frac,
reversed,
);
if !sampled.is_empty() {
if !fwd {
sampled.reverse();
}
pts.extend(sampled);
return;
}
@@ -1452,12 +1458,13 @@ pub(crate) fn append_coedge_points(
.into_iter()
.map(|(x, y, z)| [x, y, z])
.collect();
// Drop the shared end point so adjacent coedges don't double up.
// Orient the inclusive sample first, then drop the traversal end so
// the adjacent coedge contributes that shared point.
if !fwd {
sampled.reverse();
}
sampled.pop();
if sampled.len() >= 2 {
if !fwd {
sampled.reverse();
}
pts.extend(sampled);
return;
}