33#include <wx/datetime.h>
36#include <wx/translation.h>
39#include "model/navutil_base.h"
40#include "model/own_ship.h"
44static wxTimeSpan RoundToMinutes(
const wxTimeSpan &span) {
45 auto minutes = span.GetMinutes() % 60;
46 auto seconds = span.GetSeconds() % 60;
47 if (seconds > 30) minutes += 1;
48 return wxTimeSpan(span.GetHours(), minutes, 0);
51wxString toSDMM(
int NEflag,
double a,
bool hi_precision) {
74 }
else if (NEflag == 2) {
84 switch (g_iSDMMFormat) {
87 if (hi_precision) mpy = mpy * 1000;
89 m = (long)wxRound((a - (
double)d) * mpy);
91 if (!NEflag || NEflag < 1 || NEflag > 2)
94 s.Printf(_T (
"%d%c %02ld.%04ld'" ), d, 0x00B0, m / 10000, m % 10000);
96 s.Printf(_T (
"%d%c %02ld.%01ld'" ), d, 0x00B0, m / 10, m % 10);
100 s.Printf(_T (
"%02d%c %02ld.%04ld' %c" ), d, 0x00B0, m / 10000,
103 s.Printf(_T (
"%03d%c %02ld.%04ld' %c" ), d, 0x00B0, m / 10000,
105 else if (NEflag == 1)
106 s.Printf(_T (
"%02d%c %02ld.%01ld' %c" ), d, 0x00B0, m / 10, (m % 10),
109 s.Printf(_T (
"%03d%c %02ld.%01ld' %c" ), d, 0x00B0, m / 10, (m % 10),
115 s.Printf(_T (
"%03.6f" ),
120 s.Printf(_T (
"%03.4f" ), ang);
123 m = (long)((a - (
double)d) * 60);
125 if (hi_precision) mpy = mpy * 100;
126 long sec = (long)((a - (
double)d - (((double)m) / 60)) * 3600 * mpy);
128 if (!NEflag || NEflag < 1 || NEflag > 2)
131 s.Printf(_T (
"%d%c %ld'%ld.%ld\"" ), d, 0x00B0, m, sec / 1000,
134 s.Printf(_T (
"%d%c %ld'%ld.%ld\"" ), d, 0x00B0, m, sec / 10,
139 s.Printf(_T (
"%02d%c %02ld' %02ld.%03ld\" %c" ), d, 0x00B0, m,
140 sec / 1000, sec % 1000, c);
142 s.Printf(_T (
"%03d%c %02ld' %02ld.%03ld\" %c" ), d, 0x00B0, m,
143 sec / 1000, sec % 1000, c);
144 else if (NEflag == 1)
145 s.Printf(_T (
"%02d%c %02ld' %02ld.%ld\" %c" ), d, 0x00B0, m,
146 sec / 10, sec % 10, c);
148 s.Printf(_T (
"%03d%c %02ld' %02ld.%ld\" %c" ), d, 0x00B0, m,
149 sec / 10, sec % 10, c);
159double toUsrSpeed(
double kts_speed,
int unit) {
161 if (
unit == -1)
unit = g_iSpeedFormat;
167 ret = kts_speed * 1.15078;
170 ret = kts_speed * 1.852;
173 ret = kts_speed * 0.514444444;
182double toUsrWindSpeed(
double kts_wspeed,
int unit) {
184 if (
unit == -1)
unit = g_iWindSpeedFormat;
190 ret = kts_wspeed * 0.514444444;
193 ret = kts_wspeed * 1.15078;
196 ret = kts_wspeed * 1.852;
205double toUsrDistance(
double nm_distance,
int unit) {
207 if (
unit == -1)
unit = g_iDistanceFormat;
213 ret = nm_distance * 1.15078;
216 ret = nm_distance * 1.852;
219 ret = nm_distance * 1852;
222 ret = nm_distance * 6076.12;
225 ret = nm_distance * 1012.68591;
228 ret = nm_distance * 72913.4;
231 ret = nm_distance * 185200;
240double toUsrTemp(
double cel_temp,
int unit) {
242 if (
unit == -1)
unit = g_iTempFormat;
248 ret = (cel_temp * 9.0 / 5.0) + 32;
251 ret = cel_temp + 273.15;
260wxString getUsrTempUnit(
int unit) {
262 if (
unit == -1)
unit = g_iTempFormat;
280wxString getUsrDistanceUnit(
int unit) {
282 if (
unit == -1)
unit = g_iDistanceFormat;
315wxString getUsrSpeedUnit(
int unit) {
317 if (
unit == -1)
unit = g_iSpeedFormat;
338wxString getUsrWindSpeedUnit(
int unit) {
340 if (
unit == -1)
unit = g_iWindSpeedFormat;
358wxString FormatDistanceAdaptive(
double distance) {
360 int unit = g_iDistanceFormat;
361 double usrDistance = toUsrDistance(distance,
unit);
362 if (usrDistance < 0.1 &&
363 (
unit == DISTANCE_KM ||
unit == DISTANCE_MI ||
unit == DISTANCE_NMI)) {
364 unit = (
unit == DISTANCE_MI) ? DISTANCE_FT : DISTANCE_M;
365 usrDistance = toUsrDistance(distance,
unit);
368 if (usrDistance < 5.0) {
369 format = _T(
"%1.2f ");
370 }
else if (usrDistance < 100.0) {
371 format = _T(
"%2.1f ");
372 }
else if (usrDistance < 1000.0) {
373 format = _T(
"%3.0f ");
375 format = _T(
"%4.0f ");
377 result << wxString::Format(format, usrDistance) << getUsrDistanceUnit(
unit);
384double fromUsrSpeed(
double usr_speed,
int unit,
int default_val) {
393 ret = usr_speed / 1.15078;
396 ret = usr_speed / 1.852;
399 ret = usr_speed / 0.514444444;
408double fromUsrDistance(
double usr_distance,
int unit,
int default_val) {
416 ret = usr_distance / 1.15078;
419 ret = usr_distance / 1.852;
422 ret = usr_distance / 1852;
425 ret = usr_distance / 6076.12;
434double toUsrDepth(
double cel_depth,
int unit) {
436 if (
unit == -1)
unit = g_nDepthUnitDisplay;
439 ret = cel_depth / 0.3048;
445 ret = cel_depth / 0.3048 / 6;
454double fromUsrDepth(
double usr_depth,
int unit) {
456 if (
unit == -1)
unit = g_nDepthUnitDisplay;
459 ret = usr_depth * 0.3048;
465 ret = usr_depth * 0.3048 * 6;
474wxString getUsrDepthUnit(
int unit) {
476 if (
unit == -1)
unit = g_nDepthUnitDisplay;
494double vGetLengthOfNormal(pVector2D a, pVector2D b, pVector2D n) {
503 c.x = b->x * (vDotProduct(a, b) / vDotProduct(b, b));
504 c.y = b->y * (vDotProduct(a, b) / vDotProduct(b, b));
508 vSubtractVectors(a, &c, &vNormal);
514 return (vVectorMagnitude(&vNormal));
517double vDotProduct(pVector2D v0, pVector2D v1) {
521 (v0 == NULL || v1 == NULL) ? 0.0 : (v0->x * v1->x) + (v0->y * v1->y);
526pVector2D vAddVectors(pVector2D v0, pVector2D v1, pVector2D v) {
527 if (v0 == NULL || v1 == NULL)
530 v->x = v0->x + v1->x;
531 v->y = v0->y + v1->y;
536pVector2D vSubtractVectors(pVector2D v0, pVector2D v1, pVector2D v) {
537 if (v0 == NULL || v1 == NULL)
540 v->x = v0->x - v1->x;
541 v->y = v0->y - v1->y;
546double vVectorSquared(pVector2D v0) {
552 dS = ((v0->x * v0->x) + (v0->y * v0->y));
556double vVectorMagnitude(pVector2D v0) {
562 dMagnitude = sqrt(vVectorSquared(v0));
578const wxChar *ParseGPXDateTime(wxDateTime &dt,
const wxChar *datetime) {
579 long sign, hrs_west, mins_west;
583 while (isspace(*datetime)) datetime++;
586 if (*datetime == wxT(
'-')) datetime++;
589 if ((end = dt.ParseFormat(datetime, wxT(
"%Y-%m-%dT%T"))) != NULL) {
591 if (*end == 0)
return NULL;
597 else if (*end == wxT(
'Z')) {
603 else if (*end == wxT(
'+') || *end == wxT(
'-')) {
605 if (*end == wxT(
'+'))
612 if (isdigit(*end) && isdigit(*(end + 1)) && *(end + 2) == wxT(
':')) {
614 wxString(end).ToLong(&hrs_west);
615 if (hrs_west > 12)
return NULL;
619 if (isdigit(*end) && isdigit(*(end + 1))) {
623 mins[1] = *(end + 1);
625 wxString(mins).ToLong(&mins_west);
626 if (mins_west > 59)
return NULL;
629 dt -= sign * wxTimeSpan(hrs_west, mins_west, 0, 0);
646wxString formatTimeDelta(wxTimeSpan span) {
652 if (span.GetHours() > 0) span = RoundToMinutes(span);
653 if (span.GetDays() > 0) ss << setw(2) << span.GetDays() <<
"d ";
654 if (span.GetHours() > 0) {
655 ss << setw(2) << span.GetHours() % 24 << _(
"H ");
656 ss << setw(2) << span.GetMinutes() % 60 << _(
"M");
658 ss << setw(2) << span.GetMinutes() % 60 << _(
"M ");
659 ss << setw(2) << span.GetSeconds() % 60 << _(
"S");
664wxString formatTimeDelta(wxDateTime startTime, wxDateTime endTime) {
666 if (startTime.IsValid() && endTime.IsValid()) {
667 wxTimeSpan span = endTime - startTime;
668 return formatTimeDelta(span);
674wxString formatTimeDelta(wxLongLong secs) {
677 wxTimeSpan span(0, 0, secs);
678 return formatTimeDelta(span);
682wxString GpxDocument::GetUUID(
void) {
687 int time_hi_and_version;
688 int clock_seq_hi_and_rsv;
694 uuid.time_low = GetRandomNumber(
697 uuid.time_mid = GetRandomNumber(0, 65535);
698 uuid.time_hi_and_version = GetRandomNumber(0, 65535);
699 uuid.clock_seq_hi_and_rsv = GetRandomNumber(0, 255);
700 uuid.clock_seq_low = GetRandomNumber(0, 255);
701 uuid.node_hi = GetRandomNumber(0, 65535);
702 uuid.node_low = GetRandomNumber(0, 2147483647);
706 uuid.clock_seq_hi_and_rsv = (uuid.clock_seq_hi_and_rsv & 0x3F) | 0x80;
710 uuid.time_hi_and_version = (uuid.time_hi_and_version & 0x0fff) | 0x4000;
712 str.Printf(_T(
"%08x-%04x-%04x-%02x%02x-%04x%08x"), uuid.time_low,
713 uuid.time_mid, uuid.time_hi_and_version, uuid.clock_seq_hi_and_rsv,
714 uuid.clock_seq_low, uuid.node_hi, uuid.node_low);
719int GpxDocument::GetRandomNumber(
int range_min,
int range_max) {
720 long u = (long)wxRound(
721 ((
double)rand() / ((
double)(RAND_MAX) + 1) * (range_max - range_min)) +
748double fromDMM(wxString sdms) {
752 double stk[32], sign = 1;
757 replhelper = wxString::FromUTF8(
"´·");
758 sdms.Replace(replhelper, _T(
"."));
760 wxString::FromUTF8(
"\"·");
761 sdms.Replace(replhelper, _T(
"."));
762 replhelper = wxString::FromUTF8(
"·");
763 sdms.Replace(replhelper, _T(
"."));
766 wxString::FromUTF8(
"s. š.");
768 sdms.Replace(replhelper, _T(
"N"));
769 replhelper = wxString::FromUTF8(
"j. š.");
770 sdms.Replace(replhelper, _T(
"S"));
771 sdms.Replace(_T(
"v. d."), _T(
"E"));
772 sdms.Replace(_T(
"z. d."), _T(
"W"));
777 if (sdms.Contains(_T(
"N")) || sdms.Contains(_T(
"S")) ||
778 sdms.Contains(_T(
"E")) || sdms.Contains(_T(
"W")))
779 sdms.Replace(_T(
"-"), _T(
" "));
781 wcsncpy(buf, sdms.wc_str(wxConvUTF8), 63);
783 len = wxMin(wcslen(buf),
sizeof(narrowbuf) - 1);
786 for (i = 0; i < len; i++) {
788 if ((c >=
'0' && c <=
'9') || c ==
'-' || c ==
'.' || c ==
'+') {
796 if ((c | 32) ==
'w' || (c | 32) ==
's')
802 stk[0] = stk[1] = stk[2] = 0;
803 for (i = 0; i < len; i++) {
804 while (i < len && narrowbuf[i] == 0) i++;
806 stk[top++] = atof(narrowbuf + i);
807 i += strlen(narrowbuf + i);
811 return sign * (stk[0] + (stk[1] + stk[2] / 60) / 60);
814double toMagnetic(
double deg_true) {
815 if (!std::isnan(gVar)) {
816 if ((deg_true - gVar) > 360.)
817 return (deg_true - gVar - 360.);
819 return ((deg_true - gVar) >= 0.) ? (deg_true - gVar)
820 : (deg_true - gVar + 360.);
822 if ((deg_true - g_UserVar) > 360.)
823 return (deg_true - g_UserVar - 360.);
825 return ((deg_true - g_UserVar) >= 0.) ? (deg_true - g_UserVar)
826 : (deg_true - g_UserVar + 360.);
830double toMagnetic(
double deg_true,
double variation) {
831 double degm = deg_true - variation;
835 return degm >= 0. ? degm : degm + 360.;