1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
use crate::{
data::Table,
err::Error,
file::{Build, Load},
geom::{Emitter, MeshBuilder, Ray},
math::{Dir3, Pos3},
ord::{X, Y, Z},
};
use arctk_attr::load;
use std::path::{Path, PathBuf};
#[load]
pub enum EmitterBuilder {
Beam(Pos3, Dir3),
Points(PathBuf),
WeightedPoints(PathBuf, PathBuf),
Surface(MeshBuilder),
}
impl Build for EmitterBuilder {
type Inst = Emitter;
#[inline]
fn build(self, in_dir: &Path) -> Result<Self::Inst, Error> {
Ok(match self {
Self::Beam(pos, dir) => Self::Inst::new_beam(Ray::new(pos, dir)),
Self::Points(points_path) => {
let table = Table::load(&in_dir.join(points_path))?;
let points = table
.into_inner()
.iter()
.map(|row| Pos3::new(row[X], row[Y], row[Z]))
.collect();
Self::Inst::new_points(points)
}
Self::WeightedPoints(points_path, weight_path) => {
let points_data = Table::load(&in_dir.join(points_path))?;
let points = points_data
.into_inner()
.iter()
.map(|row| Pos3::new(row[X], row[Y], row[Z]))
.collect();
let weights_data = Table::load(&in_dir.join(weight_path))?;
let weights: Vec<_> = weights_data.into_inner().iter().map(|row| row[X]).collect();
Self::Inst::new_weighted_points(points, &weights)
}
Self::Surface(mesh) => Self::Inst::new_surface(mesh.build(in_dir)?),
})
}
}