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
61
62
63
64
65
66
67
68
69
70
71
72
//!
//! This module implements the transform ops from `gut::ops::transform` for common meshes.
//!

use crate::ops::transform::*;
use super::vertex_positions::VertexPositions;

use math::{BaseFloat, Matrix3, Vector3};

impl<T: BaseFloat, M: VertexPositions<Element = [T; 3]>> Scale<T> for M {
    /// Scale a mesh in 3D by a given vector of scale factors.
    /// `s = [1.0; 3]` corresponds to a noop.
    fn scale(&mut self, [x,y,z]: [T; 3]) {
        for p in self.vertex_position_iter_mut() {
            p[0] *= x;
            p[1] *= y;
            p[2] *= z;
        }
    }
}

impl<T: BaseFloat, M: VertexPositions<Element = [T; 3]>> Rotate<T> for M {
    /// Rotate the mesh using the given column-major rotation matrix.
    fn rotate_by_matrix(&mut self, mtx: [[T; 3]; 3]) {
        let mtx = Matrix3::from(mtx);
        for p in self.vertex_position_iter_mut() {
            let pos = Vector3::from(*p);
            *p = (mtx * pos).into();
        }
    }
}

impl<T: BaseFloat, M: VertexPositions<Element = [T; 3]>> Translate<T> for M {
    /// Translate the mesh by the given translation vector (displacement) `t`.
    fn translate(&mut self, [x,y,z]: [T; 3]) {
        for p in self.vertex_position_iter_mut() {
            p[0] += x;
            p[1] += y;
            p[2] += z;
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use approx::*;
    use crate::ops::*;
    use crate::mesh::builder::*;

    #[test]
    fn rotate_grid() {
        let mut grid = GridBuilder {
            rows: 1,
            cols: 1,
            orientation: AxisPlaneOrientation::ZX,
        }.build();
        grid.rotate([0.0, 1.0, 0.0], std::f64::consts::PI * 0.25);
        let bbox = grid.bounding_box();

        let bound = 2.0_f64.sqrt();
        let minb = bbox.min_corner();
        let maxb = bbox.max_corner();

        assert_relative_eq!(minb[0], -bound);
        assert_eq!(minb[1], 0.0);
        assert_relative_eq!(minb[2], -bound);
        assert_relative_eq!(maxb[0], bound);
        assert_eq!(maxb[1], 0.0);
        assert_relative_eq!(maxb[2], bound);
    }
}