Skip to content

Commit

Permalink
Merge branch '213-geometry-to-geohash' of github.com:DD2480-Group-3/g…
Browse files Browse the repository at this point in the history
…eometry-api-java into 54-coveringGeohash
  • Loading branch information
LinusWallin committed Mar 4, 2024
2 parents 263f8e2 + dcdb58d commit 2aa650f
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 80 deletions.
88 changes: 50 additions & 38 deletions src/main/java/com/esri/core/geometry/Geohash.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,74 +91,87 @@ public static String toGeohash(Point2D pt, int characterLength) {
"CharacterLength cannot be less than 1"
);
}
if (characterLength > 6) {
throw new InvalidParameterException("Max characterLength of 6");
}
int precision = characterLength * 5;
double lat = pt.y;
double lon = pt.x;

String latBitStr = Geohash.convertToBinary(
long latBit = Geohash.convertToBinary(
lat,
new double[] { -90, 90 },
precision
);

String lonBitStr = Geohash.convertToBinary(
long lonBit = Geohash.convertToBinary(
lon,
new double[] { -180, 180 },
precision
);

StringBuilder interwovenBin = new StringBuilder();
for (int i = 0; i < latBitStr.length(); i++) {
interwovenBin.append(lonBitStr.charAt(i));
interwovenBin.append(latBitStr.charAt(i));
long interwovenBin = 1;
for (int i = precision - 1; i >= 0; i--) {
long currLon = (lonBit >>> i) & 1;
long currLat = (latBit >>> i) & 1;
interwovenBin <<= 1;
interwovenBin |= currLon;
interwovenBin <<= 1;
interwovenBin |= currLat;
}

return Geohash
.binaryToBase32(interwovenBin.toString())
.binaryToBase32(interwovenBin, precision * 2)
.substring(0, characterLength);
}

/**
* Computes the base32 value of the binary string given
* @param binStr Binary string with "0" || "1" that is to be converted to a base32 string
* @param binStr (long) Binary string with "0" || "1" that is to be converted to a base32 string
* @param len (int) number of significant bits
* @return base32 string of the binStr in chunks of 5 binary digits
*/

public static String binaryToBase32(String binStr) {
private static String binaryToBase32(long binStr, int len) {
StringBuilder base32Str = new StringBuilder();
for (int i = 0; i < binStr.length(); i += 5) {
String chunk = binStr.substring(i, i + 5);
int decVal = Integer.valueOf(chunk, 2);
base32Str.append(base32.charAt(decVal));
// for (int i = 0; i < binStr.length(); i += 5) {
// String chunk = binStr.substring(i, i + 5);
// int decVal = Integer.valueOf(chunk, 2);
// base32Str.append(base32.charAt(decVal));
// }

for (int i = len - 5; i >= 0; i -= 5) {
// Extract a group of 5 bits
int group = (int) (binStr >>> i) & 0x1F;

// Use the extracted group as an index to fetch the corresponding base32 character
base32Str.append(base32.charAt(group));
}

return base32Str.toString();
}

/**
* Converts the value given to a binary string with the given precision and range
* @param value The value to be converted to a binString
* @param r The range at which the value is to be compared with
* @param precision The Precision (number of bits) that the binary string needs
* @return A binary string representation of the value with the given range and precision
* @param value (double) The value to be converted to a binString
* @param r (double[]) The range at which the value is to be compared with
* @param precision (int) The Precision (number of bits) that the binary string needs
* @return (String) A binary string representation of the value with the given range and precision
*/

public static String convertToBinary(
double value,
double[] r,
int precision
) {
StringBuilder binString = new StringBuilder();
private static long convertToBinary(double value, double[] r, int precision) {
int binVal = 1;
for (int i = 0; i < precision; i++) {
double mid = (r[0] + r[1]) / 2;
if (value >= mid) {
binString.append("1");
binVal = binVal << 1;
binVal = binVal | 1;
r[0] = mid;
} else {
binString.append("0");
binVal = binVal << 1;
r[1] = mid;
}
}
return binString.toString();
return binVal;
}

/**
Expand All @@ -179,27 +192,26 @@ public static String containingGeohash(Envelope2D envelope) {
double deltaLon = 360;
double deltaLat = 180;

while(xmin == xmax && ymin == ymax && chars < 25){

if(chars%2 == 0){
while (xmin == xmax && ymin == ymax && chars < 25) {
if (chars % 2 == 0) {
deltaLon = deltaLon / 8;
deltaLat = deltaLat / 4;
}else{
} else {
deltaLon = deltaLon / 4;
deltaLat = deltaLat / 8;
}

xmin = Math.floor(posMinX/deltaLon);
xmax = Math.floor(posMaxX/deltaLon);
ymin = Math.floor(posMinY/deltaLat);
ymax = Math.floor(posMaxY/deltaLat);
xmin = Math.floor(posMinX / deltaLon);
xmax = Math.floor(posMaxX / deltaLon);
ymin = Math.floor(posMinY / deltaLat);
ymax = Math.floor(posMaxY / deltaLat);

chars++;
}

if(chars == 1) return "";
return toGeohash(new Point2D(envelope.xmin, envelope.ymin), chars-1);
if (chars == 1) return "";

return toGeohash(new Point2D(envelope.xmin, envelope.ymin), chars - 1);
}

/**
Expand Down
72 changes: 30 additions & 42 deletions src/test/java/com/esri/core/geometry/TestGeohash.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,76 +72,64 @@ public void testGeohashToEnvelopeGoodDimensions2() {
assertEquals(latDiff, env.ymax - env.ymin, delta);
}

/**
* Check if BinaryToBase32 work as intended with a normal binary string
*/
@Test
public void testBinaryToBase32() {
String testStr = "011011111111011";
assertEquals("ezv", Geohash.binaryToBase32(testStr));
}

@Test
public void testConvertToBinary() {
double lat = 40.7128;
double lon = -74.0060;
String latStr = Geohash.convertToBinary(lat, new double[] { -90, 90 }, 10);
String lonStr = Geohash.convertToBinary(
lon,
new double[] { -180, 180 },
10
);

assertEquals("1011100111", latStr);
assertEquals("0100101101", lonStr);
}

@Test
public void testToGeoHash() {
Point2D p1 = new Point2D(-4.329,48.669);
Point2D p0 = new Point2D(0, 0);

Point2D p1 = new Point2D(-4.329, 48.669);
Point2D p2 = new Point2D(-30.382, 70.273);
Point2D p3 = new Point2D(14.276, 37.691);
Point2D p4 = new Point2D(-143.923, 48.669);
Point2D p5 = new Point2D(-143.923, 48.669);

int chrLen = 5;

String p0Hash = Geohash.toGeohash(p0, 1);

String p1Hash = Geohash.toGeohash(p1, chrLen);
String p2Hash = Geohash.toGeohash(p2, chrLen);
String p3Hash = Geohash.toGeohash(p3, chrLen);
String p4Hash = Geohash.toGeohash(p4, chrLen);
String p5Hash = Geohash.toGeohash(p5, 6);

assertEquals("s", p0Hash);
assertEquals("gbsuv", p1Hash);
assertEquals("gk6ru", p2Hash);
assertEquals("sqdnk", p3Hash);
assertEquals("bb9su", p4Hash);
assertEquals("bb9sug", p5Hash);
}

@Test
public void testToGeohashHasGoodPrecision(){
Point2D point = new Point2D(18.068581, 59.329323);
assertEquals(6, Geohash.toGeohash(point, 6).length());
public void testToGeohashHasGoodPrecision() {
Point2D point = new Point2D(18.068581, 59.329323);
assertEquals(6, Geohash.toGeohash(point, 6).length());
}

@Test
public void testToGeohash2(){
String expected = "u6sce";
Point2D point = new Point2D(18.068581, 59.329323);
String geoHash = Geohash.toGeohash(point, 5);
public void testToGeohash2() {
String expected = "u6sce";
Point2D point = new Point2D(18.068581, 59.329323);
String geoHash = Geohash.toGeohash(point, 5);

assertEquals(expected, geoHash);
assertEquals(expected, geoHash);
}

@Test
public void testContainingGeohashWithHugeValues(){
Envelope2D envelope = new Envelope2D(-179, -89, 179, 89);
assertEquals("", Geohash.containingGeohash(envelope));
public void testContainingGeohashWithHugeValues() {
Envelope2D envelope = new Envelope2D(-179, -89, 179, 89);
assertEquals("", Geohash.containingGeohash(envelope));
}

@Test
public void testContainingGeohash(){
Envelope2D envelope = new Envelope2D(-179, -89, -140, -50);
assertEquals("0", Geohash.containingGeohash(envelope));
public void testContainingGeohash() {
Envelope2D envelope = new Envelope2D(-179, -89, -140, -50);
assertEquals("0", Geohash.containingGeohash(envelope));
}

@Test
public void testContainingGeohash2(){
Envelope2D envelope = new Envelope2D(18.078, 59.3564, 18.1,59.3344);
public void testContainingGeohash2() {
Envelope2D envelope = new Envelope2D(18.078, 59.3564, 18.1, 59.3344);
assertEquals("u6sce", Geohash.containingGeohash(envelope));
}

Expand All @@ -162,7 +150,7 @@ public void testCoveringGeohashOneGeohash() {
public void testCoveringGeohashPoint() {
Envelope2D env = new Envelope2D(180,90,180,90);
String [] coverage = Geohash.coveringGeohash(env);
assertEquals("zzzzzzzzzzzzzzzzzzzzzzzz", coverage[0]);
assertEquals("zzzzzz", coverage[0]);
}

@Test
Expand Down

0 comments on commit 2aa650f

Please sign in to comment.