daikon_stl/
lib.rs

1use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
2use std::io::{Error, Read};
3
4pub trait STLObject: Sized {
5    fn parse(reader: &mut dyn Read) -> Result<Self, Error>;
6    fn serialize(&self, writer: &mut dyn std::io::Write) -> Result<(), Error>;
7}
8
9impl STLObject for cgmath::Point3<f32> {
10    fn parse(reader: &mut dyn Read) -> Result<Self, Error> {
11        Ok(Self {
12            x: reader.read_f32::<LittleEndian>()?,
13            y: reader.read_f32::<LittleEndian>()?,
14            z: reader.read_f32::<LittleEndian>()?,
15        })
16    }
17
18    fn serialize(&self, writer: &mut dyn std::io::Write) -> Result<(), Error> {
19        writer.write_f32::<LittleEndian>(self.x)?;
20        writer.write_f32::<LittleEndian>(self.y)?;
21        writer.write_f32::<LittleEndian>(self.z)?;
22        Ok(())
23    }
24}
25
26#[derive(PartialEq, Debug)]
27pub struct Triangle {
28    pub normal: cgmath::Point3<f32>,
29    pub vertices: [cgmath::Point3<f32>; 3],
30}
31
32impl STLObject for Triangle {
33    fn parse(reader: &mut dyn Read) -> Result<Self, Error> {
34        let triangle = Ok(Triangle {
35            normal: cgmath::Point3::parse(reader)?,
36            vertices: [
37                cgmath::Point3::parse(reader)?,
38                cgmath::Point3::parse(reader)?,
39                cgmath::Point3::parse(reader)?,
40            ],
41        });
42
43        reader.read_u16::<LittleEndian>()?;
44
45        triangle
46    }
47
48    fn serialize(&self, writer: &mut dyn std::io::Write) -> Result<(), Error> {
49        self.normal.serialize(writer)?;
50        for vertex in self.vertices.iter() {
51            vertex.serialize(writer)?;
52        }
53        writer.write_u16::<LittleEndian>(0)?;
54        Ok(())
55    }
56}
57
58#[derive(Debug)]
59pub struct STL {
60    pub header: [u8; 80],
61    pub n_triangles: u32,
62    pub triangles: Vec<Triangle>,
63}
64
65impl STLObject for STL {
66    fn parse(reader: &mut dyn Read) -> Result<Self, Error> {
67        let mut header = [0u8; 80];
68        reader.read_exact(&mut header)?;
69        let n_triangles = reader.read_u32::<LittleEndian>()?;
70        match (0..n_triangles).map(|_| Triangle::parse(reader)).collect() {
71            Ok(triangles) => Ok(STL {
72                header,
73                n_triangles,
74                triangles,
75            }),
76            Err(e) => Err(e),
77        }
78    }
79
80    fn serialize(&self, writer: &mut dyn std::io::Write) -> Result<(), Error> {
81        writer.write(&self.header)?;
82        writer.write_u32::<LittleEndian>(self.n_triangles)?;
83        for triangle in self.triangles.iter() {
84            triangle.serialize(writer)?;
85        }
86        Ok(())
87    }
88}
89
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94
95    #[test]
96    fn parse_one_face() -> Result<(), Box<dyn std::error::Error>> {
97        // Create an empty stl
98        let mut stl_bytes = [0u8; 80 + 4 + 3 * 4 + 3 * 3 * 4 + 2];
99
100        // Set the number of triangles to 1
101        stl_bytes[80] = 1;
102
103        // parse
104        let stl = STL::parse(&mut stl_bytes.as_slice())?;
105
106        assert_eq!(
107            Triangle {
108                normal: Normal {
109                    x: 0.0,
110                    y: 0.0,
111                    z: 0.0
112                },
113                vertices: [
114                    Vertex {
115                        x: 0.0,
116                        y: 0.0,
117                        z: 0.0
118                    },
119                    Vertex {
120                        x: 0.0,
121                        y: 0.0,
122                        z: 0.0
123                    },
124                    Vertex {
125                        x: 0.0,
126                        y: 0.0,
127                        z: 0.0
128                    },
129                ]
130            },
131            stl.triangles[0]
132        );
133
134        Ok(())
135    }
136}
137