fix(kernel): revolving adjacent profiles on the axis makes no zero-area faces (#490)
Profiles revolved together merge into one region that keeps a vertex where each shared edge met the axis. With the axis edge in several pieces the loop skipped the builders for a profile with an edge on the axis, and the generic sweep turned each piece into a degenerate face that booleans failed on. Runs of collinear axis lines are merged into one first. Fixes #487 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
219816d282
commit
91de39d3fe
3 files changed
+64
-2
No files matched your search
@@ -125,6 +125,35 @@ impl NumberedLoop {
|
||||
out
|
||||
}
|
||||
|
||||
/// Each run of lines that `joins` says continue one another as a single line, over what
|
||||
/// they all ran over. (Adjacent profiles merged into one region keep a vertex where each
|
||||
/// shared edge met the outline.)
|
||||
pub(crate) fn merged_lines(&self, joins: impl Fn(&Seg2, &Seg2) -> bool) -> NumberedLoop {
|
||||
let n = self.lp.segs.len();
|
||||
let join = |i: usize, j: usize| match (self.lp.segs.get(i), self.lp.segs.get(j)) {
|
||||
(Some(s @ Seg2::Line { .. }), Some(t @ Seg2::Line { .. })) => joins(s, t),
|
||||
_ => false,
|
||||
};
|
||||
// Start where a run starts (a loop of nothing but one run stays as it is).
|
||||
let Some(k) = (0..n).find(|&i| !join((i + n - 1) % n, i)) else { return self.clone() };
|
||||
let mut out = NumberedLoop { lp: Loop2 { segs: Vec::new() }, from: Vec::new() };
|
||||
for j in 0..n {
|
||||
let i = (k + j) % n;
|
||||
let (Some(s), from) = (self.lp.segs.get(i).copied(), self.numbers(i)) else { continue };
|
||||
if j > 0
|
||||
&& join((i + n - 1) % n, i)
|
||||
&& let (Some(Seg2::Line { b, .. }), Some(prev)) = (out.lp.segs.last_mut(), out.from.last_mut())
|
||||
{
|
||||
*b = s.end();
|
||||
*prev = union([prev.as_slice(), from]);
|
||||
continue;
|
||||
}
|
||||
out.lp.segs.push(s);
|
||||
out.from.push(from.to_vec());
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// Split segment `k` in half, both halves over what it ran over.
|
||||
fn split_half(&mut self, k: usize) {
|
||||
if k >= self.lp.segs.len() || k >= self.from.len() {
|
||||
|
||||
Reference in new issue
Block a user