bspline/
bspline.rs

1use geom3d::{
2    surface::{BSplineSurface, SurfacePatch},
3    Float, Grid, Model, Point3,
4};
5
6fn load_teapot(
7    degree: (usize, usize),
8    division: (usize, usize),
9) -> std::io::Result<Model<SurfacePatch<BSplineSurface<Point3>>>> {
10    use std::fs::File;
11    use std::io::{BufRead, BufReader};
12    use std::path::Path;
13    use std::str::FromStr;
14
15    let file = Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap()).join("assets/teapot.bpt");
16    let reader = BufReader::new(File::open(file)?);
17
18    let mut model = Model::new();
19    let mut points = Vec::new();
20    let mut current_cols = 0;
21
22    for line in reader.lines() {
23        let numbers = line?;
24        let items = numbers.split_whitespace().collect::<Vec<_>>();
25        if items.len() == 1 {
26            model
27                .faces
28                .reserve_exact(usize::from_str(items[0]).unwrap());
29        } else if items.len() == 2 {
30            if points.len() > 0 {
31                let surface = SurfacePatch {
32                    surface: BSplineSurface::uniform_clamped(
33                        Grid::from_vec(points, current_cols),
34                        degree,
35                    ),
36                    parameter_range: ((0.0, 1.0), (0.0, 1.0)),
37                    parameter_division: division,
38                };
39                model.add_face(surface);
40            }
41            let m = usize::from_str(items[0]).unwrap();
42            let n = usize::from_str(items[1]).unwrap();
43            points = Vec::with_capacity((m + 1) * (n + 1));
44            current_cols = n + 1;
45        } else if items.len() == 3 {
46            let point = Point3::new(
47                Float::from_str(items[0]).unwrap(),
48                Float::from_str(items[1]).unwrap(),
49                Float::from_str(items[2]).unwrap(),
50            );
51            points.push(point);
52        }
53    }
54    // add last surface
55    let surface = SurfacePatch {
56        surface: BSplineSurface::uniform_clamped(Grid::from_vec(points, current_cols), degree),
57        parameter_range: ((0.0, 1.0), (0.0, 1.0)),
58        parameter_division: division,
59    };
60    model.add_face(surface);
61    Ok(model)
62}
63
64fn main() {
65    let teapot = load_teapot((2, 2), (16, 16)).unwrap();
66    teapot.save_as_stl("teapot.stl").unwrap();
67    let teapot = load_teapot((3, 1), (16, 16)).unwrap();
68    teapot.save_as_obj("teapot.obj").unwrap();
69}