pub trait ShapeSample {
type Output;
// Required methods
fn sample_interior<R>(&self, rng: &mut R) -> Self::Output
where R: Rng + ?Sized;
fn sample_boundary<R>(&self, rng: &mut R) -> Self::Output
where R: Rng + ?Sized;
// Provided methods
fn interior_dist(self) -> impl Distribution<Self::Output>
where Self: Sized { ... }
fn boundary_dist(self) -> impl Distribution<Self::Output>
where Self: Sized { ... }
}Expand description
Exposes methods to uniformly sample a variety of primitive shapes.
Required Associated Types§
Required Methods§
Sourcefn sample_interior<R>(&self, rng: &mut R) -> Self::Output
fn sample_interior<R>(&self, rng: &mut R) -> Self::Output
Uniformly sample a point from inside the area/volume of this shape, centered on 0.
Shapes like Cylinder, Capsule2d and Capsule3d are oriented along the y-axis.
§Example
let square = Rectangle::new(2.0, 2.0);
// Returns a Vec2 with both x and y between -1 and 1.
println!("{}", square.sample_interior(&mut rand::rng()));Sourcefn sample_boundary<R>(&self, rng: &mut R) -> Self::Output
fn sample_boundary<R>(&self, rng: &mut R) -> Self::Output
Uniformly sample a point from the surface of this shape, centered on 0.
Shapes like Cylinder, Capsule2d and Capsule3d are oriented along the y-axis.
§Example
let square = Rectangle::new(2.0, 2.0);
// Returns a Vec2 where one of the coordinates is at ±1,
// and the other is somewhere between -1 and 1.
println!("{}", square.sample_boundary(&mut rand::rng()));Provided Methods§
Sourcefn interior_dist(self) -> impl Distribution<Self::Output>where
Self: Sized,
fn interior_dist(self) -> impl Distribution<Self::Output>where
Self: Sized,
Extract a Distribution whose samples are points of this shape’s interior, taken uniformly.
§Example
let square = Rectangle::new(2.0, 2.0);
let rng = rand::rng();
// Iterate over points randomly drawn from `square`'s interior:
for random_val in square.interior_dist().sample_iter(rng).take(5) {
println!("{}", random_val);
}Examples found in repository?
examples/math/random_sampling.rs (line 188)
137fn handle_keypress(
138 mut commands: Commands,
139 keyboard: Res<ButtonInput<KeyCode>>,
140 mut mode: ResMut<Mode>,
141 shape: Res<SampledShape>,
142 mut random_source: ResMut<RandomSource>,
143 sample_mesh: Res<PointMesh>,
144 sample_material: Res<PointMaterial>,
145 samples: Query<Entity, With<SamplePoint>>,
146) {
147 // R => restart, deleting all samples
148 if keyboard.just_pressed(KeyCode::KeyR) {
149 for entity in &samples {
150 commands.entity(entity).despawn();
151 }
152 }
153
154 // S => sample once
155 if keyboard.just_pressed(KeyCode::KeyS) {
156 let rng = &mut random_source.0;
157
158 // Get a single random Vec3:
159 let sample: Vec3 = match *mode {
160 Mode::Interior => shape.0.sample_interior(rng),
161 Mode::Boundary => shape.0.sample_boundary(rng),
162 };
163
164 // Spawn a sphere at the random location:
165 commands.spawn((
166 Mesh3d(sample_mesh.0.clone()),
167 MeshMaterial3d(sample_material.0.clone()),
168 Transform::from_translation(sample),
169 SamplePoint,
170 ));
171
172 // NOTE: The point is inside the cube created at setup just because of how the
173 // scene is constructed; in general, you would want to use something like
174 // `cube_transform.transform_point(sample)` to get the position of where the sample
175 // would be after adjusting for the position and orientation of the cube.
176 //
177 // If the spawned point also needed to follow the position of the cube as it moved,
178 // then making it a child entity of the cube would be a good approach.
179 }
180
181 // D => generate many samples
182 if keyboard.just_pressed(KeyCode::KeyD) {
183 let mut rng = &mut random_source.0;
184
185 // Get 100 random Vec3s:
186 let samples: Vec<Vec3> = match *mode {
187 Mode::Interior => {
188 let dist = shape.0.interior_dist();
189 dist.sample_iter(&mut rng).take(100).collect()
190 }
191 Mode::Boundary => {
192 let dist = shape.0.boundary_dist();
193 dist.sample_iter(&mut rng).take(100).collect()
194 }
195 };
196
197 // For each sample point, spawn a sphere:
198 for sample in samples {
199 commands.spawn((
200 Mesh3d(sample_mesh.0.clone()),
201 MeshMaterial3d(sample_material.0.clone()),
202 Transform::from_translation(sample),
203 SamplePoint,
204 ));
205 }
206
207 // NOTE: See the previous note above regarding the positioning of these samples
208 // relative to the transform of the cube containing them.
209 }
210
211 // M => toggle mode between interior and boundary.
212 if keyboard.just_pressed(KeyCode::KeyM) {
213 match *mode {
214 Mode::Interior => *mode = Mode::Boundary,
215 Mode::Boundary => *mode = Mode::Interior,
216 }
217 }
218}Sourcefn boundary_dist(self) -> impl Distribution<Self::Output>where
Self: Sized,
fn boundary_dist(self) -> impl Distribution<Self::Output>where
Self: Sized,
Extract a Distribution whose samples are points of this shape’s boundary, taken uniformly.
§Example
let square = Rectangle::new(2.0, 2.0);
let rng = rand::rng();
// Iterate over points randomly drawn from `square`'s boundary:
for random_val in square.boundary_dist().sample_iter(rng).take(5) {
println!("{}", random_val);
}Examples found in repository?
examples/math/random_sampling.rs (line 192)
137fn handle_keypress(
138 mut commands: Commands,
139 keyboard: Res<ButtonInput<KeyCode>>,
140 mut mode: ResMut<Mode>,
141 shape: Res<SampledShape>,
142 mut random_source: ResMut<RandomSource>,
143 sample_mesh: Res<PointMesh>,
144 sample_material: Res<PointMaterial>,
145 samples: Query<Entity, With<SamplePoint>>,
146) {
147 // R => restart, deleting all samples
148 if keyboard.just_pressed(KeyCode::KeyR) {
149 for entity in &samples {
150 commands.entity(entity).despawn();
151 }
152 }
153
154 // S => sample once
155 if keyboard.just_pressed(KeyCode::KeyS) {
156 let rng = &mut random_source.0;
157
158 // Get a single random Vec3:
159 let sample: Vec3 = match *mode {
160 Mode::Interior => shape.0.sample_interior(rng),
161 Mode::Boundary => shape.0.sample_boundary(rng),
162 };
163
164 // Spawn a sphere at the random location:
165 commands.spawn((
166 Mesh3d(sample_mesh.0.clone()),
167 MeshMaterial3d(sample_material.0.clone()),
168 Transform::from_translation(sample),
169 SamplePoint,
170 ));
171
172 // NOTE: The point is inside the cube created at setup just because of how the
173 // scene is constructed; in general, you would want to use something like
174 // `cube_transform.transform_point(sample)` to get the position of where the sample
175 // would be after adjusting for the position and orientation of the cube.
176 //
177 // If the spawned point also needed to follow the position of the cube as it moved,
178 // then making it a child entity of the cube would be a good approach.
179 }
180
181 // D => generate many samples
182 if keyboard.just_pressed(KeyCode::KeyD) {
183 let mut rng = &mut random_source.0;
184
185 // Get 100 random Vec3s:
186 let samples: Vec<Vec3> = match *mode {
187 Mode::Interior => {
188 let dist = shape.0.interior_dist();
189 dist.sample_iter(&mut rng).take(100).collect()
190 }
191 Mode::Boundary => {
192 let dist = shape.0.boundary_dist();
193 dist.sample_iter(&mut rng).take(100).collect()
194 }
195 };
196
197 // For each sample point, spawn a sphere:
198 for sample in samples {
199 commands.spawn((
200 Mesh3d(sample_mesh.0.clone()),
201 MeshMaterial3d(sample_material.0.clone()),
202 Transform::from_translation(sample),
203 SamplePoint,
204 ));
205 }
206
207 // NOTE: See the previous note above regarding the positioning of these samples
208 // relative to the transform of the cube containing them.
209 }
210
211 // M => toggle mode between interior and boundary.
212 if keyboard.just_pressed(KeyCode::KeyM) {
213 match *mode {
214 Mode::Interior => *mode = Mode::Boundary,
215 Mode::Boundary => *mode = Mode::Interior,
216 }
217 }
218}Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.