geop_ops_subd/
examples.rs1use geop_core_editor::registry::ExampleSet;
5use geop_core_program::program::Program;
6
7use geop_core_math::plain::centroid;
8
9use crate::{Cage, Mirror, SubdArgs};
10
11pub fn set() -> ExampleSet {
13 ExampleSet {
14 programs: vec![("subd_mouse", subd_mouse), ("subd_mug", subd_mug)],
15 workspaces: Vec::new(),
16 }
17}
18
19#[allow(clippy::expect_used, reason = "the cage is the example's own")]
24pub fn subd_mouse() -> Program {
25 let mut cage = Cage::cuboid([1.2, 2.0, 0.8]);
26 cage.halve(0).expect("the box reaches across x = 0");
27 let bottom = cage.face(8).expect("the box's bottom").vertices.clone();
28 let on_plane = |v: u32| cage.vertex(v).is_ok_and(|x| x.at[0] == 0.0);
29 let rim: Vec<[u32; 2]> = (0..bottom.len())
30 .map(|k| [bottom[k], bottom[(k + 1) % bottom.len()]])
31 .filter(|&[a, b]| !(on_plane(a) && on_plane(b)))
32 .collect();
33 cage.set_sharpness(&rim, 1.0);
34 let back = cage
35 .vertices
36 .iter()
37 .filter(|v| v.at[1] > 0.0 && v.at[2] > 0.0)
38 .map(|v| v.id)
39 .collect();
40 cage.transform(&back, Mirror::X, |p| [p[0], p[1], p[2] + 0.3]);
41 let mut program = Program::new();
42 program.push(
43 "mouse",
44 SubdArgs {
45 cage,
46 mirror: Mirror::X,
47 },
48 );
49 program
50}
51
52#[allow(clippy::expect_used, reason = "the cage is the example's own")]
54fn face_near(cage: &Cage, point: [f64; 3]) -> u32 {
55 let centre = |ids: &[u32]| {
56 centroid(ids.iter().map(|&v| cage.vertex(v).expect("a corner").at)).expect("corners")
57 };
58 let distance = |c: [f64; 3]| (0..3).map(|k| (c[k] - point[k]).powi(2)).sum::<f64>();
59 (cage.faces.iter())
60 .min_by(|a, b| distance(centre(&a.vertices)).total_cmp(&distance(centre(&b.vertices))))
61 .expect("a face")
62 .id
63}
64
65#[allow(clippy::expect_used, reason = "the cage is the example's own")]
71pub fn subd_mug() -> Program {
72 let mirror = Mirror::Y;
73 let mut cage = Cage::cylinder(1.0, 2.4, 8);
74 cage.halve(1).expect("the cylinder reaches across y = 0");
75 cage.insert_loop(0, 8, 0.5).expect("a ring of quads");
78 cage.insert_loop(8, 16, 0.5).expect("a ring of quads");
79 let lower = face_near(&cage, [0.95, 0.2, -0.9]);
82 let upper = face_near(&cage, [0.95, 0.2, 0.9]);
83 cage.extrude(&[lower].into(), 0.8, mirror).expect("a face");
84 cage.extrude(&[upper].into(), 0.8, mirror).expect("a face");
85 cage.bridge(lower, upper, mirror).expect("two quads");
86 let top = face_near(&cage, [0.0, 0.5, 1.2]);
88 let lip: Vec<[u32; 2]> = cage
89 .edges()
90 .into_iter()
91 .filter(|&[a, b]| {
92 let (p, q) = (cage.vertex(a).expect("a").at, cage.vertex(b).expect("b").at);
93 p[2] == 1.2 && q[2] == 1.2 && !(p[1] == 0.0 && q[1] == 0.0)
94 })
95 .collect();
96 cage.inset(&[top].into(), 0.15, mirror).expect("a face");
97 cage.extrude(&[top].into(), -2.0, mirror).expect("a face");
98 cage.set_sharpness(&lip, 0.5);
99 let bottom: Vec<[u32; 2]> = cage
100 .edges()
101 .into_iter()
102 .filter(|&[a, b]| {
103 let (p, q) = (cage.vertex(a).expect("a").at, cage.vertex(b).expect("b").at);
104 p[2] == -1.2 && q[2] == -1.2 && !(p[1] == 0.0 && q[1] == 0.0)
105 })
106 .collect();
107 cage.set_sharpness(&bottom, 1.0);
108 let mut program = Program::new();
109 program.push("mug", SubdArgs { cage, mirror });
110 program
111}