From 9abb95a3bb87c066a9cb1233b4076b4e09f2a137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lynn=20B=C3=BCttgenbach?= <62256001+lynn-lumen@users.noreply.github.com> Date: Sat, 12 Jul 2025 00:21:50 +0200 Subject: [PATCH] Implement `ShapeSample for CircularSector` --- .../bevy_math/src/sampling/shape_sampling.rs | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/crates/bevy_math/src/sampling/shape_sampling.rs b/crates/bevy_math/src/sampling/shape_sampling.rs index c17bc6fa76600..ba5ad8c4da4bb 100644 --- a/crates/bevy_math/src/sampling/shape_sampling.rs +++ b/crates/bevy_math/src/sampling/shape_sampling.rs @@ -38,7 +38,7 @@ //! //! In any case, the [`Rng`] used as the source of randomness must be provided explicitly. -use core::f32::consts::{PI, TAU}; +use core::f32::consts::{FRAC_PI_2, PI, TAU}; use crate::{ops, primitives::*, NormedVectorSpace, ScalarField, Vec2, Vec3}; use rand::{ @@ -167,6 +167,31 @@ impl ShapeSample for Circle { } } +impl ShapeSample for CircularSector { + type Output = Vec2; + + fn sample_interior(&self, rng: &mut R) -> Vec2 { + let theta = rng.gen_range(-self.half_angle()..=self.half_angle()); + let r_squared = rng.gen_range(0.0..=(self.radius() * self.radius())); + let r = ops::sqrt(r_squared); + let (sin, cos) = ops::sin_cos(theta); + Vec2::new(r * sin, r * cos) + } + + fn sample_boundary(&self, rng: &mut R) -> Vec2 { + if rng.gen_range(0.0..=1.0) <= self.arc_length() / self.perimeter() { + // Sample on the arc + let theta = FRAC_PI_2 + rng.gen_range(-self.half_angle()..self.half_angle()); + Vec2::from_angle(theta) * self.radius() + } else { + // Sample on the "inner" straight lines + let dir = self.radius() * Vec2::from_angle(FRAC_PI_2 + self.half_angle()); + let r: f32 = rng.gen_range(-1.0..1.0); + (-r).clamp(0.0, 1.0) * dir + r.clamp(0.0, 1.0) * dir * Vec2::new(-1.0, 1.0) + } + } +} + /// Boundary sampling for unit-spheres #[inline] fn sample_unit_sphere_boundary(rng: &mut R) -> Vec3 {