Fix GeoPos losing the sign of coordinates between 0 and -1 (#3283)

GeoPos stored a coordinate's sign only in its degrees NumberField, which
is an int32_t and therefore has no negative zero. Any coordinate whose
integer degrees part is 0 but which is negative (i.e. strictly between
0.0 and -1.0) could not be represented at all:

  - set_lat()/set_lon() passed the raw float to the degrees field, so
    -0.2933 truncated to 0 and the sign was gone before it reached the
    widget.
  - lat()/lon() then decided the sign with `field_lon_degrees.value() < 0`,
    which is false for 0, so the value came back positive.

The reporter's airport is at longitude -0.2933, which was impossible to
enter in the ADSB Tx app.

Give each coordinate an explicit hemisphere field (N/S and E/W) and make
the degrees field an unsigned magnitude:

  - The hemisphere OptionsField is the single source of the sign, so
    "negative with zero degrees" is now representable.
  - set_lat()/set_lon() derive the hemisphere from the sign of the input
    and feed the fields the magnitude.
  - lat()/lon() read the hemisphere instead of inferring the sign from
    the degrees value.
  - The minutes on_wrap handlers no longer need to flip the carry
    direction based on the degrees sign, since degrees is now a
    magnitude; the carry is the same in both hemispheres.
  - The degrees fields no longer loop, so carrying below 0 clamps at 0
    instead of wrapping round to 90/180.

The hemisphere indicator occupies the column that the 4-wide signed
degrees field used for its minus sign, so the row layout, the degree
symbol and the decimal readout all stay where they were.

Fixes #3234
This commit is contained in:
MsfPablo
2026-08-08 21:18:18 +02:00
committed by GitHub
parent 367eaf54c0
commit 9067e007b6
2 changed files with 51 additions and 26 deletions
+23 -8
View File
@@ -239,12 +239,21 @@ class GeoPos : public View {
{25 * 8, UI_POS_Y(0), 5 * 8, 16},
""};
NumberField field_lat_degrees{
// Sign is held by the hemisphere field, not by the degrees field: an
// int32_t degrees field has no negative zero, so a coordinate in
// (-1, 0) could not otherwise be represented (see issue #3234).
OptionsField field_lat_hemisphere{
{5 * 8, 1 * 16},
4,
{-90, 90},
1,
' '};
{{"N", 0},
{"S", 1}}};
NumberField field_lat_degrees{
{6 * 8, 1 * 16},
3,
{0, 90},
1,
' ',
false};
NumberField field_lat_minutes{
{10 * 8, 1 * 16},
2,
@@ -263,12 +272,18 @@ class GeoPos : public View {
{17 * 8, 1 * 16, 13 * 8, 1 * 16},
""};
NumberField field_lon_degrees{
OptionsField field_lon_hemisphere{
{5 * 8, 2 * 16},
4,
{-180, 180},
1,
' '};
{{"E", 0},
{"W", 1}}};
NumberField field_lon_degrees{
{6 * 8, 2 * 16},
3,
{0, 180},
1,
' ',
false};
NumberField field_lon_minutes{
{10 * 8, 2 * 16},
2,