From 8b8f829fc3d4e6b8ea0bc0bdce2e79223783678a Mon Sep 17 00:00:00 2001 From: Glenn Burkhardt Date: Thu, 8 Aug 2019 00:00:21 +0200 Subject: [PATCH] MGRS conversion fixes. Fix index out of bounds error due to a typo in convertMGRSToUPS; Fix handling of extreme southern latitude (zone 0) conversions following Geotrans 3.7 for guidance: should give Lat: -89.345400 deg, Lon: -48.930600 deg ==> MGRS: AZN 45208 47747 --- .../geom/coords/MGRSCoordConverter.java | 201 ++++++++---------- 1 file changed, 84 insertions(+), 117 deletions(-) diff --git a/src/gov/nasa/worldwind/geom/coords/MGRSCoordConverter.java b/src/gov/nasa/worldwind/geom/coords/MGRSCoordConverter.java index 4762603fa8..23bbd6f090 100644 --- a/src/gov/nasa/worldwind/geom/coords/MGRSCoordConverter.java +++ b/src/gov/nasa/worldwind/geom/coords/MGRSCoordConverter.java @@ -37,7 +37,7 @@ class MGRSCoordConverter private static final int MGRS_ZONE_ERROR = 0x0100; private static final int MGRS_HEMISPHERE_ERROR = 0x0200; private static final int MGRS_LAT_WARNING = 0x0400; - private static final int MGRS_NOZONE_WARNING = 0x0800; + // private static final int MGRS_NOZONE_WARNING = 0x0800; private static final int MGRS_UTM_ERROR = 0x1000; private static final int MGRS_UPS_ERROR = 0x2000; @@ -62,7 +62,7 @@ class MGRSCoordConverter // Ellipsoid parameters, default to WGS 84 private double MGRS_a = 6378137.0; // Semi-major axis of ellipsoid in meters private double MGRS_f = 1 / 298.257223563; // Flattening of ellipsoid - private double MGRS_recpf = 298.257223563; + // private double MGRS_recpf = 298.257223563; private String MGRS_Ellipsoid_Code = "WE"; private Globe globe; @@ -255,9 +255,11 @@ public long convertMGRSToGeodetic(String MGRSString) { latitude = 0; longitude = 0; - long error_code = checkZone(MGRSString); - if (error_code == MGRS_NO_ERROR) - { + MGRSComponents mgrs = breakMGRSString(MGRSString); + if (mgrs == null) return last_error; + + long error_code = MGRS_NO_ERROR; + if (mgrs.zone != 0) { UTMCoord UTM = convertMGRSToUTM(MGRSString); if (UTM != null) { @@ -267,9 +269,8 @@ public long convertMGRSToGeodetic(String MGRSString) else error_code = MGRS_UTM_ERROR; } - else if (error_code == MGRS_NOZONE_WARNING) + else { - // TODO: polar conversion UPSCoord UPS = convertMGRSToUPS(MGRSString); if (UPS != null) { @@ -314,17 +315,15 @@ private MGRSComponents breakMGRSString(String MGRSString) long northing = 0; int precision = 0; - while (i < MGRSString.length() && MGRSString.charAt(i) == ' ') - { - i++; /* skip any leading blanks */ - } + MGRSString = MGRSString.toUpperCase().replaceAll("\\s", ""); j = i; - while (i < MGRSString.length() && Character.isDigit(MGRSString.charAt(i))) + while (i < MGRSString.length() && Character.isDigit(' ')) { i++; } num_digits = i - j; if (num_digits <= 2) + { if (num_digits > 0) { /* get zone */ @@ -333,7 +332,11 @@ private MGRSComponents breakMGRSString(String MGRSString) error_code |= MGRS_STRING_ERROR; } else - error_code |= MGRS_STRING_ERROR; + { + zone = 0; + } + } + j = i; while (i < MGRSString.length() && Character.isLetter(MGRSString.charAt(i))) @@ -394,40 +397,6 @@ private MGRSComponents breakMGRSString(String MGRSString) return null; } - /** - * The function Check_Zone receives an MGRS coordinate string. If a zone is given, MGRS_NO_ERROR is returned. - * Otherwise, MGRS_NOZONE_WARNING. is returned. - * - * @param MGRSString the MGRS coordinate string. - * - * @return the error code. - */ - private long checkZone(String MGRSString) - { - int i = 0; - int j = 0; - int num_digits = 0; - long error_code = MGRS_NO_ERROR; - - /* skip any leading blanks */ - while (i < MGRSString.length() && MGRSString.charAt(i) == ' ') - { - i++; - } - j = i; - while (i < MGRSString.length() && Character.isDigit(MGRSString.charAt(i))) - { - i++; - } - num_digits = i - j; - if (num_digits > 2) - error_code |= MGRS_STRING_ERROR; - else if (num_digits <= 0) - error_code |= MGRS_NOZONE_WARNING; - - return error_code; - } - /** * The function Get_Latitude_Band_Min_Northing receives a latitude band letter and uses the Latitude_Band_Table to * determine the minimum northing for that latitude band letter. Updates min_northing. @@ -503,13 +472,9 @@ else if ((letter >= LETTER_P) && (letter <= LETTER_X)) */ private UTMCoord convertMGRSToUTM(String MGRSString) { - double scaled_min_northing; double grid_easting; /* Easting for 100,000 meter grid square */ double grid_northing; /* Northing for 100,000 meter grid square */ - double temp_grid_northing = 0.0; - double fabs_grid_northing = 0.0; double latitude = 0.0; - double longitude = 0.0; double divisor = 1.0; long error_code = MGRS_NO_ERROR; @@ -622,10 +587,6 @@ private UTMCoord convertMGRSToUTM(String MGRSString) */ public long convertGeodeticToMGRS(double latitude, double longitude, int precision) { - String Hemisphere = AVKey.NORTH; - double Easting = 0.0; - double Northing = 0.0; - MGRSString = ""; long error_code = MGRS_NO_ERROR; @@ -861,7 +822,7 @@ private long convertUTMToMGRS(long Zone, double Latitude, double Easting, double * The function Get_Grid_Values sets the letter range used for the 2nd letter in the MGRS coordinate string, based * on the set number of the utm zone. It also sets the false northing using a value of A for the second letter of * the grid square, based on the grid pattern and set number of the utm zone. - *

+ *

* Key values that are set in this function include: ltr2_low_value, ltr2_high_value, and false_northing. * * @param zone Zone number @@ -1077,84 +1038,90 @@ private UPSCoord convertMGRSToUPS(String MGRS) MGRSComponents mgrs = breakMGRSString(MGRS); if (mgrs == null) + { error_code = this.last_error; - - if (mgrs != null && mgrs.zone > 0) - error_code |= MGRS_STRING_ERROR; - - if (error_code == MGRS_NO_ERROR) + } + else { - easting = mgrs.easting; - northing = mgrs.northing; - - if (mgrs.latitudeBand >= LETTER_Y) - { - hemisphere = AVKey.NORTH; - - index = mgrs.latitudeBand - 22; - ltr2_low_value = upsConstants[index][1]; //.ltr2_low_value; - ltr2_high_value = upsConstants[index][2]; //.ltr2_high_value; - ltr3_high_value = upsConstants[index][3]; //.ltr3_high_value; - false_easting = upsConstants[index][4]; //.false_easting; - false_northing = upsConstants[index][5]; //.false_northing; - } - else + if (mgrs.zone > 0) { - hemisphere = AVKey.SOUTH; - - ltr2_low_value = upsConstants[mgrs.latitudeBand][12]; //.ltr2_low_value; - ltr2_high_value = upsConstants[mgrs.latitudeBand][2]; //.ltr2_high_value; - ltr3_high_value = upsConstants[mgrs.latitudeBand][3]; //.ltr3_high_value; - false_easting = upsConstants[mgrs.latitudeBand][4]; //.false_easting; - false_northing = upsConstants[mgrs.latitudeBand][5]; //.false_northing; + error_code |= MGRS_STRING_ERROR; } - // Check that the second letter of the MGRS string is within - // the range of valid second letter values - // Also check that the third letter is valid - if ((mgrs.squareLetter1 < ltr2_low_value) || (mgrs.squareLetter1 > ltr2_high_value) || - ((mgrs.squareLetter1 == LETTER_D) || (mgrs.squareLetter1 == LETTER_E) || - (mgrs.squareLetter1 == LETTER_M) || (mgrs.squareLetter1 == LETTER_N) || - (mgrs.squareLetter1 == LETTER_V) || (mgrs.squareLetter1 == LETTER_W)) || - (mgrs.squareLetter2 > ltr3_high_value)) - error_code = MGRS_STRING_ERROR; - if (error_code == MGRS_NO_ERROR) { - grid_northing = (double) mgrs.squareLetter2 * ONEHT + false_northing; - if (mgrs.squareLetter2 > LETTER_I) - grid_northing = grid_northing - ONEHT; + easting = mgrs.easting; + northing = mgrs.northing; - if (mgrs.squareLetter2 > LETTER_O) - grid_northing = grid_northing - ONEHT; - - grid_easting = (double) ((mgrs.squareLetter1) - ltr2_low_value) * ONEHT + false_easting; - if (ltr2_low_value != LETTER_A) + if (mgrs.latitudeBand >= LETTER_Y) { - if (mgrs.squareLetter1 > LETTER_L) - grid_easting = grid_easting - 300000.0; - - if (mgrs.squareLetter1 > LETTER_U) - grid_easting = grid_easting - 200000.0; + hemisphere = AVKey.NORTH; + + index = mgrs.latitudeBand - 22; + ltr2_low_value = upsConstants[index][1]; //.ltr2_low_value; + ltr2_high_value = upsConstants[index][2]; //.ltr2_high_value; + ltr3_high_value = upsConstants[index][3]; //.ltr3_high_value; + false_easting = upsConstants[index][4]; //.false_easting; + false_northing = upsConstants[index][5]; //.false_northing; } else { - if (mgrs.squareLetter1 > LETTER_C) - grid_easting = grid_easting - 200000.0; - - if (mgrs.squareLetter1 > LETTER_I) - grid_easting = grid_easting - ONEHT; + hemisphere = AVKey.SOUTH; - if (mgrs.squareLetter1 > LETTER_L) - grid_easting = grid_easting - 300000.0; + ltr2_low_value = upsConstants[mgrs.latitudeBand][1]; //.ltr2_low_value; + ltr2_high_value = upsConstants[mgrs.latitudeBand][2]; //.ltr2_high_value; + ltr3_high_value = upsConstants[mgrs.latitudeBand][3]; //.ltr3_high_value; + false_easting = upsConstants[mgrs.latitudeBand][4]; //.false_easting; + false_northing = upsConstants[mgrs.latitudeBand][5]; //.false_northing; } - easting = grid_easting + easting; - northing = grid_northing + northing; - return UPSCoord.fromUPS(hemisphere, easting, northing, globe); + // Check that the second letter of the MGRS string is within + // the range of valid second letter values + // Also check that the third letter is valid + if ((mgrs.squareLetter1 < ltr2_low_value) || (mgrs.squareLetter1 > ltr2_high_value) || + ((mgrs.squareLetter1 == LETTER_D) || (mgrs.squareLetter1 == LETTER_E) || + (mgrs.squareLetter1 == LETTER_M) || (mgrs.squareLetter1 == LETTER_N) || + (mgrs.squareLetter1 == LETTER_V) || (mgrs.squareLetter1 == LETTER_W)) || + (mgrs.squareLetter2 > ltr3_high_value)) + error_code = MGRS_STRING_ERROR; + + if (error_code == MGRS_NO_ERROR) + { + grid_northing = (double) mgrs.squareLetter2 * ONEHT + false_northing; + if (mgrs.squareLetter2 > LETTER_I) + grid_northing = grid_northing - ONEHT; + + if (mgrs.squareLetter2 > LETTER_O) + grid_northing = grid_northing - ONEHT; + + grid_easting = (double) ((mgrs.squareLetter1) - ltr2_low_value) * ONEHT + false_easting; + if (ltr2_low_value != LETTER_A) + { + if (mgrs.squareLetter1 > LETTER_L) + grid_easting = grid_easting - 300000.0; + + if (mgrs.squareLetter1 > LETTER_U) + grid_easting = grid_easting - 200000.0; + } + else + { + if (mgrs.squareLetter1 > LETTER_C) + grid_easting = grid_easting - 200000.0; + + if (mgrs.squareLetter1 > LETTER_I) + grid_easting = grid_easting - ONEHT; + + if (mgrs.squareLetter1 > LETTER_L) + grid_easting = grid_easting - 300000.0; + } + + easting = grid_easting + easting; + northing = grid_northing + northing; + return UPSCoord.fromUPS(hemisphere, easting, northing, globe); + } } } return null; } -} +} \ No newline at end of file