Skip to content

Commit 25de5ce

Browse files
committed
Fix two problems:
a) Index out of bounds error due to typo in convertMGRSToUPS; clearly the index should have been 1 instead of 12. b) Conversions from geodetic to MGRS would fail for low southern latitudes (zone 0). Geotrans 3.7 has this problem fixed. The WorldWind conversion code was derived from NGA's Geotrans. Test case: Lat: -89.345400 deg, Lon: -48.930600 deg ==> MGRS: AZN 45208 47747
1 parent e9e5d04 commit 25de5ce

File tree

2 files changed

+186
-131
lines changed

2 files changed

+186
-131
lines changed

src/gov/nasa/worldwind/geom/coords/MGRSCoordConverter.java

Lines changed: 98 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class MGRSCoordConverter
3737
private static final int MGRS_ZONE_ERROR = 0x0100;
3838
private static final int MGRS_HEMISPHERE_ERROR = 0x0200;
3939
private static final int MGRS_LAT_WARNING = 0x0400;
40-
private static final int MGRS_NOZONE_WARNING = 0x0800;
40+
// private static final int MGRS_NOZONE_WARNING = 0x0800;
4141
private static final int MGRS_UTM_ERROR = 0x1000;
4242
private static final int MGRS_UPS_ERROR = 0x2000;
4343

@@ -62,7 +62,7 @@ class MGRSCoordConverter
6262
// Ellipsoid parameters, default to WGS 84
6363
private double MGRS_a = 6378137.0; // Semi-major axis of ellipsoid in meters
6464
private double MGRS_f = 1 / 298.257223563; // Flattening of ellipsoid
65-
private double MGRS_recpf = 298.257223563;
65+
// private double MGRS_recpf = 298.257223563;
6666
private String MGRS_Ellipsoid_Code = "WE";
6767

6868
private Globe globe;
@@ -255,9 +255,11 @@ public long convertMGRSToGeodetic(String MGRSString)
255255
{
256256
latitude = 0;
257257
longitude = 0;
258-
long error_code = checkZone(MGRSString);
259-
if (error_code == MGRS_NO_ERROR)
260-
{
258+
MGRSComponents mgrs = breakMGRSString(MGRSString);
259+
if (mgrs == null) return last_error;
260+
261+
long error_code = MGRS_NO_ERROR;
262+
if (mgrs.zone != 0) {
261263
UTMCoord UTM = convertMGRSToUTM(MGRSString);
262264
if (UTM != null)
263265
{
@@ -267,9 +269,8 @@ public long convertMGRSToGeodetic(String MGRSString)
267269
else
268270
error_code = MGRS_UTM_ERROR;
269271
}
270-
else if (error_code == MGRS_NOZONE_WARNING)
272+
else
271273
{
272-
// TODO: polar conversion
273274
UPSCoord UPS = convertMGRSToUPS(MGRSString);
274275
if (UPS != null)
275276
{
@@ -314,17 +315,15 @@ private MGRSComponents breakMGRSString(String MGRSString)
314315
long northing = 0;
315316
int precision = 0;
316317

317-
while (i < MGRSString.length() && MGRSString.charAt(i) == ' ')
318-
{
319-
i++; /* skip any leading blanks */
320-
}
318+
MGRSString = MGRSString.toUpperCase().replaceAll("\\s", "");
321319
j = i;
322320
while (i < MGRSString.length() && Character.isDigit(MGRSString.charAt(i)))
323321
{
324322
i++;
325323
}
326324
num_digits = i - j;
327325
if (num_digits <= 2)
326+
{
328327
if (num_digits > 0)
329328
{
330329
/* get zone */
@@ -333,7 +332,11 @@ private MGRSComponents breakMGRSString(String MGRSString)
333332
error_code |= MGRS_STRING_ERROR;
334333
}
335334
else
336-
error_code |= MGRS_STRING_ERROR;
335+
{
336+
zone = 0;
337+
}
338+
}
339+
337340
j = i;
338341

339342
while (i < MGRSString.length() && Character.isLetter(MGRSString.charAt(i)))
@@ -394,40 +397,6 @@ private MGRSComponents breakMGRSString(String MGRSString)
394397
return null;
395398
}
396399

397-
/**
398-
* The function Check_Zone receives an MGRS coordinate string. If a zone is given, MGRS_NO_ERROR is returned.
399-
* Otherwise, MGRS_NOZONE_WARNING. is returned.
400-
*
401-
* @param MGRSString the MGRS coordinate string.
402-
*
403-
* @return the error code.
404-
*/
405-
private long checkZone(String MGRSString)
406-
{
407-
int i = 0;
408-
int j = 0;
409-
int num_digits = 0;
410-
long error_code = MGRS_NO_ERROR;
411-
412-
/* skip any leading blanks */
413-
while (i < MGRSString.length() && MGRSString.charAt(i) == ' ')
414-
{
415-
i++;
416-
}
417-
j = i;
418-
while (i < MGRSString.length() && Character.isDigit(MGRSString.charAt(i)))
419-
{
420-
i++;
421-
}
422-
num_digits = i - j;
423-
if (num_digits > 2)
424-
error_code |= MGRS_STRING_ERROR;
425-
else if (num_digits <= 0)
426-
error_code |= MGRS_NOZONE_WARNING;
427-
428-
return error_code;
429-
}
430-
431400
/**
432401
* The function Get_Latitude_Band_Min_Northing receives a latitude band letter and uses the Latitude_Band_Table to
433402
* determine the minimum northing for that latitude band letter. Updates min_northing.
@@ -503,13 +472,9 @@ else if ((letter >= LETTER_P) && (letter <= LETTER_X))
503472
*/
504473
private UTMCoord convertMGRSToUTM(String MGRSString)
505474
{
506-
double scaled_min_northing;
507475
double grid_easting; /* Easting for 100,000 meter grid square */
508476
double grid_northing; /* Northing for 100,000 meter grid square */
509-
double temp_grid_northing = 0.0;
510-
double fabs_grid_northing = 0.0;
511477
double latitude = 0.0;
512-
double longitude = 0.0;
513478
double divisor = 1.0;
514479
long error_code = MGRS_NO_ERROR;
515480

@@ -546,8 +511,8 @@ private UTMCoord convertMGRSToUTM(String MGRSString)
546511
if (error_code == MGRS_NO_ERROR)
547512
{
548513
grid_northing =
549-
(double) (MGRS.squareLetter2) * ONEHT; // smithjl commented out + false_northing;
550-
grid_easting = (double) ((MGRS.squareLetter1) - ltr2_low_value + 1) * ONEHT;
514+
(MGRS.squareLetter2) * ONEHT; // smithjl commented out + false_northing;
515+
grid_easting = ((MGRS.squareLetter1) - ltr2_low_value + 1) * ONEHT;
551516
if ((ltr2_low_value == LETTER_J) && (MGRS.squareLetter1 > LETTER_O))
552517
grid_easting = grid_easting - ONEHT;
553518

@@ -622,10 +587,6 @@ private UTMCoord convertMGRSToUTM(String MGRSString)
622587
*/
623588
public long convertGeodeticToMGRS(double latitude, double longitude, int precision)
624589
{
625-
String Hemisphere = AVKey.NORTH;
626-
double Easting = 0.0;
627-
double Northing = 0.0;
628-
629590
MGRSString = "";
630591

631592
long error_code = MGRS_NO_ERROR;
@@ -736,8 +697,8 @@ private long convertUPSToMGRS(String Hemisphere, Double Easting, Double Northing
736697
// false_easting = UPS_Constant_Table.get(index).false_easting;
737698
// false_northing = UPS_Constant_Table.get(index).false_northing;
738699
ltr2_low_value = (int) upsConstants[index][1];
739-
false_easting = (double) upsConstants[index][4];
740-
false_northing = (double) upsConstants[index][5];
700+
false_easting = upsConstants[index][4];
701+
false_northing = upsConstants[index][5];
741702
}
742703
else // AVKey.SOUTH.equals(Hemisphere)
743704
{
@@ -750,8 +711,8 @@ private long convertUPSToMGRS(String Hemisphere, Double Easting, Double Northing
750711
// false_easting = UPS_Constant_Table.get((int) letters[0]).false_easting;
751712
// false_northing = UPS_Constant_Table.get((int) letters[0]).false_northing;
752713
ltr2_low_value = (int) upsConstants[(int) letters[0]][1];
753-
false_easting = (double) upsConstants[(int) letters[0]][4];
754-
false_northing = (double) upsConstants[(int) letters[0]][5];
714+
false_easting = upsConstants[(int) letters[0]][4];
715+
false_northing = upsConstants[(int) letters[0]][5];
755716
}
756717

757718
grid_northing = Northing;
@@ -766,7 +727,7 @@ private long convertUPSToMGRS(String Hemisphere, Double Easting, Double Northing
766727

767728
grid_easting = Easting;
768729
grid_easting = grid_easting - false_easting;
769-
letters[1] = (int) ltr2_low_value + ((int) (grid_easting / ONEHT));
730+
letters[1] = ltr2_low_value + ((int) (grid_easting / ONEHT));
770731

771732
if (Easting < TWOMIL)
772733
{
@@ -861,7 +822,7 @@ private long convertUTMToMGRS(long Zone, double Latitude, double Easting, double
861822
* The function Get_Grid_Values sets the letter range used for the 2nd letter in the MGRS coordinate string, based
862823
* on the set number of the utm zone. It also sets the false northing using a value of A for the second letter of
863824
* the grid square, based on the grid pattern and set number of the utm zone.
864-
* <p>
825+
* <p></p>
865826
* Key values that are set in this function include: ltr2_low_value, ltr2_high_value, and false_northing.
866827
*
867828
* @param zone Zone number
@@ -884,18 +845,18 @@ private void getGridValues(long zone)
884845

885846
if ((set_number == 1) || (set_number == 4))
886847
{
887-
ltr2_low_value = (long) LETTER_A;
888-
ltr2_high_value = (long) LETTER_H;
848+
ltr2_low_value = LETTER_A;
849+
ltr2_high_value = LETTER_H;
889850
}
890851
else if ((set_number == 2) || (set_number == 5))
891852
{
892-
ltr2_low_value = (long) LETTER_J;
893-
ltr2_high_value = (long) LETTER_R;
853+
ltr2_low_value = LETTER_J;
854+
ltr2_high_value = LETTER_R;
894855
}
895856
else if ((set_number == 3) || (set_number == 6))
896857
{
897-
ltr2_low_value = (long) LETTER_S;
898-
ltr2_high_value = (long) LETTER_Z;
858+
ltr2_low_value = LETTER_S;
859+
ltr2_high_value = LETTER_Z;
899860
}
900861

901862
/* False northing at A for second letter of grid square */
@@ -930,7 +891,7 @@ private long getLatitudeLetter(double latitude)
930891
double lat_deg = latitude * RAD_TO_DEG;
931892

932893
if (lat_deg >= 72 && lat_deg < 84.5)
933-
lastLetter = (long) LETTER_X;
894+
lastLetter = LETTER_X;
934895
else if (lat_deg > -80.5 && lat_deg < 72)
935896
{
936897
temp = ((latitude + (80.0 * DEG_TO_RAD)) / (8.0 * DEG_TO_RAD)) + 1.0e-12;
@@ -961,7 +922,7 @@ private double roundMGRS(double value)
961922
ival = (long) (ivalue);
962923
if ((fraction > 0.5) || ((fraction == 0.5) && (ival % 2 == 1)))
963924
ival++;
964-
return (double) ival;
925+
return ival;
965926
}
966927

967928
/**
@@ -1077,84 +1038,90 @@ private UPSCoord convertMGRSToUPS(String MGRS)
10771038

10781039
MGRSComponents mgrs = breakMGRSString(MGRS);
10791040
if (mgrs == null)
1041+
{
10801042
error_code = this.last_error;
1081-
1082-
if (mgrs != null && mgrs.zone > 0)
1083-
error_code |= MGRS_STRING_ERROR;
1084-
1085-
if (error_code == MGRS_NO_ERROR)
1043+
}
1044+
else
10861045
{
1087-
easting = mgrs.easting;
1088-
northing = mgrs.northing;
1089-
1090-
if (mgrs.latitudeBand >= LETTER_Y)
1091-
{
1092-
hemisphere = AVKey.NORTH;
1093-
1094-
index = mgrs.latitudeBand - 22;
1095-
ltr2_low_value = upsConstants[index][1]; //.ltr2_low_value;
1096-
ltr2_high_value = upsConstants[index][2]; //.ltr2_high_value;
1097-
ltr3_high_value = upsConstants[index][3]; //.ltr3_high_value;
1098-
false_easting = upsConstants[index][4]; //.false_easting;
1099-
false_northing = upsConstants[index][5]; //.false_northing;
1100-
}
1101-
else
1046+
if (mgrs.zone > 0)
11021047
{
1103-
hemisphere = AVKey.SOUTH;
1104-
1105-
ltr2_low_value = upsConstants[mgrs.latitudeBand][12]; //.ltr2_low_value;
1106-
ltr2_high_value = upsConstants[mgrs.latitudeBand][2]; //.ltr2_high_value;
1107-
ltr3_high_value = upsConstants[mgrs.latitudeBand][3]; //.ltr3_high_value;
1108-
false_easting = upsConstants[mgrs.latitudeBand][4]; //.false_easting;
1109-
false_northing = upsConstants[mgrs.latitudeBand][5]; //.false_northing;
1048+
error_code |= MGRS_STRING_ERROR;
11101049
}
11111050

1112-
// Check that the second letter of the MGRS string is within
1113-
// the range of valid second letter values
1114-
// Also check that the third letter is valid
1115-
if ((mgrs.squareLetter1 < ltr2_low_value) || (mgrs.squareLetter1 > ltr2_high_value) ||
1116-
((mgrs.squareLetter1 == LETTER_D) || (mgrs.squareLetter1 == LETTER_E) ||
1117-
(mgrs.squareLetter1 == LETTER_M) || (mgrs.squareLetter1 == LETTER_N) ||
1118-
(mgrs.squareLetter1 == LETTER_V) || (mgrs.squareLetter1 == LETTER_W)) ||
1119-
(mgrs.squareLetter2 > ltr3_high_value))
1120-
error_code = MGRS_STRING_ERROR;
1121-
11221051
if (error_code == MGRS_NO_ERROR)
11231052
{
1124-
grid_northing = (double) mgrs.squareLetter2 * ONEHT + false_northing;
1125-
if (mgrs.squareLetter2 > LETTER_I)
1126-
grid_northing = grid_northing - ONEHT;
1053+
easting = mgrs.easting;
1054+
northing = mgrs.northing;
11271055

1128-
if (mgrs.squareLetter2 > LETTER_O)
1129-
grid_northing = grid_northing - ONEHT;
1130-
1131-
grid_easting = (double) ((mgrs.squareLetter1) - ltr2_low_value) * ONEHT + false_easting;
1132-
if (ltr2_low_value != LETTER_A)
1056+
if (mgrs.latitudeBand >= LETTER_Y)
11331057
{
1134-
if (mgrs.squareLetter1 > LETTER_L)
1135-
grid_easting = grid_easting - 300000.0;
1136-
1137-
if (mgrs.squareLetter1 > LETTER_U)
1138-
grid_easting = grid_easting - 200000.0;
1058+
hemisphere = AVKey.NORTH;
1059+
1060+
index = mgrs.latitudeBand - 22;
1061+
ltr2_low_value = upsConstants[index][1]; //.ltr2_low_value;
1062+
ltr2_high_value = upsConstants[index][2]; //.ltr2_high_value;
1063+
ltr3_high_value = upsConstants[index][3]; //.ltr3_high_value;
1064+
false_easting = upsConstants[index][4]; //.false_easting;
1065+
false_northing = upsConstants[index][5]; //.false_northing;
11391066
}
11401067
else
11411068
{
1142-
if (mgrs.squareLetter1 > LETTER_C)
1143-
grid_easting = grid_easting - 200000.0;
1144-
1145-
if (mgrs.squareLetter1 > LETTER_I)
1146-
grid_easting = grid_easting - ONEHT;
1069+
hemisphere = AVKey.SOUTH;
11471070

1148-
if (mgrs.squareLetter1 > LETTER_L)
1149-
grid_easting = grid_easting - 300000.0;
1071+
ltr2_low_value = upsConstants[mgrs.latitudeBand][1]; //.ltr2_low_value;
1072+
ltr2_high_value = upsConstants[mgrs.latitudeBand][2]; //.ltr2_high_value;
1073+
ltr3_high_value = upsConstants[mgrs.latitudeBand][3]; //.ltr3_high_value;
1074+
false_easting = upsConstants[mgrs.latitudeBand][4]; //.false_easting;
1075+
false_northing = upsConstants[mgrs.latitudeBand][5]; //.false_northing;
11501076
}
11511077

1152-
easting = grid_easting + easting;
1153-
northing = grid_northing + northing;
1154-
return UPSCoord.fromUPS(hemisphere, easting, northing, globe);
1078+
// Check that the second letter of the MGRS string is within
1079+
// the range of valid second letter values
1080+
// Also check that the third letter is valid
1081+
if ((mgrs.squareLetter1 < ltr2_low_value) || (mgrs.squareLetter1 > ltr2_high_value) ||
1082+
((mgrs.squareLetter1 == LETTER_D) || (mgrs.squareLetter1 == LETTER_E) ||
1083+
(mgrs.squareLetter1 == LETTER_M) || (mgrs.squareLetter1 == LETTER_N) ||
1084+
(mgrs.squareLetter1 == LETTER_V) || (mgrs.squareLetter1 == LETTER_W)) ||
1085+
(mgrs.squareLetter2 > ltr3_high_value))
1086+
error_code = MGRS_STRING_ERROR;
1087+
1088+
if (error_code == MGRS_NO_ERROR)
1089+
{
1090+
grid_northing = mgrs.squareLetter2 * ONEHT + false_northing;
1091+
if (mgrs.squareLetter2 > LETTER_I)
1092+
grid_northing = grid_northing - ONEHT;
1093+
1094+
if (mgrs.squareLetter2 > LETTER_O)
1095+
grid_northing = grid_northing - ONEHT;
1096+
1097+
grid_easting = ((mgrs.squareLetter1) - ltr2_low_value) * ONEHT + false_easting;
1098+
if (ltr2_low_value != LETTER_A)
1099+
{
1100+
if (mgrs.squareLetter1 > LETTER_L)
1101+
grid_easting = grid_easting - 300000.0;
1102+
1103+
if (mgrs.squareLetter1 > LETTER_U)
1104+
grid_easting = grid_easting - 200000.0;
1105+
}
1106+
else
1107+
{
1108+
if (mgrs.squareLetter1 > LETTER_C)
1109+
grid_easting = grid_easting - 200000.0;
1110+
1111+
if (mgrs.squareLetter1 > LETTER_I)
1112+
grid_easting = grid_easting - ONEHT;
1113+
1114+
if (mgrs.squareLetter1 > LETTER_L)
1115+
grid_easting = grid_easting - 300000.0;
1116+
}
1117+
1118+
easting = grid_easting + easting;
1119+
northing = grid_northing + northing;
1120+
return UPSCoord.fromUPS(hemisphere, easting, northing, globe);
1121+
}
11551122
}
11561123
}
11571124

11581125
return null;
11591126
}
1160-
}
1127+
}

0 commit comments

Comments
 (0)