Mesh: the hex meshers honour edge seeds

A seed is matched to a mesher's curve by position (ends and middle within the
two tessellations' tolerance), which also orients its bias. Interval
assignment holds exact seeds, raises minimums and takes free seeds as goals;
an equality, loop minimum or parity it cannot meet with the exact seeds held
names them. Seeded curves get the seed's spacing. Extrude and revolve seed
cross-section curves and the layers of a level interval; sweep and mapped
seed their B-rep edges; cells seed the shared edge once, so both cells keep
it and stay conforming.

Part of #230.

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-14 21:23:05 -04:00
1 parent bdd84a491d
commit 13b506150c
9 files changed
+677 -24

No files matched your search

+3 -3
View File
@@ -16,7 +16,7 @@ use super::brep::Brep;
use super::interval::Intervals;
use super::{Ctx, Raw, project_to_face, project_to_faces};
use crate::quad::{lattice_index, transfinite_faces, transfinite_volume};
use crate::size::{divide_polyline, ideal_divisions};
use crate::size::ideal_divisions;
use crate::vec3::{P, det, sub};
use crate::{Error, Result};
@@ -155,7 +155,7 @@ pub(crate) fn mesh(ctx: &Ctx) -> Result<Raw> {
let groups = cube.groups;
let mut ia = Intervals::default();
for e in 0..brep.edges.len() {
ia.var(ideal_divisions(ctx.field, &brep.edge_points(e, true))?, 1);
ctx.edge_var(&mut ia, e, ideal_divisions(ctx.field, &brep.edge_points(e, true))?);
}
for g in &groups {
let first = g.first().map(|x| x.0).unwrap_or(0);
@@ -173,7 +173,7 @@ pub(crate) fn mesh(ctx: &Ctx) -> Result<Raw> {
}
// Edge node positions, low corner to high.
let edge_pts = |(e, fwd): (usize, bool), n: usize| -> Result<Vec<P>> {
let pts = divide_polyline(ctx.field, &brep.edge_points(e, fwd), n)?;
let pts = ctx.divide_edge(e, fwd, n)?;
let faces = brep.edges.get(e).map(|x| x.faces.to_vec()).unwrap_or_default();
let last = pts.len().saturating_sub(1);
Ok(pts.iter().enumerate().map(|(k, q)| if k == 0 || k == last { *q } else { project_to_faces(ctx, &faces, *q) }).collect())