Another project
1use bone_kernel::{
2 BrepSolid, Curve2Kind, ExtrudeDirection, ExtrudeEndCondition, ExtrudeFeature, ExtrudeProfile,
3 ExtrudeSense, Line2, MergeResult, ProfileEdge, ProfileLoop, evaluate_extrude,
4};
5use bone_render::{SolidRenderer, SolidScene, Style, frame_isometric};
6use bone_types::{
7 AngleTolerance, ChordHeightTolerance, FeatureId, Length, Plane3, Point2, Point3,
8 PositiveLength, SketchEntityId, SketchId, Tolerance, UnitVec3, millimeter,
9};
10use slotmap::{Key, SlotMap};
11
12mod common;
13
14use common::{check_golden, extent_square as extent, make_context};
15
16const GOLDEN: &str = "tests/goldens/cube_iso_256.png";
17const UPDATE_ENV: &str = "BONE_UPDATE_CUBE_ISO_GOLDEN";
18const TOLERANCE: Tolerance = Tolerance::new(1.0e-9);
19
20fn unit_cube() -> BrepSolid {
21 let mut entities: SlotMap<SketchEntityId, ()> = SlotMap::with_key();
22 let mut features: SlotMap<FeatureId, ()> = SlotMap::with_key();
23 let Ok(plane) = Plane3::new(
24 Point3::origin(),
25 UnitVec3::x_axis(),
26 UnitVec3::y_axis(),
27 TOLERANCE,
28 ) else {
29 panic!("x and y axes are orthonormal");
30 };
31 let corners = [
32 Point2::from_mm(0.0, 0.0),
33 Point2::from_mm(1.0, 0.0),
34 Point2::from_mm(1.0, 1.0),
35 Point2::from_mm(0.0, 1.0),
36 ];
37 let edges = (0..4)
38 .map(|index| {
39 let start = corners[index];
40 let end = corners[(index + 1) % 4];
41 let Ok(segment) = Line2::new(start, end, TOLERANCE) else {
42 panic!("rectangle endpoints are distinct");
43 };
44 ProfileEdge::new(
45 Curve2Kind::Line(segment),
46 entities.insert(()),
47 entities.insert(()),
48 )
49 })
50 .collect();
51 let profile = ExtrudeProfile::new(plane, vec![ProfileLoop::Open(edges)]);
52 let Ok(depth) = PositiveLength::new(Length::new::<millimeter>(1.0)) else {
53 panic!("1 mm is a positive length");
54 };
55 let feature = ExtrudeFeature {
56 sketch: SketchId::null(),
57 direction: ExtrudeDirection::Normal {
58 sense: ExtrudeSense::Forward,
59 },
60 end_condition: ExtrudeEndCondition::Blind { depth },
61 draft: None,
62 thin_wall: None,
63 merge_result: MergeResult::Merge,
64 };
65 let Ok(solid) = evaluate_extrude(features.insert(()), &profile, &feature) else {
66 panic!("the unit square extrudes into a cube");
67 };
68 solid
69}
70
71#[test]
72fn cube_iso_matches_golden() {
73 let size = extent(256);
74 let ctx = make_context(size);
75 let mut renderer = SolidRenderer::new(ctx.gpu(), ctx.color_format());
76 let solid = unit_cube();
77 let Ok(mesh) = solid.tessellate(
78 ChordHeightTolerance::from_mm(0.05),
79 AngleTolerance::from_radians(0.2),
80 ) else {
81 panic!("the cube tessellates");
82 };
83 let Ok(scene) = SolidScene::from_mesh(&mesh) else {
84 panic!("the cube mesh packs face pick ids");
85 };
86 let Some(aabb) = solid.bounding_box() else {
87 panic!("the cube has a bounding box");
88 };
89 let Ok(camera) = frame_isometric(aabb, size) else {
90 panic!("the cube frames isometrically");
91 };
92 let style = Style::default();
93
94 let Ok(frame) = renderer.render(&ctx, &scene, camera, &style) else {
95 panic!("SolidRenderer::render failed");
96 };
97
98 check_golden(&frame, GOLDEN, UPDATE_ENV);
99}