geng_utils/
layout.rs

1use geng::prelude::*;
2
3/// Get a point inside the aabb.
4/// (0.0, 0.0) corresponds to min.
5/// (1.0, 1.0) corresponds to max.
6pub fn aabb_pos<T: Float>(aabb: Aabb2<T>, align: vec2<T>) -> vec2<T> {
7    aabb.min + aabb.size() * align
8}
9
10/// Align an aabb of the given size inside another.
11pub fn align_aabb<T: Float>(size: vec2<T>, aabb: Aabb2<T>, align: vec2<T>) -> Aabb2<T> {
12    let half = T::from_f32(0.5);
13    let pos_aabb = aabb.extend_symmetric(-size * half);
14    let pos = aabb_pos(pos_aabb, align);
15    Aabb2::point(pos).extend_symmetric(size * half)
16}
17
18/// Fit an aabb of the given size into the given aabb.
19pub fn fit_aabb<T: Float>(size: vec2<T>, aabb: Aabb2<T>, align: vec2<T>) -> Aabb2<T> {
20    let ratio = aabb.size() / size;
21    let ratio = if ratio.x < ratio.y { ratio.x } else { ratio.y };
22    let fit_size = size * ratio;
23    align_aabb(fit_size, aabb, align)
24}
25
26/// Fit an aabb of the given size by width into the given aabb.
27pub fn fit_aabb_width<T: Float>(size: vec2<T>, aabb: Aabb2<T>, align: T) -> Aabb2<T> {
28    let ratio = aabb.width() / size.x;
29    let fit_size = size * ratio;
30    align_aabb(fit_size, aabb, vec2(T::ZERO, align))
31}
32
33/// Fit an aabb of the given size by height into the given aabb.
34pub fn fit_aabb_height<T: Float>(size: vec2<T>, aabb: Aabb2<T>, align: T) -> Aabb2<T> {
35    let ratio = aabb.height() / size.y;
36    let fit_size = size * ratio;
37    align_aabb(fit_size, aabb, vec2(align, T::ZERO))
38}
39
40#[test]
41fn test_fit_aabb() {
42    let size = vec2(1.0, 1.0);
43
44    let aabb = Aabb2 {
45        min: vec2(0.0, 0.0),
46        max: vec2(10.0, 5.0),
47    };
48    assert_eq!(
49        fit_aabb(size, aabb, vec2::splat(0.0)),
50        Aabb2 {
51            min: vec2(0.0, 0.0),
52            max: vec2(5.0, 5.0),
53        }
54    );
55    assert_eq!(
56        fit_aabb(size, aabb, vec2::splat(0.5)),
57        Aabb2 {
58            min: vec2(2.5, 0.0),
59            max: vec2(7.5, 5.0),
60        }
61    );
62    assert_eq!(
63        fit_aabb(size, aabb, vec2::splat(1.0)),
64        Aabb2 {
65            min: vec2(5.0, 0.0),
66            max: vec2(10.0, 5.0),
67        }
68    );
69
70    let aabb = Aabb2 {
71        min: vec2(0.0, 0.0),
72        max: vec2(5.0, 10.0),
73    };
74    assert_eq!(
75        fit_aabb(size, aabb, vec2::splat(0.0)),
76        Aabb2 {
77            min: vec2(0.0, 0.0),
78            max: vec2(5.0, 5.0),
79        }
80    );
81    assert_eq!(
82        fit_aabb(size, aabb, vec2::splat(0.5)),
83        Aabb2 {
84            min: vec2(0.0, 2.5),
85            max: vec2(5.0, 7.5),
86        }
87    );
88    assert_eq!(
89        fit_aabb(size, aabb, vec2::splat(1.0)),
90        Aabb2 {
91            min: vec2(0.0, 5.0),
92            max: vec2(5.0, 10.0),
93        }
94    );
95}