forked from 1b-agent/fieldcraft-upstream
mesh: divide a block edge that bends with a curved target by its length
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
1 parent
5db21aba7b
commit
729a770d6c
2 files changed
+23
-5
No files matched your search
@@ -202,8 +202,12 @@ fn squeezed_junction_elements_are_reported_not_meshed() {
|
||||
p["min_quality"] = json!(0.3);
|
||||
let model = s.model.clone();
|
||||
let e = s.execute("mesh.hex.project", &p).unwrap_err().to_string();
|
||||
// Smoothing leaves the worst element in the squeezed ring block (34) or in block 36.
|
||||
assert!(e.contains("smallest scaled Jacobian") && (e.contains("worst in block 34") || e.contains("worst in block 36")), "{e}");
|
||||
// Smoothing leaves the worst element in the squeezed ring block (34) or in block 36; with
|
||||
// the cup's rim divided by its own length, the junction's corner (block 13) folds instead,
|
||||
// and the validity gate refuses it.
|
||||
let squeezed = e.contains("smallest scaled Jacobian") && (e.contains("worst in block 34") || e.contains("worst in block 36"));
|
||||
let folded = e.contains("inverted, twisted or degenerate") && e.contains("block 13");
|
||||
assert!(squeezed || folded, "{e}");
|
||||
assert_eq!(s.model, model);
|
||||
}
|
||||
|
||||
|
||||
@@ -514,11 +514,17 @@ pub fn project_mesh(t: &Topology, surface: &BoundarySurface, g: &dyn Geometry, o
|
||||
// lengths). A class runs through every block its edges are parallel in, so its edges can
|
||||
// differ a lot in length (a cup's wall, 4 mm thick, and its floor's radial edges, twice
|
||||
// that); the longest edge alone would cut the thin blocks into flat slivers. No element is
|
||||
// longer than [`MAX_STRETCH`] sizes, so a coarse size still follows the geometry.
|
||||
// longer than [`MAX_STRETCH`] sizes, so a coarse size still follows the geometry. An edge
|
||||
// that bends with a curved target is the exception: its elements' sides are chords of the
|
||||
// surface, and one longer than the size cuts off more of the part than the size allows (a
|
||||
// butterfly's rim shares its class with the shorter sides of its middle square), so a class
|
||||
// takes at least the geometric mean of its bent edges' lengths in sizes (rounded,
|
||||
// as the mean; an annulus's rim and bore balance each other as its straight edges do).
|
||||
let (classes, nclass) = edge_classes(t);
|
||||
let mut class_log = vec![(0.0f64, 0usize); nclass];
|
||||
// Per class, its longest edge in element sizes.
|
||||
let mut class_max = vec![0.0f64; nclass];
|
||||
let mut class_bent = vec![(0.0f64, 0usize); nclass];
|
||||
let mut seen: BTreeSet<[u32; 2]> = BTreeSet::new();
|
||||
for (block, cls) in t.blocks.iter().zip(&classes) {
|
||||
for d in 0..3 {
|
||||
@@ -550,6 +556,12 @@ pub fn project_mesh(t: &Topology, surface: &BoundarySurface, g: &dyn Geometry, o
|
||||
if let Some(m) = class_max.get_mut(cls[d]) {
|
||||
*m = m.max(measured);
|
||||
}
|
||||
if len - dist(pa, pb) > tol
|
||||
&& let Some(l) = class_bent.get_mut(cls[d])
|
||||
{
|
||||
l.0 += libm::log(measured);
|
||||
l.1 += 1;
|
||||
}
|
||||
if let Some(l) = class_log.get_mut(cls[d]).filter(|_| len > tol) {
|
||||
l.0 += libm::log(measured);
|
||||
l.1 += 1;
|
||||
@@ -615,9 +627,11 @@ pub fn project_mesh(t: &Topology, surface: &BoundarySurface, g: &dyn Geometry, o
|
||||
.iter()
|
||||
.zip(&class_max)
|
||||
.zip(&class_arc)
|
||||
.map(|((&(sum, k), &longest), &arc)| {
|
||||
.zip(&class_bent)
|
||||
.map(|(((&(sum, k), &longest), &arc), &(bent_sum, bent_k))| {
|
||||
let mean = if k == 0 { 1.0 } else { libm::exp(sum / k as f64).round() };
|
||||
(mean.max((longest / MAX_STRETCH).ceil()) as usize).max(arc).clamp(1, crate::block::MAX_DIVISIONS)
|
||||
let bent = if bent_k == 0 { 0 } else { libm::exp(bent_sum / bent_k as f64).round().min(crate::block::MAX_DIVISIONS as f64) as usize };
|
||||
(mean.max((longest / MAX_STRETCH).ceil()) as usize).max(arc).max(bent).clamp(1, crate::block::MAX_DIVISIONS)
|
||||
})
|
||||
.collect();
|
||||
for &(b, d, n) in &opts.divisions {
|
||||
|
||||
Reference in new issue
Block a user