HoldCurve

Struct HoldCurve 

Source
pub struct HoldCurve { /* private fields */ }
Expand description

A solved, sampled drop-vs-range curve expressed in ANGULAR units (MBA-1361/MBA-1362).

One solve, sampled finely, then read by interpolation — the same shape come-ups uses, but keyed on angle rather than linear drop because that is what a reticle mark is.

This is THE drop-vs-range helper, forward (Self::at_range) and inverse (Self::range_for_angular_drop_mil), and all four consumers go through it: reticle hold --range (MBA-1361) plus mark-to-range, bdc-match and optimal-zero (MBA-1362). Sharing it is the point — three separately-written root finds would be three chances for “the drop at 500 yards” to mean three different things. The future constant-drop range-card ticket is mark-to-range with uniformly spaced marks and should reuse it too rather than growing a fourth.

Implementations§

Source§

impl HoldCurve

Source

pub const SAMPLE_INTERVAL_M: f64 = 0.9144

Sample interval used by every hold curve, meters (~1 yard).

Fine enough that linear interpolation between neighbours is well below the resolution any reticle can be read to, and coarse enough that a 1500 m curve is a few thousand points.

Source

pub fn solve( load: &HoldCurveLoad, max_range_m: f64, ) -> Result<Self, Box<dyn Error>>

Solve once and sample out to max_range_m.

Source

pub fn max_sampled_range_m(&self) -> f64

The furthest range this curve reaches, meters.

Source

pub fn sample_ranges_m(&self) -> Vec<f64>

This curve’s own sample ranges, in order, meters.

Exact multiples of Self::SAMPLE_INTERVAL_M (i as f64 * SAMPLE_INTERVAL_M for i = 0..N), the same arithmetic sequence a caller would otherwise have to reproduce by hand to reason about where this curve was actually verified – an additive accessor so no consumer needs read access to the private samples field just to answer “which ranges did this curve solve at.”

Source

pub fn at_range(&self, range_m: f64) -> Option<HoldPoint>

Linearly interpolate the angular hold at range_m.

None when the range is outside the sampled span or non-positive (an angular drop is undefined at the muzzle — it divides by the range).

Source

pub fn far_zero_range_m(&self) -> f64

The downrange distance of the FAR zero crossing, meters — the point past which angular drop grows monotonically with range.

Angular drop is not monotone over the whole flight: it starts large and positive at the muzzle (the bullet is a sight height below the line of sight, divided by a tiny range), falls through zero at the near zero, goes negative while the bullet rides above the line of sight, and returns through zero at the far zero. Only past that second crossing is the inverse below single-valued, so the search domain starts there rather than at the muzzle.

Source

pub fn range_for_angular_drop_mil(&self, target_mil: f64) -> MarkToRangeOutcome

Invert the curve: the range at which the angular drop equals target_mil.

Bisection over the interpolated curve on [far zero, furthest sample], where drop is monotone increasing in range. Both out-of-domain cases come back as their own outcome rather than as a clamped range.

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.