#[repr(C)]pub struct FFIMonteCarloResults {
pub ranges: *mut c_double,
pub impact_velocities: *mut c_double,
pub impact_positions_x: *mut c_double,
pub impact_positions_y: *mut c_double,
pub impact_positions_z: *mut c_double,
pub num_results: c_int,
pub mean_range: c_double,
pub std_dev_range: c_double,
pub mean_impact_velocity: c_double,
pub std_dev_impact_velocity: c_double,
pub hit_probability: c_double,
}Expand description
Monte Carlo simulation results, one entry per simulated shot.
Every array holds num_results doubles and all of them are indexed by the same sample
number.
The impact_positions_* arrays are DEVIATIONS, not positions. Each triple is the
sample’s offset from the baseline point of aim, measured in the target plane (the plane at
the requested target distance), in METERS — see crate::MonteCarloResults::impact_positions.
A triple of zeros means “exactly on the point of aim”, not “at the muzzle”.
Axes follow FFITrajectoryPoint:
| field | axis | use for dispersion? |
|---|---|---|
impact_positions_z | HORIZONTAL / windage deviation, + right | YES — this is the horizontal dispersion axis |
impact_positions_y | VERTICAL deviation, + up | YES — this is the vertical dispersion axis |
impact_positions_x | downrange, and the target plane sits at a FIXED downrange | NO — never a dispersion axis |
Consumers ported from engine 0.13.x (X lateral, Z downrange) commonly read
impact_positions_x as the horizontal spread. Under this convention that reads the
downrange component instead, which is not scatter, and it fails silently.
§Filter the shortfall sentinel before computing any statistic
A sample that never reached the target plane has no deviation to report, so it is encoded as
(0, TARGET_NOT_REACHED_SENTINEL_M, 0) — the Y component is
crate::TARGET_NOT_REACHED_SENTINEL_M (-1.0e9 meters) — which keeps these arrays the same
length as ranges and impact_velocities. The engine does NOT drop those entries for you.
A sample is a finite arrival exactly when
crate::MonteCarloResults::position_reached_target accepts it: every component finite AND
the Y component not equal to the sentinel.
Feeding an unfiltered array into a mean or standard deviation drags the result toward
-1e9 and produces a plainly absurd group size. Exclude sentinel samples from dispersion
statistics, but keep them in the denominator for hit probability — they are definite misses,
which is how hit_probability already counts them.
Fields§
§ranges: *mut c_double§impact_velocities: *mut c_double§impact_positions_x: *mut c_doubleDownrange component of the target-plane deviation, meters. NOT a dispersion axis; see the struct docs.
impact_positions_y: *mut c_doubleVERTICAL deviation from the point of aim, meters, positive up — and the field carrying
the shortfall marker: crate::TARGET_NOT_REACHED_SENTINEL_M (-1.0e9) marks a sample
that did not reach the target plane. Exclude those from dispersion statistics but retain
them as misses for probability calculations. See the struct docs.
impact_positions_z: *mut c_doubleHORIZONTAL / windage deviation from the point of aim, meters, positive right. This is the horizontal dispersion axis; see the struct docs.
num_results: c_int§mean_range: c_double§std_dev_range: c_double§mean_impact_velocity: c_double§std_dev_impact_velocity: c_double§hit_probability: c_doubleAuto Trait Implementations§
impl Freeze for FFIMonteCarloResults
impl RefUnwindSafe for FFIMonteCarloResults
impl !Send for FFIMonteCarloResults
impl !Sync for FFIMonteCarloResults
impl Unpin for FFIMonteCarloResults
impl UnwindSafe for FFIMonteCarloResults
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read more§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.