bevy_math/primitives/
inset.rs1use crate::{
2 ops,
3 primitives::{
4 Capsule2d, Circle, CircularSegment, Primitive2d, Rectangle, RegularPolygon, Rhombus,
5 Triangle2d,
6 },
7 Vec2,
8};
9
10pub trait Inset: Primitive2d {
16 fn inset(self, distance: f32) -> Self;
24}
25
26impl Inset for Circle {
27 fn inset(mut self, distance: f32) -> Self {
28 self.radius -= distance;
29 self
30 }
31}
32
33impl Inset for Triangle2d {
34 fn inset(self, distance: f32) -> Self {
35 fn find_inset_point(a: Vec2, b: Vec2, c: Vec2, distance: f32) -> Vec2 {
36 let unit_vector_ab = (b - a).normalize();
37 let unit_vector_ac = (c - a).normalize();
38 let half_angle_bac = unit_vector_ab.angle_to(unit_vector_ac) / 2.0;
39 let mean = (unit_vector_ab + unit_vector_ac) / 2.0;
40 let direction = mean.normalize();
41 let magnitude = distance / ops::sin(half_angle_bac);
42 a + direction * magnitude
43 }
44
45 let [a, b, c] = self.vertices;
46
47 let new_a = find_inset_point(a, b, c, distance);
48 let new_b = find_inset_point(b, c, a, distance);
49 let new_c = find_inset_point(c, a, b, distance);
50
51 Self::new(new_a, new_b, new_c)
52 }
53}
54
55impl Inset for Rhombus {
56 fn inset(mut self, distance: f32) -> Self {
57 let [half_width, half_height] = self.half_diagonals.into();
58 let angle = ops::atan(half_height / half_width);
59 let x_offset = distance / ops::sin(angle);
60 let y_offset = distance / ops::cos(angle);
61 self.half_diagonals -= Vec2::new(x_offset, y_offset);
62 self
63 }
64}
65
66impl Inset for Capsule2d {
67 fn inset(mut self, distance: f32) -> Self {
68 self.radius -= distance;
69 self
70 }
71}
72
73impl Inset for Rectangle {
74 fn inset(mut self, distance: f32) -> Self {
75 self.half_size -= Vec2::splat(distance);
76 self
77 }
78}
79
80impl Inset for CircularSegment {
81 fn inset(self, distance: f32) -> Self {
82 let old_arc = self.arc;
83 let radius = old_arc.radius - distance;
84 let apothem = old_arc.apothem() + distance;
85 let half_angle = ops::acos(apothem / radius);
87 Self::new(radius, half_angle)
88 }
89}
90
91impl Inset for RegularPolygon {
92 fn inset(mut self, distance: f32) -> Self {
93 let half_angle = self.internal_angle_radians() / 2.0;
94 let offset = distance / ops::sin(half_angle);
95 self.circumcircle.radius -= offset;
96 self
97 }
98}