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
impl HoldCurve
Sourcepub const SAMPLE_INTERVAL_M: f64 = 0.9144
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.
Sourcepub fn solve(
load: &HoldCurveLoad,
max_range_m: f64,
) -> Result<Self, Box<dyn Error>>
pub fn solve( load: &HoldCurveLoad, max_range_m: f64, ) -> Result<Self, Box<dyn Error>>
Solve once and sample out to max_range_m.
Sourcepub fn max_sampled_range_m(&self) -> f64
pub fn max_sampled_range_m(&self) -> f64
The furthest range this curve reaches, meters.
Sourcepub fn sample_ranges_m(&self) -> Vec<f64>
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.”
Sourcepub fn at_range(&self, range_m: f64) -> Option<HoldPoint>
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).
Sourcepub fn far_zero_range_m(&self) -> f64
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.
Sourcepub fn range_for_angular_drop_mil(&self, target_mil: f64) -> MarkToRangeOutcome
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§
impl Freeze for HoldCurve
impl RefUnwindSafe for HoldCurve
impl Send for HoldCurve
impl Sync for HoldCurve
impl Unpin for HoldCurve
impl UnwindSafe for HoldCurve
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.