|
38 | 38 | //!
|
39 | 39 | //! In any case, the [`Rng`] used as the source of randomness must be provided explicitly.
|
40 | 40 |
|
41 |
| -use core::f32::consts::{PI, TAU}; |
| 41 | +use core::f32::consts::{FRAC_PI_2, PI, TAU}; |
42 | 42 |
|
43 | 43 | use crate::{ops, primitives::*, NormedVectorSpace, ScalarField, Vec2, Vec3};
|
44 | 44 | use rand::{
|
@@ -167,6 +167,31 @@ impl ShapeSample for Circle {
|
167 | 167 | }
|
168 | 168 | }
|
169 | 169 |
|
| 170 | +impl ShapeSample for CircularSector { |
| 171 | + type Output = Vec2; |
| 172 | + |
| 173 | + fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec2 { |
| 174 | + let theta = rng.gen_range(-self.half_angle()..=self.half_angle()); |
| 175 | + let r_squared = rng.gen_range(0.0..=(self.radius() * self.radius())); |
| 176 | + let r = ops::sqrt(r_squared); |
| 177 | + let (sin, cos) = ops::sin_cos(theta); |
| 178 | + Vec2::new(r * sin, r * cos) |
| 179 | + } |
| 180 | + |
| 181 | + fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec2 { |
| 182 | + if rng.gen_range(0.0..=1.0) <= self.arc_length() / self.perimeter() { |
| 183 | + // Sample on the arc |
| 184 | + let theta = FRAC_PI_2 + rng.gen_range(-self.half_angle()..self.half_angle()); |
| 185 | + Vec2::from_angle(theta) * self.radius() |
| 186 | + } else { |
| 187 | + // Sample on the "inner" straight lines |
| 188 | + let dir = self.radius() * Vec2::from_angle(FRAC_PI_2 + self.half_angle()); |
| 189 | + let r: f32 = rng.gen_range(-1.0..1.0); |
| 190 | + (-r).clamp(0.0, 1.0) * dir + r.clamp(0.0, 1.0) * dir * Vec2::new(-1.0, 1.0) |
| 191 | + } |
| 192 | + } |
| 193 | +} |
| 194 | + |
170 | 195 | /// Boundary sampling for unit-spheres
|
171 | 196 | #[inline]
|
172 | 197 | fn sample_unit_sphere_boundary<R: Rng + ?Sized>(rng: &mut R) -> Vec3 {
|
|
0 commit comments