Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 20 additions & 17 deletions src/main/java/mil/nga/gars/GARS.java
Original file line number Diff line number Diff line change
Expand Up @@ -315,31 +315,34 @@ public static GARS from(Point point) {

// Normalize the longitude if needed
GeometryUtils.normalizeWGS84(point);
double longitude = point.getLongitude();
if (longitude >= GARSConstants.MAX_LON) {
// 180 is the same meridian as -180, in band 001
longitude -= 360.0;
}

double lon = GARSUtils.getLongitudeDecimalBand(point.getLongitude());
double lat = GARSUtils.getLatitudeDecimalBandValue(point.getLatitude());
// Index of the 5 minute cell, counted from 180 W and 90 S. Multiply
// before adding the offset so that values on a cell boundary land in
// the cell they start (scaling the band fractions in steps let
// rounding put them in the cell below or to the left). The top row
// includes latitude 90.
int lonIndex = (int) Math.floor(longitude * 12.0) + 180 * 12;
int latIndex = (int) Math.floor(point.getLatitude() * 12.0) + 90 * 12;
lonIndex = Math.max(0, Math.min(lonIndex, 360 * 12 - 1));
latIndex = Math.max(0, Math.min(latIndex, 180 * 12 - 1));

int lonInt = (int) lon;
int latInt = (int) lat;
int lonInt = lonIndex / 6 + 1;
int latInt = latIndex / 6 + 1;

String latBand = GARSUtils.bandLetters(latInt);

double lonDecimal = lon - lonInt;
double latDecimal = lat - latInt;

double quadrantColumn = lonDecimal * 2.0;
double quadrantRow = latDecimal * 2.0;

int quadrantColumnInt = (int) quadrantColumn;
int quadrantRowInt = (int) quadrantRow;
int quadrantColumnInt = (lonIndex % 6) / 3;
int quadrantRowInt = (latIndex % 6) / 3;

int quadrant = GARSUtils.quadrant(quadrantColumnInt, quadrantRowInt);

lonDecimal = quadrantColumn - quadrantColumnInt;
latDecimal = quadrantRow - quadrantRowInt;

int keypadColumn = (int) (lonDecimal * 3.0);
int keypadRow = (int) (latDecimal * 3.0);
int keypadColumn = lonIndex % 3;
int keypadRow = latIndex % 3;

int keypad = GARSUtils.keypad(keypadColumn, keypadRow);

Expand Down
45 changes: 44 additions & 1 deletion src/test/java/mil/nga/gars/GARSTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,9 @@ public void testPointBounds() {

// Max latitude tests

String gars = "462RA49";
// Latitude 90 is in the top band, QZ (there is no band RA, and
// parse() rejects it)
String gars = "462QZ23";
String gars2 = "462QZ26";
double longitude = 50.920338;
double latitudeBelow = 89.9;
Expand Down Expand Up @@ -497,4 +499,45 @@ private void testCoordinate(Point point, String value)

}

/**
* Test points on the antimeridian, at the north pole, and on whole
* minute cell boundaries
*
* @throws ParseException
* upon failure to parse
*/
@Test
public void testCellBoundaries() throws ParseException {

// 180 is the same meridian as -180; latitude 90 is in the top row.
// These used to give 721HN37 and 361RA37, which parse() rejects.
assertEquals("001HN37", GARS.from(180, 0).coordinate());
assertEquals("361QZ11", GARS.from(0, 90).coordinate());
assertEquals("001QZ11", GARS.from(180, 90).coordinate());
assertEquals("720QZ23", GARS.from(179.9999999, 89.9999999).coordinate());
GARS.parse(GARS.from(180, 0).coordinate());
GARS.parse(GARS.from(0, 90).coordinate());

// A point on a 5 minute boundary is in the cell it starts
// (10 05' E 10 05' N used to give 381JJ38, the cell to the south)
assertEquals("381JJ35", GARS.from(10 + 5 / 60.0, 10 + 5 / 60.0).coordinate());
assertEquals("340GR23",
GARS.from(-(10 + 5 / 60.0), -(10 + 5 / 60.0)).coordinate());

for (int i = 0; i < 360 * 12; i += 7) {
for (int j = 0; j < 180 * 12; j += 5) {
int lonMinutes = i * 5 - 180 * 60;
int latMinutes = j * 5 - 90 * 60;
double lon = Math.signum(lonMinutes) * (Math.abs(lonMinutes) / 60
+ (Math.abs(lonMinutes) % 60) / 60.0);
double lat = Math.signum(latMinutes) * (Math.abs(latMinutes) / 60
+ (Math.abs(latMinutes) % 60) / 60.0);
Point southwest = GARS.from(lon, lat).toPoint();
assertEquals(lon, southwest.getLongitude(), 1e-9);
assertEquals(lat, southwest.getLatitude(), 1e-9);
}
}

}

}