From c889198d09c1e12ca3a970c854850c294b3403c4 Mon Sep 17 00:00:00 2001 From: Edward d'Auvergne Date: Tue, 14 Jul 2015 18:57:42 +0200 Subject: [PATCH] Redesign of the latitude and longitude formatting for the HUD. This follows from http://thread.gmane.org/gmane.games.flightgear.devel/78650 and resolves the sign bug https://sourceforge.net/p/flightgear/codetickets/1778/ . Combined with a matching change to FGData, this changes the HUD formats from the current set of 3 (note that the text in brackets is not shown in the HUD preferences PUI dialog, but is show here for reference): 0) Decimal degrees (37.618890N -122.375000W) 1) Degrees, minutes (37*37.133N -122*22.500W) 2) Degrees, minutes, seconds (37*37 08.0 N -122*22 30.0 W) to (here the text in brackets will be shown in the PUI dialog): 0) DDD format (37.618890N 122.375000W) 1) DMM format (37*37.133'N 122*22.500'W) 2) DMS format (37*37'08.0"N 122*22'30.0"W) 3) Signed DDD format (37.618890 -122.375000) 4) Signed DMM format (37*37.133' -122*22.500') 5) Signed DMS format (37*37'08.0" -122*22'30.0") 6) Zero padded DDD (51.477500N 000.461389W) 7) Zero padded DMM (51*28.650'N 000*27.683'W) 8) Zero padded DMS (51*28'39.0"N 000*27'41.0"W) 9) Trinity House Navigation (51* 28'.650N 000* 27'.683W) --- src/Main/fg_props.cxx | 165 ++++++++++++++++++++++++++++++------------ 1 file changed, 120 insertions(+), 45 deletions(-) diff --git a/src/Main/fg_props.cxx b/src/Main/fg_props.cxx index 43b3228cb..f348bc3bd 100644 --- a/src/Main/fg_props.cxx +++ b/src/Main/fg_props.cxx @@ -366,85 +366,160 @@ SGConstPropertyNode_ptr FGProperties::_longDeg; SGConstPropertyNode_ptr FGProperties::_latDeg; SGConstPropertyNode_ptr FGProperties::_lonLatformat; -const char * -FGProperties::getLongitudeString () -{ - static char buf[32]; - double d = _longDeg->getDoubleValue(); - int format = _lonLatformat->getIntValue(); - char c = d < 0.0 ? 'W' : 'E'; - d = fabs(d); +/* + * Format the latitude and longitude floats into a character array using a variety of coordinate formats. + */ +static void +formatLatLongString (double deg, int format, char *buf, char c) { + double min, sec; + int sign = deg < 0.0 ? -1 : 1; + deg = fabs(deg); if (format == 0) { - snprintf(buf, 32, "%3.6f%c", d, c); + // d.dddddd' (DDD format). + snprintf(buf, 32, "%3.6f%c", deg, c); } else if (format == 1) { - // dd mm.mmm' (DMM-Format) -- uses a round-off factor tailored to the + // d mm.mmm' (DMM format) -- uses a round-off factor tailored to the // required precision of the minutes field (three decimal places), // preventing minute values of 60. - double min = (d - int(d)) * 60.0; + min = (deg - int(deg)) * 60.0; if (min >= 59.9995) { min -= 60.0; - d += 1.0; + deg += 1.0; } - snprintf(buf, 32, "%d*%06.3f%c", int(d), fabs(min), c); + snprintf(buf, 32, "%d*%06.3f'%c", int(deg), fabs(min), c); - } else { - // mm'ss.s'' (DMS-Format) -- uses a round-off factor tailored to the + } else if (format == 2) { + // d mm'ss.s" (DMS format) -- uses a round-off factor tailored to the // required precision of the seconds field (one decimal place), // preventing second values of 60. - double min = (d - int(d)) * 60.0; - double sec = (min - int(min)) * 60.0; + min = (deg - int(deg)) * 60.0; + sec = (min - int(min)) * 60.0; if (sec >= 59.95) { sec -= 60.0; min += 1.0; if (min >= 60.0) { min -= 60.0; - d += 1.0; + deg += 1.0; } } - snprintf(buf, 32, "%d*%02d %04.1f%c", int(d), - int(min), fabs(sec), c); - } - buf[31] = '\0'; - return buf; -} + snprintf(buf, 32, "%d*%02d'%04.1f\"%c", int(deg), int(min), fabs(sec), c); -const char * -FGProperties::getLatitudeString () -{ - static char buf[32]; - double d = _latDeg->getDoubleValue(); - int format = _lonLatformat->getIntValue(); - char c = d < 0.0 ? 'S' : 'N'; - d = fabs(d); + } else if (format == 3) { + // d.dddddd' (signed DDD format). + snprintf(buf, 32, "%3.6f", sign*deg); - if (format == 0) { - snprintf(buf, 32, "%3.6f%c", d, c); + } else if (format == 4) { + // d mm.mmm' (signed DMM format). + min = (deg - int(deg)) * 60.0; + if (min >= 59.9995) { + min -= 60.0; + deg += 1.0; + } + if (sign == 1) { + snprintf(buf, 32, "%d*%06.3f'", int(deg), fabs(min)); + } else { + snprintf(buf, 32, "-%d*%06.3f'", int(deg), fabs(min)); + } - } else if (format == 1) { - double min = (d - int(d)) * 60.0; + } else if (format == 5) { + // d mm'ss.s" (signed DMS format). + min = (deg - int(deg)) * 60.0; + sec = (min - int(min)) * 60.0; + if (sec >= 59.95) { + sec -= 60.0; + min += 1.0; + if (min >= 60.0) { + min -= 60.0; + deg += 1.0; + } + } + if (sign == 1) { + snprintf(buf, 32, "%d*%02d'%04.1f\"", int(deg), int(min), fabs(sec)); + } else { + snprintf(buf, 32, "-%d*%02d'%04.1f\"", int(deg), int(min), fabs(sec)); + } + + } else if (format == 6) { + // dd.dddddd X, ddd.dddddd X (zero padded DDD format). + if (c == 'N' || c == 'S') { + snprintf(buf, 32, "%09.6f%c", deg, c); + } else { + snprintf(buf, 32, "%010.6f%c", deg, c); + } + + } else if (format == 7) { + // dd mm.mmm' X, ddd mm.mmm' X (zero padded DMM format). + min = (deg - int(deg)) * 60.0; if (min >= 59.9995) { min -= 60.0; - d += 1.0; + deg += 1.0; + } + if (c == 'N' || c == 'S') { + snprintf(buf, 32, "%02d*%06.3f'%c", int(deg), fabs(min), c); + } else { + snprintf(buf, 32, "%03d*%06.3f'%c", int(deg), fabs(min), c); } - snprintf(buf, 32, "%d*%06.3f%c", int(d), fabs(min), c); - } else { - double min = (d - int(d)) * 60.0; - double sec = (min - int(min)) * 60.0; + } else if (format == 8) { + // dd mm'ss.s" X, dd mm'ss.s" X (zero padded DMS format). + min = (deg - int(deg)) * 60.0; + sec = (min - int(min)) * 60.0; if (sec >= 59.95) { sec -= 60.0; min += 1.0; if (min >= 60.0) { min -= 60.0; - d += 1.0; + deg += 1.0; } } - snprintf(buf, 32, "%d*%02d %04.1f%c", int(d), - int(min), fabs(sec), c); + if (c == 'N' || c == 'S') { + snprintf(buf, 32, "%02d*%02d'%04.1f\"%c", int(deg), int(min), fabs(sec), c); + } else { + snprintf(buf, 32, "%03d*%02d'%04.1f\"%c", int(deg), int(min), fabs(sec), c); + } + + } else if (format == 9) { + // dd* mm'.mmm X, ddd* mm'.mmm X (Trinity House Navigation standard). + min = (deg - int(deg)) * 60.0; + if (min >= 59.9995) { + min -= 60.0; + deg += 1.0; + } + if (c == 'N' || c == 'S') { + snprintf(buf, 32, "%02d* %02d'.%03d%c", int(deg), int(min), int(round((min-int(min))*1000)), c); + } else { + snprintf(buf, 32, "%03d* %02d'.%03d%c", int(deg), int(min), int(round((min-int(min))*1000)), c); + } + + } else { + // Empty the buffer for all invalid formats. + buf[0] = '\0'; } - buf[31] = '\0'; +} + +const char * +FGProperties::getLongitudeString () +{ + static char buf[32]; + double d = _longDeg->getDoubleValue(); + int format = _lonLatformat->getIntValue(); + + char c = d < 0.0 ? 'W' : 'E'; + formatLatLongString(d, format, buf, c); + return buf; +} + +const char * +FGProperties::getLatitudeString () +{ + static char buf[32]; + double d = _latDeg->getDoubleValue(); + int format = _lonLatformat->getIntValue(); + + char c = d < 0.0 ? 'S' : 'N'; + formatLatLongString(d, format, buf, c); return buf; } -- 2.39.5