ShapeSample

Trait ShapeSample 

Source
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§

Source

type Output

The type of vector returned by the sample methods, Vec2 for 2D shapes and Vec3 for 3D shapes.

Required Methods§

Source

fn sample_interior<R>(&self, rng: &mut R) -> Self::Output
where R: Rng + ?Sized,

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()));
Source

fn sample_boundary<R>(&self, rng: &mut R) -> Self::Output
where R: Rng + ?Sized,

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§

Source

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}
Source

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.

Implementors§