mirror of
https://github.com/bevyengine/bevy
synced 2024-11-23 13:13:49 +00:00
Implement Measured2d
for Arc2d
-based primitives. (#16213)
# Objective - `CircularSegment` and `CircularSector` are well defined 2D shapes with both an area and a perimeter. # Solution - This PR implements `perimeter` for both and moves the existsing `area` functions into the `Measured2d` implementations. ## Testing - The `arc_tests` have been extended to also check for perimeters.
This commit is contained in:
parent
1970b819f0
commit
d7f2e431e5
1 changed files with 42 additions and 12 deletions
|
@ -292,6 +292,22 @@ impl Default for CircularSector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Measured2d for CircularSector {
|
||||||
|
#[inline(always)]
|
||||||
|
fn area(&self) -> f32 {
|
||||||
|
self.arc.radius.squared() * self.arc.half_angle
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn perimeter(&self) -> f32 {
|
||||||
|
if self.half_angle() >= PI {
|
||||||
|
self.arc.radius * 2.0 * PI
|
||||||
|
} else {
|
||||||
|
2.0 * self.radius() + self.arc_length()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CircularSector {
|
impl CircularSector {
|
||||||
/// Create a new [`CircularSector`] from a `radius` and an `angle`
|
/// Create a new [`CircularSector`] from a `radius` and an `angle`
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -382,12 +398,6 @@ impl CircularSector {
|
||||||
pub fn sagitta(&self) -> f32 {
|
pub fn sagitta(&self) -> f32 {
|
||||||
self.arc.sagitta()
|
self.arc.sagitta()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the area of this sector
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn area(&self) -> f32 {
|
|
||||||
self.arc.radius.squared() * self.arc.half_angle
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A primitive representing a circular segment:
|
/// A primitive representing a circular segment:
|
||||||
|
@ -425,6 +435,17 @@ impl Default for CircularSegment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Measured2d for CircularSegment {
|
||||||
|
#[inline(always)]
|
||||||
|
fn area(&self) -> f32 {
|
||||||
|
0.5 * self.arc.radius.squared() * (self.arc.angle() - ops::sin(self.arc.angle()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn perimeter(&self) -> f32 {
|
||||||
|
self.chord_length() + self.arc_length()
|
||||||
|
}
|
||||||
|
}
|
||||||
impl CircularSegment {
|
impl CircularSegment {
|
||||||
/// Create a new [`CircularSegment`] from a `radius`, and an `angle`
|
/// Create a new [`CircularSegment`] from a `radius`, and an `angle`
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -515,17 +536,12 @@ impl CircularSegment {
|
||||||
pub fn sagitta(&self) -> f32 {
|
pub fn sagitta(&self) -> f32 {
|
||||||
self.arc.sagitta()
|
self.arc.sagitta()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the area of this segment
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn area(&self) -> f32 {
|
|
||||||
0.5 * self.arc.radius.squared() * (self.arc.angle() - ops::sin(self.arc.angle()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod arc_tests {
|
mod arc_tests {
|
||||||
use core::f32::consts::FRAC_PI_4;
|
use core::f32::consts::FRAC_PI_4;
|
||||||
|
use core::f32::consts::SQRT_2;
|
||||||
|
|
||||||
use approx::assert_abs_diff_eq;
|
use approx::assert_abs_diff_eq;
|
||||||
|
|
||||||
|
@ -548,7 +564,9 @@ mod arc_tests {
|
||||||
is_minor: bool,
|
is_minor: bool,
|
||||||
is_major: bool,
|
is_major: bool,
|
||||||
sector_area: f32,
|
sector_area: f32,
|
||||||
|
sector_perimeter: f32,
|
||||||
segment_area: f32,
|
segment_area: f32,
|
||||||
|
segment_perimeter: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArcTestCase {
|
impl ArcTestCase {
|
||||||
|
@ -581,6 +599,7 @@ mod arc_tests {
|
||||||
assert_abs_diff_eq!(self.apothem, sector.apothem());
|
assert_abs_diff_eq!(self.apothem, sector.apothem());
|
||||||
assert_abs_diff_eq!(self.sagitta, sector.sagitta());
|
assert_abs_diff_eq!(self.sagitta, sector.sagitta());
|
||||||
assert_abs_diff_eq!(self.sector_area, sector.area());
|
assert_abs_diff_eq!(self.sector_area, sector.area());
|
||||||
|
assert_abs_diff_eq!(self.sector_perimeter, sector.perimeter());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_segment(&self, segment: CircularSegment) {
|
fn check_segment(&self, segment: CircularSegment) {
|
||||||
|
@ -593,6 +612,7 @@ mod arc_tests {
|
||||||
assert_abs_diff_eq!(self.apothem, segment.apothem());
|
assert_abs_diff_eq!(self.apothem, segment.apothem());
|
||||||
assert_abs_diff_eq!(self.sagitta, segment.sagitta());
|
assert_abs_diff_eq!(self.sagitta, segment.sagitta());
|
||||||
assert_abs_diff_eq!(self.segment_area, segment.area());
|
assert_abs_diff_eq!(self.segment_area, segment.area());
|
||||||
|
assert_abs_diff_eq!(self.segment_perimeter, segment.perimeter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,7 +635,9 @@ mod arc_tests {
|
||||||
is_minor: true,
|
is_minor: true,
|
||||||
is_major: false,
|
is_major: false,
|
||||||
sector_area: 0.0,
|
sector_area: 0.0,
|
||||||
|
sector_perimeter: 2.0,
|
||||||
segment_area: 0.0,
|
segment_area: 0.0,
|
||||||
|
segment_perimeter: 0.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
tests.check_arc(Arc2d::new(1.0, 0.0));
|
tests.check_arc(Arc2d::new(1.0, 0.0));
|
||||||
|
@ -642,7 +664,9 @@ mod arc_tests {
|
||||||
is_minor: true,
|
is_minor: true,
|
||||||
is_major: false,
|
is_major: false,
|
||||||
sector_area: 0.0,
|
sector_area: 0.0,
|
||||||
|
sector_perimeter: 0.0,
|
||||||
segment_area: 0.0,
|
segment_area: 0.0,
|
||||||
|
segment_perimeter: 0.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
tests.check_arc(Arc2d::new(0.0, FRAC_PI_4));
|
tests.check_arc(Arc2d::new(0.0, FRAC_PI_4));
|
||||||
|
@ -670,7 +694,9 @@ mod arc_tests {
|
||||||
is_minor: true,
|
is_minor: true,
|
||||||
is_major: false,
|
is_major: false,
|
||||||
sector_area: FRAC_PI_4,
|
sector_area: FRAC_PI_4,
|
||||||
|
sector_perimeter: FRAC_PI_2 + 2.0,
|
||||||
segment_area: FRAC_PI_4 - 0.5,
|
segment_area: FRAC_PI_4 - 0.5,
|
||||||
|
segment_perimeter: FRAC_PI_2 + SQRT_2,
|
||||||
};
|
};
|
||||||
|
|
||||||
tests.check_arc(Arc2d::from_turns(1.0, 0.25));
|
tests.check_arc(Arc2d::from_turns(1.0, 0.25));
|
||||||
|
@ -697,7 +723,9 @@ mod arc_tests {
|
||||||
is_minor: true,
|
is_minor: true,
|
||||||
is_major: true,
|
is_major: true,
|
||||||
sector_area: FRAC_PI_2,
|
sector_area: FRAC_PI_2,
|
||||||
|
sector_perimeter: PI + 2.0,
|
||||||
segment_area: FRAC_PI_2,
|
segment_area: FRAC_PI_2,
|
||||||
|
segment_perimeter: PI + 2.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
tests.check_arc(Arc2d::from_radians(1.0, PI));
|
tests.check_arc(Arc2d::from_radians(1.0, PI));
|
||||||
|
@ -724,7 +752,9 @@ mod arc_tests {
|
||||||
is_minor: false,
|
is_minor: false,
|
||||||
is_major: true,
|
is_major: true,
|
||||||
sector_area: PI,
|
sector_area: PI,
|
||||||
|
sector_perimeter: 2.0 * PI,
|
||||||
segment_area: PI,
|
segment_area: PI,
|
||||||
|
segment_perimeter: 2.0 * PI,
|
||||||
};
|
};
|
||||||
|
|
||||||
tests.check_arc(Arc2d::from_degrees(1.0, 360.0));
|
tests.check_arc(Arc2d::from_degrees(1.0, 360.0));
|
||||||
|
|
Loading…
Reference in a new issue