34 #include <wx/datetime.h>
36 #include <wx/string.h>
37 #include <wx/translation.h>
40 #include "model/navutil_base.h"
41 #include "model/own_ship.h"
46 static wxTimeSpan RoundToMinutes(
const wxTimeSpan& span) {
47 auto minutes = span.GetMinutes() % 60;
48 auto seconds = span.GetSeconds() % 60;
49 if (seconds > 30) minutes += 1;
50 return wxTimeSpan(span.GetHours(), minutes, 0);
53 wxString toSDMM(
int NEflag,
double a,
bool hi_precision) {
76 }
else if (NEflag == 2) {
86 switch (g_iSDMMFormat) {
89 if (hi_precision) mpy = mpy * 1000;
91 m = (long)wxRound((a - (
double)d) * mpy);
93 if (!NEflag || NEflag < 1 || NEflag > 2)
96 s.Printf(_T (
"%d%c %02ld.%04ld'" ), d, 0x00B0, m / 10000, m % 10000);
98 s.Printf(_T (
"%d%c %02ld.%01ld'" ), d, 0x00B0, m / 10, m % 10);
102 s.Printf(_T (
"%02d%c %02ld.%04ld' %c" ), d, 0x00B0, m / 10000,
105 s.Printf(_T (
"%03d%c %02ld.%04ld' %c" ), d, 0x00B0, m / 10000,
107 else if (NEflag == 1)
108 s.Printf(_T (
"%02d%c %02ld.%01ld' %c" ), d, 0x00B0, m / 10, (m % 10), c);
110 s.Printf(_T (
"%03d%c %02ld.%01ld' %c" ), d, 0x00B0, m / 10, (m % 10), c);
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, sec % 10);
138 s.Printf(_T (
"%02d%c %02ld' %02ld.%03ld\" %c" ), d, 0x00B0, m,
139 sec / 1000, sec % 1000, c);
141 s.Printf(_T (
"%03d%c %02ld' %02ld.%03ld\" %c" ), d, 0x00B0, m,
142 sec / 1000, sec % 1000, c);
143 else if (NEflag == 1)
144 s.Printf(_T (
"%02d%c %02ld' %02ld.%ld\" %c" ), d, 0x00B0, m, sec / 10,
147 s.Printf(_T (
"%03d%c %02ld' %02ld.%ld\" %c" ), d, 0x00B0, m, sec / 10,
158 double toUsrSpeed(
double kts_speed,
int unit) {
160 if (
unit == -1)
unit = g_iSpeedFormat;
166 ret = kts_speed * 1.15078;
169 ret = kts_speed * 1.852;
172 ret = kts_speed * 0.514444444;
181 double toUsrWindSpeed(
double kts_wspeed,
int unit) {
183 if (
unit == -1)
unit = g_iWindSpeedFormat;
189 ret = kts_wspeed * 0.514444444;
192 ret = kts_wspeed * 1.15078;
195 ret = kts_wspeed * 1.852;
204 double toUsrDistance(
double nm_distance,
int unit) {
206 if (
unit == -1)
unit = g_iDistanceFormat;
212 ret = nm_distance * 1.15078;
215 ret = nm_distance * 1.852;
218 ret = nm_distance * 1852;
221 ret = nm_distance * 6076.12;
224 ret = nm_distance * 1012.68591;
227 ret = nm_distance * 72913.4;
230 ret = nm_distance * 185200;
239 double toUsrTemp(
double cel_temp,
int unit) {
241 if (
unit == -1)
unit = g_iTempFormat;
247 ret = (cel_temp * 9.0 / 5.0) + 32;
250 ret = cel_temp + 273.15;
259 wxString getUsrTempUnit(
int unit) {
261 if (
unit == -1)
unit = g_iTempFormat;
279 wxString getUsrDistanceUnit(
int unit) {
281 if (
unit == -1)
unit = g_iDistanceFormat;
315 wxString getUsrSpeedUnit(
int unit) {
317 if (
unit == -1)
unit = g_iSpeedFormat;
338 wxString getUsrWindSpeedUnit(
int unit) {
340 if (
unit == -1)
unit = g_iWindSpeedFormat;
359 wxString FormatDistanceAdaptive(
double distance) {
361 int unit = g_iDistanceFormat;
362 double usrDistance = toUsrDistance(distance,
unit);
363 if (usrDistance < 0.1 &&
364 (
unit == DISTANCE_KM ||
unit == DISTANCE_MI ||
unit == DISTANCE_NMI)) {
365 unit = (
unit == DISTANCE_MI) ? DISTANCE_FT : DISTANCE_M;
366 usrDistance = toUsrDistance(distance,
unit);
369 if (usrDistance < 5.0) {
370 format = _T(
"%1.2f ");
371 }
else if (usrDistance < 100.0) {
372 format = _T(
"%2.1f ");
373 }
else if (usrDistance < 1000.0) {
374 format = _T(
"%3.0f ");
376 format = _T(
"%4.0f ");
378 result << wxString::Format(format, usrDistance) << getUsrDistanceUnit(
unit);
385 double fromUsrSpeed(
double usr_speed,
int unit,
int default_val) {
394 ret = usr_speed / 1.15078;
397 ret = usr_speed / 1.852;
400 ret = usr_speed / 0.514444444;
409 double fromUsrDistance(
double usr_distance,
int unit,
int default_val) {
417 ret = usr_distance / 1.15078;
420 ret = usr_distance / 1.852;
423 ret = usr_distance / 1852;
426 ret = usr_distance / 6076.12;
435 double toUsrDepth(
double cel_depth,
int unit) {
437 if (
unit == -1)
unit = g_nDepthUnitDisplay;
440 ret = cel_depth / 0.3048;
446 ret = cel_depth / 0.3048 / 6;
455 double fromUsrDepth(
double usr_depth,
int unit) {
457 if (
unit == -1)
unit = g_nDepthUnitDisplay;
460 ret = usr_depth * 0.3048;
466 ret = usr_depth * 0.3048 * 6;
475 wxString getUsrDepthUnit(
int unit) {
477 if (
unit == -1)
unit = g_nDepthUnitDisplay;
495 double vGetLengthOfNormal(pVector2D a, pVector2D b, pVector2D n) {
504 c.x = b->x * (vDotProduct(a, b) / vDotProduct(b, b));
505 c.y = b->y * (vDotProduct(a, b) / vDotProduct(b, b));
509 vSubtractVectors(a, &c, &vNormal);
515 return (vVectorMagnitude(&vNormal));
518 double vDotProduct(pVector2D v0, pVector2D v1) {
522 (v0 == NULL || v1 == NULL) ? 0.0 : (v0->x * v1->x) + (v0->y * v1->y);
527 pVector2D vAddVectors(pVector2D v0, pVector2D v1, pVector2D v) {
528 if (v0 == NULL || v1 == NULL)
531 v->x = v0->x + v1->x;
532 v->y = v0->y + v1->y;
537 pVector2D vSubtractVectors(pVector2D v0, pVector2D v1, pVector2D v) {
538 if (v0 == NULL || v1 == NULL)
541 v->x = v0->x - v1->x;
542 v->y = v0->y - v1->y;
547 double vVectorSquared(pVector2D v0) {
553 dS = ((v0->x * v0->x) + (v0->y * v0->y));
557 double vVectorMagnitude(pVector2D v0) {
563 dMagnitude = sqrt(vVectorSquared(v0));
580 const wxChar *ParseGPXDateTime(wxDateTime &dt,
const wxChar *datetime) {
581 long sign, hrs_west, mins_west;
585 while (isspace(*datetime)) datetime++;
588 if (*datetime == wxT(
'-')) datetime++;
591 if ((end = dt.ParseFormat(datetime, wxT(
"%Y-%m-%dT%T"))) != NULL) {
593 if (*end == 0)
return NULL;
599 else if (*end == wxT(
'Z')) {
605 else if (*end == wxT(
'+') || *end == wxT(
'-')) {
607 if (*end == wxT(
'+'))
614 if (isdigit(*end) && isdigit(*(end + 1)) && *(end + 2) == wxT(
':')) {
616 wxString(end).ToLong(&hrs_west);
617 if (hrs_west > 12)
return NULL;
621 if (isdigit(*end) && isdigit(*(end + 1))) {
625 mins[1] = *(end + 1);
627 wxString(mins).ToLong(&mins_west);
628 if (mins_west > 59)
return NULL;
631 dt -= sign * wxTimeSpan(hrs_west, mins_west, 0, 0);
648 wxString formatTimeDelta(wxTimeSpan span) {
654 if (span.GetHours() > 0) span = RoundToMinutes(span);
655 if (span.GetDays() > 0) ss << setw(2) << span.GetDays() <<
"d ";
656 if (span.GetHours() > 0) {
657 ss << setw(2) << span.GetHours() % 24 << _(
"H ");
658 ss << setw(2) << span.GetMinutes() % 60 << _(
"M");
660 ss << setw(2) << span.GetMinutes() % 60 << _(
"M ");
661 ss << setw(2) << span.GetSeconds() % 60 << _(
"S");
666 wxString formatTimeDelta(wxDateTime startTime, wxDateTime endTime) {
668 if (startTime.IsValid() && endTime.IsValid()) {
669 wxTimeSpan span = endTime - startTime;
670 return formatTimeDelta(span);
676 wxString formatTimeDelta(wxLongLong secs) {
679 wxTimeSpan span(0, 0, secs);
680 return formatTimeDelta(span);
684 wxString GpxDocument::GetUUID(
void) {
689 int time_hi_and_version;
690 int clock_seq_hi_and_rsv;
696 uuid.time_low = GetRandomNumber(
699 uuid.time_mid = GetRandomNumber(0, 65535);
700 uuid.time_hi_and_version = GetRandomNumber(0, 65535);
701 uuid.clock_seq_hi_and_rsv = GetRandomNumber(0, 255);
702 uuid.clock_seq_low = GetRandomNumber(0, 255);
703 uuid.node_hi = GetRandomNumber(0, 65535);
704 uuid.node_low = GetRandomNumber(0, 2147483647);
708 uuid.clock_seq_hi_and_rsv = (uuid.clock_seq_hi_and_rsv & 0x3F) | 0x80;
712 uuid.time_hi_and_version = (uuid.time_hi_and_version & 0x0fff) | 0x4000;
714 str.Printf(_T(
"%08x-%04x-%04x-%02x%02x-%04x%08x"), uuid.time_low,
715 uuid.time_mid, uuid.time_hi_and_version, uuid.clock_seq_hi_and_rsv,
716 uuid.clock_seq_low, uuid.node_hi, uuid.node_low);
721 int GpxDocument::GetRandomNumber(
int range_min,
int range_max) {
722 long u = (long)wxRound(
723 ((
double)rand() / ((
double)(RAND_MAX) + 1) * (range_max - range_min)) +
750 double fromDMM(wxString sdms) {
754 double stk[32], sign = 1;
759 replhelper = wxString::FromUTF8(
"´·");
760 sdms.Replace(replhelper, _T(
"."));
762 wxString::FromUTF8(
"\"·");
763 sdms.Replace(replhelper, _T(
"."));
764 replhelper = wxString::FromUTF8(
"·");
765 sdms.Replace(replhelper, _T(
"."));
768 wxString::FromUTF8(
"s. š.");
770 sdms.Replace(replhelper, _T(
"N"));
771 replhelper = wxString::FromUTF8(
"j. š.");
772 sdms.Replace(replhelper, _T(
"S"));
773 sdms.Replace(_T(
"v. d."), _T(
"E"));
774 sdms.Replace(_T(
"z. d."), _T(
"W"));
779 if (sdms.Contains(_T(
"N")) || sdms.Contains(_T(
"S")) ||
780 sdms.Contains(_T(
"E")) || sdms.Contains(_T(
"W")))
781 sdms.Replace(_T(
"-"), _T(
" "));
783 wcsncpy(buf, sdms.wc_str(wxConvUTF8), 63);
785 len = wxMin(wcslen(buf),
sizeof(narrowbuf) - 1);
788 for (i = 0; i < len; i++) {
790 if ((c >=
'0' && c <=
'9') || c ==
'-' || c ==
'.' || c ==
'+') {
798 if ((c | 32) ==
'w' || (c | 32) ==
's')
804 stk[0] = stk[1] = stk[2] = 0;
805 for (i = 0; i < len; i++) {
806 while (i < len && narrowbuf[i] == 0) i++;
808 stk[top++] = atof(narrowbuf + i);
809 i += strlen(narrowbuf + i);
813 return sign * (stk[0] + (stk[1] + stk[2] / 60) / 60);
816 double toMagnetic(
double deg_true) {
817 if (!std::isnan(gVar)) {
818 if ((deg_true - gVar) > 360.)
819 return (deg_true - gVar - 360.);
821 return ((deg_true - gVar) >= 0.) ? (deg_true - gVar) : (deg_true - gVar + 360.);
823 if ((deg_true - g_UserVar) > 360.)
824 return (deg_true - g_UserVar - 360.);
826 return ((deg_true - g_UserVar) >= 0.) ? (deg_true - g_UserVar) : (deg_true - g_UserVar + 360.);
830 double toMagnetic(
double deg_true,
double variation) {
831 double degm = deg_true - variation;
835 return degm >= 0. ? degm : degm + 360.;