FFIMonteCarloResults

Struct FFIMonteCarloResults 

Source
#[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:

fieldaxisuse for dispersion?
impact_positions_zHORIZONTAL / windage deviation, + rightYES — this is the horizontal dispersion axis
impact_positions_yVERTICAL deviation, + upYES — this is the vertical dispersion axis
impact_positions_xdownrange, and the target plane sits at a FIXED downrangeNO — 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_double

Downrange component of the target-plane deviation, meters. NOT a dispersion axis; see the struct docs.

§impact_positions_y: *mut c_double

VERTICAL 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_double

HORIZONTAL / 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_double

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.