pub struct Polar { /* private fields */ }Expand description
A boat’s expected speed for every true wind angle and speed on a grid.
Symmetric port/starboard by construction: every lookup folds its own
angle to 0..=180 first – see Polar::boat_speed_kn – because a
hull does not sail differently on the other tack.
Implementations§
Source§impl Polar
impl Polar
Sourcepub fn new(
tws_kn: Vec<f64>,
twa_deg: Vec<f64>,
boat_speed_kn: Vec<Vec<f64>>,
) -> Result<Self, PolarError>
pub fn new( tws_kn: Vec<f64>, twa_deg: Vec<f64>, boat_speed_kn: Vec<Vec<f64>>, ) -> Result<Self, PolarError>
Builds a table from its own axes and the speed at every intersection.
§Errors
PolarError::InvalidShape when either axis has fewer than two
points, either axis is not strictly ascending, twa_deg strays
outside 0..=180, or boat_speed_kn’s own shape does not match
twa_deg.len() rows of tws_kn.len() columns each.
Sourcepub fn parse(text: &str) -> Result<Self, PolarError>
pub fn parse(text: &str) -> Result<Self, PolarError>
Parses the common tab/space-separated polar table format: a header
row of wind speeds (its own first cell, conventionally twa/tws,
ignored), then one row per wind angle – the angle itself, then
one boat speed per wind speed column, in the same order as the
header.
§Errors
PolarError::Malformed when the text does not have this shape
at all; PolarError::InvalidShape when Polar::new’s own
checks fail on what was read.
Sourcepub fn boat_speed_kn(&self, twa_deg: f64, tws_kn: f64) -> f64
pub fn boat_speed_kn(&self, twa_deg: f64, tws_kn: f64) -> f64
The boat’s expected speed at twa_deg/tws_kn, bilinearly
interpolated between the table’s own grid points.
twa_deg is folded to 0..=180 first – see this type’s own doc
on why the table itself only ever states one side. A wind speed or
angle outside the table’s own range is clamped to its nearest edge
rather than extrapolated: a polar has no honest opinion about a
wind speed nobody sailed it in.
Sourcepub fn vmg_to_wind_kn(&self, twa_deg: f64, tws_kn: f64) -> f64
pub fn vmg_to_wind_kn(&self, twa_deg: f64, tws_kn: f64) -> f64
Velocity made good directly to windward at twa_deg/tws_kn,
using this table’s own predicted boat speed –
sailing::vmg_to_wind_kn fed from Polar::boat_speed_kn
rather than a measured one.
Sourcepub fn best_upwind_angle_deg(&self, tws_kn: f64) -> f64
pub fn best_upwind_angle_deg(&self, tws_kn: f64) -> f64
The true wind angle that makes the most progress to windward at
tws_kn, searched across the upwind half of the table (0..90)
– the “actual” beat angle real laylines can offer once a polar
exists, in place of a mariner-stated constant.
Scanned in fine steps rather than solved analytically: a polar’s own boat-speed curve has no closed form, and VMG-to-wind is unimodal across a beat for every real polar this was checked against, so a dense scan finds the same peak an analytic solver would, without needing one.
Sourcepub fn best_downwind_angle_deg(&self, tws_kn: f64) -> f64
pub fn best_downwind_angle_deg(&self, tws_kn: f64) -> f64
The true wind angle that makes the most progress downwind at
tws_kn, searched across 90..180 – the downwind counterpart to
Polar::best_upwind_angle_deg, for a boat whose polar makes
sailing angles downwind faster than a dead run.
Sourcepub fn tws_kn(&self) -> &[f64]
pub fn tws_kn(&self) -> &[f64]
The wind speeds this table is defined at, knots, ascending.
For a caller that wants to walk the table’s own grid – writing it
back out, whether as Polar::to_text or in another shape
entirely, such as Signal K’s own performance.polars.
Sourcepub fn twa_deg(&self) -> &[f64]
pub fn twa_deg(&self) -> &[f64]
The wind angles this table is defined at, degrees 0..=180,
ascending. See Polar::tws_kn for why this is exposed.
Sourcepub fn to_text(&self) -> String
pub fn to_text(&self) -> String
Writes this table back out in the same tab-separated format
Polar::parse reads. Polar::parse(&polar.to_text()) round
trips, to the precision written – the format an unrelated
mariner’s own sailing software can most likely already open.