Annulus sampling (#13471)
# Objective Add random sampling for the `Annulus` primitive. This is part of ongoing work to bring the various `bevy_math` primitives to feature parity. ## Solution `Annulus` implements `ShapeSample`. Boundary sampling is implemented in the obvious way, and interior sampling works exactly as in the implementation for `Circle`, using the fact that the square of the radius should be taken uniformly from between r^2 and R^2, where r and R are the inner and outer radii respectively. ## Testing I generated a bunch of random points and rendered them. Here's 1000 points on the interior of the default annulus: <img width="1440" alt="Screenshot 2024-05-22 at 8 01 34 AM" src="https://github.com/bevyengine/bevy/assets/2975848/19c31bb0-edba-477f-b247-2b12d854afae"> This looks kind of weird around the edges, but I verified that they're all actually inside the annulus, so I assume it has to do with the fact that the rendered circles have some radius.
This commit is contained in:
parent
d2ef88f5e8
commit
5dbd827728
@ -191,6 +191,35 @@ impl ShapeSample for Sphere {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ShapeSample for Annulus {
|
||||||
|
type Output = Vec2;
|
||||||
|
|
||||||
|
fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::Output {
|
||||||
|
let inner_radius = self.inner_circle.radius;
|
||||||
|
let outer_radius = self.outer_circle.radius;
|
||||||
|
|
||||||
|
// Like random sampling for a circle, radius is weighted by the square.
|
||||||
|
let r_squared = rng.gen_range((inner_radius * inner_radius)..(outer_radius * outer_radius));
|
||||||
|
let r = r_squared.sqrt();
|
||||||
|
let theta = rng.gen_range(0.0..TAU);
|
||||||
|
|
||||||
|
Vec2::new(r * theta.cos(), r * theta.sin())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::Output {
|
||||||
|
let total_perimeter = self.inner_circle.perimeter() + self.outer_circle.perimeter();
|
||||||
|
let inner_prob = (self.inner_circle.perimeter() / total_perimeter) as f64;
|
||||||
|
|
||||||
|
// Sample from boundary circles, choosing which one by weighting by perimeter:
|
||||||
|
let inner = rng.gen_bool(inner_prob);
|
||||||
|
if inner {
|
||||||
|
self.inner_circle.sample_boundary(rng)
|
||||||
|
} else {
|
||||||
|
self.outer_circle.sample_boundary(rng)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ShapeSample for Rectangle {
|
impl ShapeSample for Rectangle {
|
||||||
type Output = Vec2;
|
type Output = Vec2;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user