kernel: CornerPatch exported with the G2 corner patch

(not built: base in progress)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017itGh5fpMEousnZ91cYcVt
This commit is contained in:
jyviko
2026-10-22 00:59:42 -04:00
parent 291af4bdbd
commit 66e31bede8
4 changed files with 316 additions and 759 deletions
+5 -8
View File
@@ -1,6 +1,6 @@
[package]
name = "solidcraft-kernel"
description = "SolidCraft B-rep kernel boundary: solids, extrude/revolve/booleans/fillets, tessellation, measures and STEP, behind our own API (implemented with truck)"
description = "SolidCraft B-rep kernel boundary: solids, extrude/revolve/booleans/fillets, meshes, measures and STEP, behind our own API (implemented with SMLib)"
version.workspace = true
edition.workspace = true
license.workspace = true
@@ -10,21 +10,18 @@ workspace = true
[features]
# Link NVIDIA's SMLib (tangency-labs/smlib) into the kernel; needs a C++ toolchain and
# scripts/fetch-smlib.sh (ADR 0002).
smlib = ["dep:solidcraft-smlib", "solidcraft-smlib/native"]
# scripts/fetch-smlib.sh (ADR 0002). Without it every geometric operation answers that SMLib
# was not built.
smlib = ["solidcraft-smlib/native"]
[dependencies]
solidcraft-geom = { workspace = true }
solidcraft-smlib = { workspace = true, optional = true }
solidcraft-smlib = { workspace = true }
solidcraft-step = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
thiserror = { workspace = true }
log = { workspace = true }
truck-modeling = { workspace = true }
truck-shapeops = { workspace = true }
truck-stepio = { workspace = true }
truck-topology = { workspace = true }
spade = { workspace = true }
web-time = { workspace = true }
+310 -697
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -176,7 +176,7 @@ pub use coaxial_overlap::{CoaxialOverlap, coaxial_candidate, coaxial_overlap};
pub use continuity::{
ContinuityReport, ContinuityTolerances, EdgePick, MAX_SAMPLES, MIN_SAMPLES, SeamReport, SeamVerdict, SeamWorst, pick_edges, seam_diagnostics,
};
pub use corner_g2::{corner_g2_patch, seam_error};
pub use corner_g2::{CornerPatch, corner_g2_patch, seam_error};
pub use delete_face::delete_faces;
pub use distance::{BodyDistance, DistanceShape, body_distance};
pub use emboss::{cylinder_emboss_anchor, emboss_cylinder, emboss_cylinder_at, has_cylinder_emboss_wall, infer_cylinder_emboss};
-53
View File
@@ -1,53 +0,0 @@
use super::*;
fn bits(v: Vec3) -> [u64; 3] {
[v.x.to_bits(), v.y.to_bits(), v.z.to_bits()]
}
fn check_body(body: &Body) -> usize {
let meshes = mesh_shells(&body.solid, 0.5);
let mut changed = 0;
for (face, meshed) in body.solid.face_iter().zip(meshes.iter().flat_map(|shell| shell.face_iter())) {
let Some(mesh) = meshed.surface() else { continue };
let surface = face.surface();
let cached = refined_with_cache(&mesh, &surface, 0.002, true);
let original = refined_with_cache(&mesh, &surface, 0.002, false);
match (cached, original) {
(None, None) => {}
(Some(cached), Some(original)) => {
changed += 1;
assert_eq!(cached.len(), original.len(), "triangle count/winding must not change");
for (cached, original) in cached.into_iter().zip(original) {
for ((point, normal), (old_point, old_normal)) in cached.into_iter().zip(original) {
assert_eq!(bits(point), bits(old_point), "every refined coordinate must remain bit-identical");
assert_eq!(bits(normal), bits(old_normal), "every refined normal must remain bit-identical");
}
}
}
_ => panic!("memoization changed the refine/no-refine decision"),
}
}
changed
}
#[test]
fn exact_refinement_cache_preserves_periodic_seams_and_normals() {
let cylinder = crate::cylinder(Vec3::ZERO, Vec3::Z, 15., 8.).unwrap();
let torus = crate::torus(Vec3::ZERO, 18., 4.).unwrap();
assert!(check_body(&cylinder) > 0, "the fixture must actually refine");
assert!(check_body(&torus) > 0, "the periodic fixture must actually refine");
}
#[test]
fn exact_refinement_cache_preserves_singular_poles_and_placed_surfaces() {
let sphere = crate::sphere(Vec3::ZERO, 12.).unwrap();
assert!(check_body(&sphere) > 0, "the polar fixture must actually refine");
let placed = crate::transform(&sphere, Vec3::new(120., -85., 40.), Vec3::ZERO, Vec3::new(1., 2., 3.), 0.371).unwrap();
assert!(check_body(&placed) > 0);
}
#[test]
fn exact_refinement_cache_keeps_unnecessary_planar_refinement_absent() {
let body = crate::box_solid(Vec3::ZERO, Vec3::new(10., 20., 30.)).unwrap();
assert_eq!(check_body(&body), 0);
}