mesh: carry a biased seed's spacing to the edges tied to it (#257)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
jyvikoandClaude Opus 5.5 authored and Irakli Kourtis committed 2026-10-15 11:11:14 -04:00
1 parent d23c2efaec
commit 3385209c6f
9 files changed
+208 -10

No files matched your search

+28 -1
View File
@@ -327,12 +327,17 @@ impl Topology {
ctxs.get(c).and_then(|x| x.seed_of(be)).map(|(seed, rev)| (seed, rev == fwd))
})
.collect();
// A biased seed's spacing carries to the unseeded edges parallel to it, through every
// cell they bound, oriented along each cell's direction (#257); the counts come from the
// edges' own seeds alone.
let carried = crate::seeds::carry(&seeds, |s: &&EdgeSeed| s.bias.is_some(), &self.parallel_ties());
let first = self.solve(&goals, &seeds)?;
// Ends of edges that leave a curved face: the spacing along that face there.
let ends = self.graded_ends(ctxs, cubes, &first);
let mut graded = goals;
let mut divisions = Vec::with_capacity(polylines.len());
for (((poly, ends), goal), seed) in polylines.into_iter().zip(ends).zip(graded.iter_mut()).zip(&seeds) {
let spacing: Vec<Option<(&EdgeSeed, bool)>> = seeds.iter().zip(carried).map(|(own, carried)| own.or(carried)).collect();
for (((poly, ends), goal), seed) in polylines.into_iter().zip(ends).zip(graded.iter_mut()).zip(&spacing) {
// A seeded edge keeps the seed's spacing, not a grading.
let ends = if seed.is_some() { [None, None] } else { ends };
let poly = if ends.iter().any(Option::is_some) {
@@ -350,6 +355,28 @@ impl Topology {
Ok(divisions)
}
/// The four edges along each direction of every cell, tied pairwise, each traversed from the
/// cell's low corner to its high one.
fn parallel_ties(&self) -> Vec<[crate::seeds::Use; 2]> {
let mut ties = Vec::new();
for (groups, ids) in self.cell_edges.iter().zip(&self.corners) {
for (d, g) in groups.iter().enumerate() {
let uses: Vec<crate::seeds::Use> = g
.iter()
.enumerate()
.map(|(m, &e)| {
let (lo, _) = edge_ends(ids, d, m);
(e, self.edges.get(e).is_some_and(|x| x.a == lo))
})
.collect();
if let Some((&first, rest)) = uses.split_first() {
ties.extend(rest.iter().map(|&u| [first, u]));
}
}
}
ties
}
fn solve(&self, goals: &[f64], seeds: &[Option<(&EdgeSeed, bool)>]) -> Result<Vec<usize>> {
let mut ia = super::interval::Intervals::default();
for (&g, seed) in goals.iter().zip(seeds) {