Skip to main content

box2d_rust/math_functions/
query.rs

1// AABB queries, plane separation, and the spring-damper helper.
2// Part of the math_functions module.
3
4use super::*;
5
6/// Does a fully contain b
7pub fn aabb_contains(a: Aabb, b: Aabb) -> bool {
8    let mut s = true;
9    s = s && a.lower_bound.x <= b.lower_bound.x;
10    s = s && a.lower_bound.y <= b.lower_bound.y;
11    s = s && b.upper_bound.x <= a.upper_bound.x;
12    s = s && b.upper_bound.y <= a.upper_bound.y;
13    s
14}
15
16/// Get the center of the AABB.
17pub fn aabb_center(a: Aabb) -> Vec2 {
18    Vec2 {
19        x: 0.5 * (a.lower_bound.x + a.upper_bound.x),
20        y: 0.5 * (a.lower_bound.y + a.upper_bound.y),
21    }
22}
23
24/// Get the extents of the AABB (half-widths).
25pub fn aabb_extents(a: Aabb) -> Vec2 {
26    Vec2 {
27        x: 0.5 * (a.upper_bound.x - a.lower_bound.x),
28        y: 0.5 * (a.upper_bound.y - a.lower_bound.y),
29    }
30}
31
32/// Union of two AABBs
33pub fn aabb_union(a: Aabb, b: Aabb) -> Aabb {
34    Aabb {
35        lower_bound: Vec2 {
36            x: min_float(a.lower_bound.x, b.lower_bound.x),
37            y: min_float(a.lower_bound.y, b.lower_bound.y),
38        },
39        upper_bound: Vec2 {
40            x: max_float(a.upper_bound.x, b.upper_bound.x),
41            y: max_float(a.upper_bound.y, b.upper_bound.y),
42        },
43    }
44}
45
46/// Do a and b overlap
47pub fn aabb_overlaps(a: Aabb, b: Aabb) -> bool {
48    !(b.lower_bound.x > a.upper_bound.x
49        || b.lower_bound.y > a.upper_bound.y
50        || a.lower_bound.x > b.upper_bound.x
51        || a.lower_bound.y > b.upper_bound.y)
52}
53
54/// Compute the bounding box of an array of points
55pub fn make_aabb(points: &[Vec2], radius: f32) -> Aabb {
56    debug_assert!(!points.is_empty());
57    let mut a = Aabb {
58        lower_bound: points[0],
59        upper_bound: points[0],
60    };
61    for point in &points[1..] {
62        a.lower_bound = min(a.lower_bound, *point);
63        a.upper_bound = max(a.upper_bound, *point);
64    }
65
66    let r = Vec2 {
67        x: radius,
68        y: radius,
69    };
70    a.lower_bound = sub(a.lower_bound, r);
71    a.upper_bound = add(a.upper_bound, r);
72
73    a
74}
75
76/// Signed separation of a point from a plane
77pub fn plane_separation(plane: Plane, point: Vec2) -> f32 {
78    dot(plane.normal, point) - plane.offset
79}
80
81/// One-dimensional mass-spring-damper simulation. Returns the new velocity given the position and time step.
82/// You can then compute the new position using:
83/// position += time_step * new_velocity
84/// This drives towards a zero position. By using implicit integration we get a stable solution
85/// that doesn't require transcendental functions.
86pub fn spring_damper(
87    hertz: f32,
88    damping_ratio: f32,
89    position: f32,
90    velocity: f32,
91    time_step: f32,
92) -> f32 {
93    let omega = 2.0 * PI * hertz;
94    let omega_h = omega * time_step;
95    (velocity - omega * omega_h * position)
96        / (1.0 + 2.0 * damping_ratio * omega_h + omega_h * omega_h)
97}