8static inline bool isSea (
char * isSeaArray,
double lat,
double lon) {
9 if (isSeaArray == NULL)
return true;
10 int iLon = round (lon * 10 + 1800);
11 int iLat = round (-lat * 10 + 900);
12 return isSeaArray [(iLat * 3601) + iLon];
16static inline bool isSeaTolerant (
char * isSeaArray,
double lat,
double lon) {
17 if (isSeaArray == NULL)
return true;
18 int iLonInf = floor (lon * 10 + 1800);
19 int iLonSup = ceil (lon * 10 + 1800);
20 int iLatInf = floor (-lat * 10 + 900);
21 int iLatSup = ceil (-lat * 10 + 900);
22 return isSeaArray [(iLatInf * 3601) + iLonInf]
23 || isSeaArray [(iLatInf * 3601) + iLonSup]
24 || isSeaArray [(iLatSup * 3601) + iLonInf]
25 || isSeaArray [(iLatSup * 3601) + iLonSup];
30 return remainder (lon, 360.0);
42 if (anteMeridian && lon < 0) lon += 360;
52static inline double fTwd (
double u,
double v) {
54 return (val > 180) ? val - 360 : val;
58static inline double fTws (
double u,
double v) {
64static inline double fTwa (
double heading,
double twd) {
65 double val = fmod ((twd - heading), 360.0);
66 return (val > 180) ? val - 360 : (val < -180) ? val + 360 : val;
70static inline void fAwaAws (
double twa,
double tws,
double sog,
double *awa,
double *aws) {
78static inline double interpolate (
double x,
double x0,
double x1,
double fx0,
double fx1) {
79 if (x1 == x0)
return fx0;
80 else return fx0 + (x-x0) * (fx1-fx0) / (x1-x0);
84static inline double givry (
double lat1,
double lon1,
double lat2,
double lon2) {
85 return (0.5 * (lon1 - lon2)) * sin (0.5 * (lat1 + lat2) *
DEG_TO_RAD);
89static inline double directCap (
double lat1,
double lon1,
double lat2,
double lon2) {
96static inline double orthoCap (
double lat1,
double lon1,
double lat2,
double lon2) {
97 const double avgLat = 0.5 * (lat1 + lat2);
98 const double deltaLat = lat2 - lat1;
99 const double deltaLon = lon2 - lon1;
101 const double cap =
RAD_TO_DEG * atan2 (deltaLon * cos (avgLatRad), deltaLat);
102 const double givryCorrection = -0.5 * deltaLon * sin (avgLatRad);
104 return cap + givryCorrection;
108static inline double orthoCap2 (
double lat1,
double lon1,
double lat2,
double lon2) {
111 double delta_lon = (lon2 - lon1) *
DEG_TO_RAD;
112 double y = sin(delta_lon) * cos(lat2);
113 double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_lon);
115 return fmod(
RAD_TO_DEG * atan2(y, x) + 360.0, 360.0);
119static inline double loxoDist (
double lat1,
double lon1,
double lat2,
double lon2) {
127 double delta_lon = lon2_rad - lon1_rad;
130 double delta_lat = lat2_rad - lat1_rad;
133 double mean_lat = (lat1_rad + lat2_rad) / 2.0;
136 double q = delta_lat / log(tan(
G_PI / 4 + lat2_rad / 2) / tan (
G_PI / 4 + lat1_rad / 2));
139 if (isnan (q)) q = cos (mean_lat);
147static inline double orthoDist(
double lat1,
double lon1,
double lat2,
double lon2) {
152 double cosDist = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(theta);
153 cosDist =
CLAMP (cosDist, -1.0, 1.0);
155 double distRad = acos(cosDist);
161static inline double orthoDist2 (
double lat1,
double lon1,
double lat2,
double lon2) {
164 double dLat = lat2 - lat1;
167 double a = sin(dLat / 2) * sin(dLat / 2) + cos(lat1) * cos(lat2) * sin(dLon / 2) * sin(dLon / 2);
168 double c = 2 * atan2(sqrt(a), sqrt(1 - a));
175 const int nLine = mat->
nLine;
176 const int nCol = mat->
nCol;
177 int l, c, lInf, cInf, lSup, cSup;
180 if (twa > 180.0) twa = 360.0 - twa;
181 else if (twa < 0.0) twa = -twa;
183 for (l = 1; l < nLine; l++) {
184 if (mat->
t [l][0] > twa)
break;
186 lSup = (l < nLine) ? l : nLine - 1;
187 lInf = (l == 1) ? 1 : l - 1;
189 for (c = 1; c < nCol; c++) {
190 if (mat->
t [0][c] > w)
break;
192 cSup = (c < nCol - 1) ? c : nCol - 1;
193 cInf = (c == 1) ? 1 : c - 1;
196 if (sailMat != NULL && sailMat->
nLine == nLine && sailMat->
nCol == nCol) {
197 bestL = ((twa - mat->
t [lInf][0]) < (mat->
t [lSup][0] - twa)) ? lInf : lSup;
198 bestC = ((w - mat->
t [0][cInf]) < (mat->
t [0][cSup] - w)) ? cInf : cSup;
199 *sail = sailMat->
t [bestL][bestC];
203 const double lInf0 = mat->
t [lInf][0];
204 const double lSup0 = mat->
t [lSup][0];
205 double s0 =
interpolate (twa, lInf0, lSup0, mat->
t [lInf][cInf], mat->
t [lSup][cInf]);
206 double s1 =
interpolate (twa, lInf0, lSup0, mat->
t [lInf][cSup], mat->
t [lSup][cSup]);
207 return interpolate (w, mat->
t [0][cInf], mat->
t [0][cSup], s0, s1);
212 const int nLine = mat->
nLine;
217 int mid = low + (high - low) / 2;
218 double midVal = mat->
t[mid][0];
219 if (midVal > val) high = mid;
231 int mid = low + (high - low) / 2;
232 double midVal = row0[mid];
233 if (midVal > val) high = mid;
242 const int nLine = mat->
nLine;
243 const int nCol = mat->
nCol;
244 int l, c, lInf, cInf, lSup, cSup;
247 if (twa > 180.0) twa = 360.0 - twa;
248 else if (twa < 0.0) twa = -twa;
250 for (l = 1; l < nLine; l++) {
251 if (mat->
t [l][0] > twa)
break;
253 lSup = (l < nLine - 1) ? l : nLine - 1;
254 lInf = (l == 1) ? 1 : l - 1;
257 cSup = (c < nCol - 1) ? c : nCol - 1;
258 cInf = (c == 1) ? 1 : c - 1;
261 if (sailMat != NULL && sailMat->
nLine == nLine && sailMat->
nCol == nCol) {
262 bestL = ((twa - mat->
t [lInf][0]) < (mat->
t [lSup][0] - twa)) ? lInf : lSup;
263 bestC = ((w - mat->
t [0][cInf]) < (mat->
t [0][cSup] - w)) ? cInf : cSup;
264 *sail = sailMat->
t [bestL][bestC];
268 const double lInf0 = mat->
t [lInf][0];
269 const double lSup0 = mat->
t [lSup][0];
270 double s0 =
interpolate (twa, lInf0, lSup0, mat->
t [lInf][cInf], mat->
t [lSup][cInf]);
271 double s1 =
interpolate (twa, lInf0, lSup0, mat->
t [lInf][cSup], mat->
t [lSup][cSup]);
272 return interpolate (w, mat->
t [0][cInf], mat->
t [0][cSup], s0, s1);
278 const int nLine = mat->
nLine;
279 const int nCol = mat->
nCol;
280 int l, c, lInf, cInf, lSup, cSup;
283 if (twa > 180.0) twa = 360.0 - twa;
284 else if (twa < 0.0) twa = -twa;
287 lSup = (l < nLine - 1) ? l : (nLine - 1);
288 lInf = (l == 1) ? 1 : (l - 1);
291 cSup = (c < nCol - 1) ? c : nCol - 1;
292 cInf = (c == 1) ? 1 : c - 1;
294 if (sailMat != NULL && sailMat->
nLine == nLine && sailMat->
nCol == nCol) {
295 bestL = ((twa - mat->
t[lInf][0]) < (mat->
t[lSup][0] - twa)) ? lInf : lSup;
296 bestC = ((w - mat->
t[0][cInf]) < (mat->
t[0][cSup] - w)) ? cInf : cSup;
297 *sail = sailMat->
t[bestL][bestC];
300 double lInf0 = mat->
t[lInf][0];
301 double lSup0 = mat->
t[lSup][0];
302 double s0 =
interpolate (twa, lInf0, lSup0, mat->
t [lInf][cInf], mat->
t [lSup][cInf]);
303 double s1 =
interpolate (twa, lInf0, lSup0, mat->
t [lInf][cSup], mat->
t [lSup][cSup]);
304 return interpolate (w, mat->
t [0][cInf], mat->
t [0][cSup], s0, s1);
310 double s0, s1, speed;
311 const int nCol = mat->
nCol;
312 const int nLine = mat->
nLine;
314 const int cSup = (c < nCol - 1) ? c : nCol - 1;
315 const int cInf = (c == 1) ? 1 : c - 1;
317 for (
int l = 1; l < nLine; l++) {
318 s0 = mat->
t[l][cInf];
319 s1 = mat->
t[l][cSup];
320 speed = s0 + (tws - mat->
t [0][cInf]) * (s1 - s0) / (mat->
t [0][cSup] - mat->
t [0][cInf]);
321 if (speed > max) max = speed;
344 double lat2,
double lon2,
346 double *latR,
double *lonR) {
347 if (!latR || !lonR)
return;
350 double total_nm =
orthoDist(lat1, lon1, lat2, lon2);
353 if (total_nm <= 1e-9) {
365 if (d_nm >= total_nm) {
372 double f = d_nm / total_nm;
384 double delta = total_nm / (60.0 *
RAD_TO_DEG);
385 double sin_delta = sin(delta);
387 if (fabs(sin_delta) < 1e-15) {
395 double A = sin((1.0 - f) * delta) / sin_delta;
396 double B = sin(f * delta) / sin_delta;
398 double cos_phi1 = cos(phi1);
399 double cos_phi2 = cos(phi2);
401 double x = A * cos_phi1 * cos(lambda1) + B * cos_phi2 * cos(lambda2);
402 double y = A * cos_phi1 * sin(lambda1) + B * cos_phi2 * sin(lambda2);
403 double z = A * sin(phi1) + B * sin(phi2);
405 double phiR = atan2(z, sqrt(x * x + y * y));
406 double lambdaR = atan2(y, x);
421static inline bool isDay(
double t,
long dataDate,
long dataTime,
double lat,
double lon) {
425 int month = (int)((dataDate % 10000) / 100);
427 if (lat > 75.0)
return (month > 4 && month < 10);
428 if (lat < -75.0)
return !(month > 4 && month < 10);
431 int hour0 = (int)(dataTime / 100);
434 double localHours = hour0 + t + lon / 15.0;
437 localHours = fmod(localHours, 24.0);
438 if (localHours < 0.0) localHours += 24.0;
441 return (localHours >= 6.0) && (localHours <= 18.0);
static bool isInZone(double lat, double lon, Zone *zone)
true if P (lat, lon) is within the zone
static double fTwa(double heading, double twd)
return TWA between -180 and 180 note : tribord amure if twa < 0
static double maxSpeedInPolarAt(double tws, const PolMat *mat)
return max speed of boat at tws for all twa
static bool isSea(char *isSeaArray, double lat, double lon)
this file contains small inlines functions to be included in source files
static double findPolar2(double twa, double w, const PolMat *mat, const PolMat *sailMat, int *sail)
find in polar boat speed or wave coeff and sail number if sailMat != NULL
static int binarySearchTwa(const PolMat *mat, double val)
dichotomic search on column 0 (TWA), using rows [1 .
static double findPolar(double twa, double w, const PolMat *mat, const PolMat *sailMat, int *sail)
find in polar boat speed or wave coeff
static double directCap(double lat1, double lon1, double lat2, double lon2)
return loxodromic cap from origin to destination
static double orthoDist(double lat1, double lon1, double lat2, double lon2)
return orthodromic distance in nautical miles from origin to destination
static double orthoCap(double lat1, double lon1, double lat2, double lon2)
return initial orthodromic cap from origin to destination equivalent to : return directCap (lat1,...
static double orthoDist2(double lat1, double lon1, double lat2, double lon2)
return orthodomic distance in nautical miles from origin to destinationi, Haversine formula time cons...
static double interpolate(double x, double x0, double x1, double fx0, double fx1)
return fx : linear interpolation
static int binarySearchW(const double *row0, int nCol, double val)
dichotomic search on row 0 (wind speed), using columns [1 .
static bool isDay(double t, long dataDate, long dataTime, double lat, double lon)
true if day light, false if night
static double fTwd(double u, double v)
true wind direction
static double lonCanonize(double lon)
return lon on ]-180, 180 ] interval
static double loxoDist(double lat1, double lon1, double lat2, double lon2)
return loxodromic distance in nautical miles from origin to destination
static double findPolar1(double twa, double w, const PolMat *mat, const PolMat *sailMat, int *sail)
find in polar boat speed or wave coeff and sail number if sailMat != NULL
static double fTws(double u, double v)
true wind speed.
static double lonNormalize(double lon, bool anteMeridian)
if antemeridian -180 < lon < 360.
static double givry(double lat1, double lon1, double lat2, double lon2)
return givry correction to apply to direct or loxodromic cap to get orthodromic cap
static void fAwaAws(double twa, double tws, double sog, double *awa, double *aws)
return AWA and AWS Apparent Wind Angle and Speed
static bool isSeaTolerant(char *isSeaArray, double lat, double lon)
say if point is in sea
static double orthoCap2(double lat1, double lon1, double lat2, double lon2)
return initial orthodromic cap from origin to destination, no givry correction
static void orthoFindInterPoint(double lat1, double lon1, double lat2, double lon2, double d_nm, double *latR, double *lonR)
Compute the intermediate point on the great circle from P1 to P2.
Zone zone
geographic zone covered by grib file
double t[MAX_N_POL_MAT_LINES][MAX_N_POL_MAT_COLS]