apply_dsf

Function apply_dsf 

Source
pub fn apply_dsf(result: &mut TrajectoryResult, table: &DsfTable)
Expand description

Apply a DSF table to an already-solved trajectory, IN PLACE, scaling only each point’s drop below the line of sight — in BOTH result.points and, when present, result.sampled_points.

For each point in result.points:

  1. Per-point Mach is point.velocity_magnitude / result.station_speed_of_sound_mps — the same frozen “station” speed of sound the solver itself divides into velocity_magnitude for its own per-point Mach diagnostics (Mach-transition tracking, pitch-damping, precession/nutation; see the “MBA-1136 (rank 30)” comments next to resolved_atmosphere() in cli_api.rs’s integration loops). The engine does NOT store a re-derived per-altitude local speed of sound on TrajectoryPoint itself, so this is “the way the solver does it”, not a sea-level constant and not a new per-point atmosphere recompute. It is also the same divisor the truing observation path uses to derive an observation’s Mach (trajectory_observation.rs), so a DSF point keyed at derivation time lands back on the identical Mach at application time — a per-point local recompute here would skew the two apart.
  2. drop = result.line_of_sight_height_m - point.position.y (drop below the horizontal line of sight, in the solver’s ground-referenced frame — the same drop_offset - y convention cli_api::fit_value_at uses for BC-fit drop curves).
  3. point.position.y is rewritten so that the (possibly rescaled) drop is drop * table.factor_at(mach).

result.sampled_points (populated when --sample-trajectory is requested; read by the Table’s “Sampled Trajectory” section, CSV --full, and the PDF dope card — the PDF dope card always requires sampling) is a SEPARATE Vec<TrajectorySample> from points and was, until MBA-1357 Task 2’s review (Critical #2), left untouched by this function — those outputs silently rendered untrued drops even with an active DSF table. Each TrajectorySample already stores its drop directly as drop_m (the same LOS - actual sign convention derived from points above — see trajectory_sampling.rs’s sample_trajectory doc comment), so no position reconstruction is needed: sample.drop_m is simply multiplied by table.factor_at(mach), with mach computed from sample.velocity_mps via the identical frozen station_speed_of_sound_mps divisor used for points above. This mirrors run_sampled_trajectory‘s (come-ups’ own sampled-trajectory path, main.rs) hand-rolled version of the same transform, so both paths now agree. None stays None — nothing to scale.

Nothing else is touched: position.x (downrange), position.z (windage/lateral), velocity_magnitude, kinetic_energy, and time are byte-identical to their pre-call values on points; distance_m, wind_drift_m, velocity_mps, energy_j, time_s, and flags are byte-identical on sampled_points; every top-level scalar on result itself (time_of_flight, impact_velocity, impact_energy, max_range, max_height, …) is untouched too.