Skip to main content

hyperwood_trough/
lib.rs

1use hyperwood::{Model, Point, Slat, Variant, Vector};
2use serde::{Deserialize, Serialize};
3
4#[derive(Serialize, Deserialize, Default)]
5pub struct TroughParameters {
6    width: isize,
7    depth: isize,
8    height: isize,
9}
10
11impl TroughParameters {
12    pub fn new(width: isize, depth: isize, height: isize) -> Self {
13        assert!(height >= 3, "Depth must be equal or greater than 3");
14        // TODO: validate minimal and maximal sizes
15
16        Self {
17            width,
18            depth,
19            height,
20        }
21    }
22}
23
24#[derive(Serialize, Deserialize, Default)]
25pub struct TroughProperties {
26    width: f32,
27    depth: f32,
28    height: f32,
29    volume: f32,
30}
31
32pub fn build_model(
33    parameters: TroughParameters,
34    variant: Variant,
35) -> Model<TroughParameters, TroughProperties> {
36    let depth = parameters.depth - 1;
37    let kurve_stop = 0;
38
39    // TODO: use a lampda
40    let d = f32::sin(-std::f32::consts::PI * 1.0 / (parameters.height - kurve_stop) as f32);
41
42    let mut slats = vec![];
43
44    let mut width: f32 = 0.0;
45    let mut height: f32 = 0.0;
46    let mut volume = 0.0;
47
48    // skids
49    slats.push(Slat {
50        name: "Skid".to_string(),
51        layer: 0,
52        origin: Point {
53            x: -d,
54            y: -d,
55            z: 0.0,
56        },
57        vector: Vector {
58            x: 0.0,
59            y: depth as f32 + 2.0 * d,
60            z: 0.0,
61        },
62    });
63    slats.push(Slat {
64        name: "Skid".to_string(),
65        layer: 0,
66        origin: Point {
67            x: (parameters.width - 1) as f32 + d,
68            y: -d,
69            z: 0.0,
70        },
71        vector: Vector {
72            x: 0.0,
73            y: depth as f32 + 2.0 * d,
74            z: 0.0,
75        },
76    });
77
78    // floor
79    for y in 0..depth + 1 {
80        slats.push(Slat {
81            name: "Floor".to_string(),
82            layer: 1,
83            origin: Point {
84                x: 0.0,
85                y: y as f32,
86                z: 1.0,
87            },
88            vector: Vector {
89                x: (parameters.width - 1) as f32,
90                y: 0.0,
91                z: 0.0,
92            },
93        });
94    }
95
96    // walls
97    for z in 2..parameters.height {
98        let d = f32::sin(
99            std::f32::consts::PI * (z - 1) as f32 / (parameters.height - kurve_stop) as f32,
100        );
101        let w = parameters.width as f32 + 2.0 * d;
102        let h = parameters.height as f32 + d;
103
104        width = width.max(w + 1.0);
105        height = height.max(h + 1.0);
106        volume += (h - 1.0) * (w - 1.0);
107
108        if z % 2 == 0 {
109            // left
110            slats.push(Slat {
111                name: "Wall side even".to_string(),
112                layer: z,
113                origin: Point {
114                    x: -d,
115                    y: -d,
116                    z: z as f32,
117                },
118                vector: Vector {
119                    x: 0.0,
120                    y: depth as f32 + 2.0 * d,
121                    z: 0.0,
122                },
123            });
124
125            // right
126            slats.push(Slat {
127                name: "Wall side even".to_string(),
128                layer: z,
129                origin: Point {
130                    x: (parameters.width - 1) as f32 + d,
131                    y: -d,
132                    z: z as f32,
133                },
134                vector: Vector {
135                    x: 0.0,
136                    y: depth as f32 + 2.0 * d,
137                    z: 0.0,
138                },
139            });
140
141            // front
142            slats.push(Slat {
143                name: "Wall even".to_string(),
144                layer: z,
145                origin: Point {
146                    x: 1.0 - d,
147                    y: -d,
148                    z: z as f32,
149                },
150                vector: Vector {
151                    x: (parameters.width - 1) as f32 - 2.0 + 2.0 * d,
152                    y: 0.0,
153                    z: 0.0,
154                },
155            });
156
157            // back
158            slats.push(Slat {
159                name: "Wall even".to_string(),
160                layer: z,
161                origin: Point {
162                    x: 1.0 - d,
163                    y: depth as f32 + d,
164                    z: z as f32,
165                },
166                vector: Vector {
167                    x: (parameters.width - 1) as f32 - 2.0 + 2.0 * d,
168                    y: 0.0,
169                    z: 0.0,
170                },
171            });
172        } else {
173            // left
174            slats.push(Slat {
175                name: "Wall side odd".to_string(),
176                layer: z,
177                origin: Point {
178                    x: -d,
179                    y: 1.0 - d,
180                    z: z as f32,
181                },
182                vector: Vector {
183                    x: 0.0,
184                    y: depth as f32 - 2.0 + 2.0 * d,
185                    z: 0.0,
186                },
187            });
188
189            // right
190            slats.push(Slat {
191                name: "Wall side odd".to_string(),
192                layer: z,
193                origin: Point {
194                    x: (parameters.width - 1) as f32 + d,
195                    y: 1.0 - d,
196                    z: z as f32,
197                },
198                vector: Vector {
199                    x: 0.0,
200                    y: depth as f32 - 2.0 + 2.0 * d,
201                    z: 0.0,
202                },
203            });
204
205            // front
206            slats.push(Slat {
207                name: "Wall odd".to_string(),
208                layer: z,
209                origin: Point {
210                    x: -d,
211                    y: -d,
212                    z: z as f32,
213                },
214                vector: Vector {
215                    x: (parameters.width - 1) as f32 + 2.0 * d,
216                    y: 0.0,
217                    z: 0.0,
218                },
219            });
220
221            // back
222            slats.push(Slat {
223                name: "Wall odd".to_string(),
224                layer: z,
225                origin: Point {
226                    x: -d,
227                    y: depth as f32 + d,
228                    z: z as f32,
229                },
230                vector: Vector {
231                    x: (parameters.width - 1) as f32 + 2.0 * d,
232                    y: 0.0,
233                    z: 0.0,
234                },
235            });
236        }
237    }
238
239    let properties = TroughProperties {
240        width: width * variant.x,
241        depth: parameters.depth as f32 * variant.y,
242        height: height * variant.z,
243        volume: volume * variant.x * variant.y * variant.z,
244    };
245
246    Model {
247        parameters,
248        properties,
249        name: "Trough".to_owned(),
250        variant,
251        slats,
252    }
253}