#[unsafe(no_mangle)]pub unsafe extern "C" fn ballistics_calculate_zero_angle(
inputs: *const FFIBallisticInputs,
wind: *const FFIWindConditions,
atmosphere: *const FFIAtmosphericConditions,
zero_distance: c_double,
) -> c_doubleExpand description
Calculate the zero angle for a target distance through the C ABI.
Solves to the classic sight-line zero contract (ZeroTargetFrame::SightLine, MBA-1412):
the target height is sight geometry and the rifle zeroes LEVEL. inputs.shooting_angle
applies to the subsequent shot, not to the zero.
§How this relates to solve-json’s zero_distance_m
Both surfaces aim the search at the same place. This export passes the caller’s
sight_height as the target height; solve-json, handed a zero_distance_m with no
target_height_m, defaults to the line of sight, muzzle_height_m + sight_height_m
(MBA-1537 — before that it defaulted to a flat 0 and the two disagreed by a full sight
height at the zero). For a level rifle at the same station conditions the two now return the
same angle; tests/zero_sight_line_default.rs pins that.
Two deliberate differences remain, neither of which is a defect — see the module documentation for the reasoning and for the numbers:
- Atmosphere. This export goes through
crate::calculate_zero_angle_with_conditions, which applies the legacy default-sentinel heuristic toatmosphere. solve-json goes throughcrate::cli_api::TrajectorySolver::new_with_resolved_station_atmosphereand trusts a supplied station temperature/pressure as given. Feeding both surfaces 15 °C / 1013.25 hPa at 2000 m is about a 0.29 MOA disagreement on a 300 m zero. - Target frame. solve-json’s documented contract (
docs/SOLVE_JSON_V1.md) isWorldVertical— an absolute height above the ground datum, with inclined zeroing projected into the world frame — not this export’sSightLine, which zeroes level and treatsinputs.shooting_angleas a shot-time condition. The frames coincide for a level rifle and diverge onceshooting_angleis nonzero.
A caller that needs solve-json’s semantics over a C ABI should use the JSON bridge
(crate::bridge, src/bridge/ffi.rs) rather than this export.
§Safety
inputs may be null, in which case this function returns NaN. When non-null,
it must point to a valid, properly aligned FFIBallisticInputs that remains
readable and is not mutated for the duration of this call. wind and
atmosphere may also be null; each non-null pointer has the same requirements
for its corresponding type.