forked from 1b-agent/fieldcraft-upstream
Meshing test corpus built with SolidCraft; assembly placement in open_design (#11)
* geometry: build designs from SolidCraft command scripts (feature scripts) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * geometry: place component bodies through their occurrences when opening a design An assembly's instances were missing and moved components sat at their own origin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Meshing test corpus: 16 SolidCraft recipes, analytic shapes, loader and runner modelcraft-testkit holds the corpus (tests/corpus/<name>/recipe.json run through SolidCraft's engine, then opened as a design) and the runner binary behind cargo xtask corpus. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * docs: corpus results, test corpus architecture and the scripts feature; licences Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * corpus: measure each body once, check stage widths, simpler loader and runner Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm --------- Co-authored-by: jyviko <2501648+jyviko@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
49 files changed
+1770
-84
No files matched your search
+23
-11
@@ -19,9 +19,13 @@
|
||||
|
||||
mod design;
|
||||
pub mod sample;
|
||||
#[cfg(feature = "scripts")]
|
||||
mod script;
|
||||
|
||||
pub use design::{Design, FeatureError, MAX_DESIGN_BYTES, open_design, open_design_file};
|
||||
pub mod tagged_mesh;
|
||||
#[cfg(feature = "scripts")]
|
||||
pub use script::{MAX_SCRIPT_BYTES, script_design};
|
||||
use solidcraft_kernel::{Body, KernelError, guard};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, thiserror::Error)]
|
||||
@@ -129,6 +133,23 @@ impl Shape {
|
||||
}
|
||||
}
|
||||
|
||||
impl SurfaceMesh {
|
||||
/// The volume the triangles enclose (divergence theorem: the sum of the signed tetrahedra each
|
||||
/// triangle spans with the origin). Equals the solid's volume for a closed, outward-oriented
|
||||
/// surface; a triangle with a vertex index out of range counts as nothing.
|
||||
pub fn enclosed_volume(&self) -> f64 {
|
||||
let six_v: f64 = self
|
||||
.triangles
|
||||
.iter()
|
||||
.filter_map(|t| {
|
||||
let [a, b, c] = [self.positions.get(t[0] as usize)?, self.positions.get(t[1] as usize)?, self.positions.get(t[2] as usize)?];
|
||||
Some(a[0] * (b[1] * c[2] - b[2] * c[1]) - a[1] * (b[0] * c[2] - b[2] * c[0]) + a[2] * (b[0] * c[1] - b[1] * c[0]))
|
||||
})
|
||||
.sum();
|
||||
six_v / 6.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -150,17 +171,8 @@ mod tests {
|
||||
faces.sort_unstable();
|
||||
faces.dedup();
|
||||
assert_eq!(faces.len(), 6);
|
||||
// Divergence theorem: the outward-oriented triangles enclose the block's volume.
|
||||
let p = |i: u32| mesh.positions[i as usize];
|
||||
let six_v: f64 = mesh
|
||||
.triangles
|
||||
.iter()
|
||||
.map(|t| {
|
||||
let (a, b, c) = (p(t[0]), p(t[1]), p(t[2]));
|
||||
a[0] * (b[1] * c[2] - b[2] * c[1]) - a[1] * (b[0] * c[2] - b[2] * c[0]) + a[2] * (b[0] * c[1] - b[1] * c[0])
|
||||
})
|
||||
.sum();
|
||||
assert!((six_v / 6.0 - 24.0).abs() < 1e-9, "{}", six_v / 6.0);
|
||||
// The outward-oriented triangles enclose the block's volume.
|
||||
assert!((mesh.enclosed_volume() - 24.0).abs() < 1e-9, "{}", mesh.enclosed_volume());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user