Skip to main content

geop_ops_surface/
examples.rs

1//! The examples of surfaces an editor offers: a doubly curved panel
2//! through a network of curves, a block split along it.
3
4use geop_core_editor::registry::ExampleSet;
5use geop_core_math::{primitives::FrameAxis, vector::Vector3};
6use geop_core_program::program::Program;
7use geop_ops_boolean::SplitArgs;
8use geop_ops_extrude_revolve::{Extents, ExtrudeArgs, Output};
9use geop_ops_model::datums::origin_plane;
10use geop_ops_model::sketch::{
11    Sketch, SketchPlane,
12    figures::{n, rectangle, solved},
13    whole_sketch,
14};
15use geop_ops_model::sketch3d::{CurveSource, Sketch3d};
16use geop_ops_model::{Combine, element, solid};
17use geop_ops_sketch::AddSketchArgs;
18use geop_ops_sketch3d::AddSketch3dArgs;
19
20use crate::NetworkSurfaceArgs;
21
22/// The examples of this crate, by name.
23pub fn set() -> ExampleSet {
24    ExampleSet {
25        programs: vec![("curved_panel", curved_panel)],
26        workspaces: Vec::new(),
27    }
28}
29
30/// A doubly curved panel, a saddle: a UV surface (`panel`) through three
31/// ribs along `x` and three spines along `z`, each a spline of a 3-D
32/// sketch through points of the saddle — the ribs' and the spines' meeting
33/// where they cross; and a block under it (`block`, up along `y`) split
34/// along it (`shaped`) into a piece with the saddle for its top and one
35/// with it for its bottom. Drawn in tens of millimetres: the panel is 40 by
36/// 30.
37pub fn curved_panel() -> Program {
38    let height = |x: f64, z: f64| 0.6 + 0.08 * (x - 2.0).powi(2) - 0.12 * (z - 1.5).powi(2);
39    let mut program = Program::new();
40    let mut splines = |name: &str, lines: Vec<Vec<[f64; 2]>>| -> Vec<CurveSource> {
41        let mut sketch = Sketch3d::new();
42        let mut curves = Vec::new();
43        for line in lines {
44            let points = line
45                .iter()
46                .map(|&[x, z]| {
47                    let at = [x, height(x, z), z].map(|c| n(10.0 * c));
48                    sketch.add_point(Vector3::from_array(at))
49                })
50                .collect();
51            let curve = sketch.add_spline(points);
52            curves.push(CurveSource::Edge(element(format!(
53                "sketch3d({name},{curve})"
54            ))));
55        }
56        program.push(
57            name,
58            AddSketch3dArgs {
59                sketch,
60                references: Vec::new(),
61            },
62        );
63        curves
64    };
65    let ribs = splines(
66        "ribs",
67        [0.0, 1.5, 3.0]
68            .iter()
69            .map(|&y| [0.0, 1.0, 2.0, 3.0, 4.0].map(|x| [x, y]).to_vec())
70            .collect(),
71    );
72    let spines = splines(
73        "spines",
74        [0.0, 2.0, 4.0]
75            .iter()
76            .map(|&x| [0.0, 0.75, 1.5, 2.25, 3.0].map(|y| [x, y]).to_vec())
77            .collect(),
78    );
79    program.push(
80        "panel",
81        NetworkSurfaceArgs {
82            u_curves: ribs,
83            v_curves: spines,
84        },
85    );
86    let mut outline = Sketch::new();
87    // Sketch `y` runs along world `-z`.
88    rectangle(&mut outline, [5.0, -25.0], 30.0, 20.0);
89    program.push(
90        "block_sketch",
91        AddSketchArgs {
92            plane: Some(SketchPlane::Datum(origin_plane(FrameAxis::Y))),
93            sketch: solved(outline),
94            ..Default::default()
95        },
96    );
97    program.push(
98        "block",
99        ExtrudeArgs {
100            sketch: whole_sketch("block_sketch"),
101            extent: Extents::blind(15.0),
102            output: Output::Solid(Combine::NewBody),
103            draft: 0.0,
104        },
105    );
106    program.push(
107        "shaped",
108        SplitArgs {
109            solid: solid("extrude(block)"),
110            face: element("network(panel)"),
111        },
112    );
113    program
114}