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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#![deny(missing_docs)]
extern crate float;
use float::*;
#[derive(Copy, Clone)]
pub struct Viewport {
pub rect: [i32; 4],
pub draw_size: [u32; 2],
pub window_size: [u32; 2],
}
impl Viewport {
pub fn abs_transform<T: Float>(&self) -> [[T; 3]; 2] {
let (dw, dh) = (self.draw_size[0] as f64, self.draw_size[1] as f64);
let (ww, wh) = (self.window_size[0] as f64, self.window_size[1] as f64);
let sx = 2.0 * (dw / ww) / self.rect[2] as f64;
let sy = -2.0 * (dh / wh) / self.rect[3] as f64;
let f = |x| FromPrimitive::from_f64(x);
[
[f(sx), f(0.0), f(-1.0)],
[f(0.0), f(sy), f(1.0)]
]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn abs() {
let transform = |mat: [[f64; 3]; 2], (px, py)| -> (f64, f64) {
(mat[0][0] * px + mat[0][1] * py + mat[0][2],
mat[1][0] * px + mat[1][1] * py + mat[1][2])
};
let viewport = Viewport {
rect: [0, 0, 100, 200],
draw_size: [100, 200],
window_size: [100, 200],
};
let abs = viewport.abs_transform();
assert_eq!(abs, [
[0.02, 0.0, -1.0],
[0.0, -0.01, 1.0]
]);
assert_eq!(transform(abs, (0.0, 0.0)), (-1.0, 1.0));
assert_eq!(transform(abs, (50.0, 100.0)), (0.0, 0.0));
assert_eq!(transform(abs, (100.0, 200.0)), (1.0, -1.0));
let viewport = Viewport {
rect: [10, 10, 80, 80],
draw_size: [100, 100],
window_size: [50, 50],
};
let abs = viewport.abs_transform();
assert_eq!(abs, [
[0.05, 0.0, -1.0],
[0.0, -0.05, 1.0]
]);
assert_eq!(transform(abs, (0.0, 0.0)), (-1.0, 1.0));
assert_eq!(transform(abs, (20.0, 20.0)), (0.0, 0.0));
assert_eq!(transform(abs, (40.0, 40.0)), (1.0, -1.0));
}
}