Faster GeoHashUtils
-------------------
Key: LUCENE-2965
URL: https://issues.apache.org/jira/browse/LUCENE-2965
Project: Lucene - Java
Issue Type: Improvement
Components: contrib/spatial
Affects Versions: 3.0.3, 3.0.2, 3.0.1, 3.0, 2.9.4, 2.9.2
Reporter: 朱文彬
I found the current implement of
org.apache.lucene.spatial.geohash.GeoHashUtils.encode and decode is slow and
this is my improvement (400% faster )
/**
* Encodes the given latitude and longitude into a geohash
*
* @param latitude Latitude to encode
* @param longitude Longitude to encode
* @return Geohash encoding of the longitude and latitude
*/
public static String encode(double latitude, double longitude) {
double latL = -90, latH = 90;
double lngL = -180, lngH = 180;
double mid;
// assert PRECISION % 2 == 0;
final char[] geohash = new char[PRECISION];
int len = 0;
int ch = 0;
while (len < PRECISION) {
if (longitude > (mid = (lngL + lngH) * 0.5)) {
ch |= 16;
lngL = mid;
} else
lngH = mid;
if (longitude > (mid = (lngL + lngH) * 0.5)) {
ch |= 4;
lngL = mid;
} else
lngH = mid;
if (longitude > (mid = (lngL + lngH) * 0.5)) {
ch |= 1;
lngL = mid;
} else {
lngH = mid;
}
if (latitude > (mid = (latL + latH) * 0.5)) {
ch |= 8;
latL = mid;
} else {
latH = mid;
}
if (latitude > (mid = (latL + latH) * 0.5)) {
ch |= 2;
latL = mid;
} else {
latH = mid;
}
geohash[len++] = BASE_32[ch];
ch = 0;
if (latitude > (mid = (latL + latH) * 0.5)) {
ch |= 16;
latL = mid;
} else
latH = mid;
if (longitude > (mid = (lngL + lngH) * 0.5)) {
ch |= 8;
lngL = mid;
} else
lngH = mid;
if (latitude > (mid = (latL + latH) * 0.5)) {
ch |= 4;
latL = mid;
} else
latH = mid;
if (longitude > (mid = (lngL + lngH) * 0.5)) {
ch |= 2;
lngL = mid;
} else
lngH = mid;
if (latitude > (mid = (latL + latH) * 0.5)) {
ch |= 1;
latL = mid;
} else
latH = mid;
geohash[len++] = BASE_32[ch];
ch = 0;
}
return new String(geohash);
}
/**
* Decodes the given geohash into a latitude and longitude
*
* @param geohash Geohash to deocde
* @return Array with the latitude at index 0, and longitude at index 1
*/
public static double[] decode(String geohash) {
double latL = -90.0, latH = 90.0;
double lngL = -180.0, lngH = 180.0;
double gap;
int len = geohash.length();
for (int i = 0; i < len; ) {
switch (geohash.charAt(i++)) {
case '0':
latH -= (latH - latL) * 0.75;
lngH -= (lngH - lngL) * 0.875;
break;
case '1':
latH -= (latH - latL) * 0.75;
gap = lngH - lngL;
lngL += gap * 0.125;
lngH -= gap * 0.75;
break;
case '2':
gap = latH - latL;
latL += gap * 0.25;
latH -= gap * 0.5;
lngH -= (lngH - lngL) * 0.875;
break;
case '3':
gap = latH - latL;
latL += gap * 0.25;
latH -= gap * 0.5;
gap = lngH - lngL;
lngL += gap * 0.125;
lngH -= gap * 0.75;
break;
case '4':
latH -= (latH - latL) * 0.75;
gap = lngH - lngL;
lngL += gap * 0.25;
lngH -= gap * 0.625;
break;
case '5':
latH -= (latH - latL) * 0.75;
gap = lngH - lngL;
lngL += gap * 0.375;
lngH -= gap * 0.5;
break;
case '6':
gap = latH - latL;
latL += gap * 0.25;
latH -= gap * 0.5;
gap = lngH - lngL;
lngL += gap * 0.25;
lngH -= gap * 0.625;
break;
case '7':
gap = latH - latL;
latL += gap * 0.25;
latH -= gap * 0.5;
gap = lngH - lngL;
lngL += gap * 0.375;
lngH -= gap * 0.5;
break;
case '8':
gap = latH - latL;
latL += gap * 0.5;
latH -= gap * 0.25;
lngH -= (lngH - lngL) * 0.875;
break;
case '9':
gap = latH - latL;
latL += gap * 0.5;
latH -= gap * 0.25;
gap = lngH - lngL;
lngL += gap * 0.125;
lngH -= gap * 0.75;
break;
case 'b':
latL += (latH - latL) * 0.75;
lngH -= (lngH - lngL) * 0.875;
break;
case 'c':
latL += (latH - latL) * 0.75;
gap = lngH - lngL;
lngL += gap * 0.125;
lngH -= gap * 0.75;
break;
case 'd':
gap = latH - latL;
latL += gap * 0.5;
latH -= gap * 0.25;
gap = lngH - lngL;
lngL += gap * 0.25;
lngH -= gap * 0.625;
break;
case 'e':
gap = latH - latL;
latL += gap * 0.5;
latH -= gap * 0.25;
gap = lngH - lngL;
lngL += gap * 0.375;
lngH -= gap * 0.5;
break;
case 'f':
latL += (latH - latL) * 0.75;
gap = lngH - lngL;
lngL += gap * 0.25;
lngH -= gap * 0.625;
break;
case 'g':
latL += (latH - latL) * 0.75;
gap = lngH - lngL;
lngL += gap * 0.375;
lngH -= gap * 0.5;
break;
case 'h':
latH -= (latH - latL) * 0.75;
gap = lngH - lngL;
lngL += gap * 0.5;
lngH -= gap * 0.375;
break;
case 'j':
latH -= (latH - latL) * 0.75;
gap = lngH - lngL;
lngL += gap * 0.625;
lngH -= gap * 0.25;
break;
case 'k':
gap = latH - latL;
latL += gap * 0.25;
latH -= gap * 0.5;
gap = lngH - lngL;
lngL += gap * 0.5;
lngH -= gap * 0.375;
break;
case 'm':
gap = latH - latL;
latL += gap * 0.25;
latH -= gap * 0.5;
gap = lngH - lngL;
lngL += gap * 0.625;
lngH -= gap * 0.25;
break;
case 'n':
latH -= (latH - latL) * 0.75;
gap = lngH - lngL;
lngL += gap * 0.75;
lngH -= gap * 0.125;
break;
case 'p':
latH -= (latH - latL) * 0.75;
lngL += (lngH - lngL) * 0.875;
break;
case 'q':
gap = latH - latL;
latL += gap * 0.25;
latH -= gap * 0.5;
gap = lngH - lngL;
lngL += gap * 0.75;
lngH -= gap * 0.125;
break;
case 'r':
gap = latH - latL;
latL += gap * 0.25;
latH -= gap * 0.5;
lngL += (lngH - lngL) * 0.875;
break;
case 's':
gap = latH - latL;
latL += gap * 0.5;
latH -= gap * 0.25;
gap = lngH - lngL;
lngL += gap * 0.5;
lngH -= gap * 0.375;
break;
case 't':
gap = latH - latL;
latL += gap * 0.5;
latH -= gap * 0.25;
gap = lngH - lngL;
lngL += gap * 0.625;
lngH -= gap * 0.25;
break;
case 'u':
latL += (latH - latL) * 0.75;
gap = lngH - lngL;
lngL += gap * 0.5;
lngH -= gap * 0.375;
break;
case 'v':
latL += (latH - latL) * 0.75;
gap = lngH - lngL;
lngL += gap * 0.625;
lngH -= gap * 0.25;
break;
case 'w':
gap = latH - latL;
latL += gap * 0.5;
latH -= gap * 0.25;
gap = lngH - lngL;
lngL += gap * 0.75;
lngH -= gap * 0.125;
break;
case 'x':
gap = latH - latL;
latL += gap * 0.5;
latH -= gap * 0.25;
lngL += (lngH - lngL) * 0.875;
break;
case 'y':
latL += (latH - latL) * 0.75;
gap = lngH - lngL;
lngL += gap * 0.75;
lngH -= gap * 0.125;
break;
case 'z':
latL += (latH - latL) * 0.75;
lngL += (lngH - lngL) * 0.875;
break;
}
switch (geohash.charAt(i++)) {
case '0':
latH -= (latH - latL) * 0.875;
lngH -= (lngH - lngL) * 0.75;
break;
case '1':
gap = latH - latL;
latL += gap * 0.125;
latH -= gap * 0.75;
lngH -= (lngH - lngL) * 0.75;
break;
case '2':
latH -= (latH - latL) * 0.875;
gap = lngH - lngL;
lngL += gap * 0.25;
lngH -= gap * 0.5;
break;
case '3':
gap = latH - latL;
latL += gap * 0.125;
latH -= gap * 0.75;
gap = lngH - lngL;
lngL += gap * 0.25;
lngH -= gap * 0.5;
break;
case '4':
gap = latH - latL;
latL += gap * 0.25;
latH -= gap * 0.625;
lngH -= (lngH - lngL) * 0.75;
break;
case '5':
gap = latH - latL;
latL += gap * 0.375;
latH -= gap * 0.5;
lngH -= (lngH - lngL) * 0.75;
break;
case '6':
gap = latH - latL;
latL += gap * 0.25;
latH -= gap * 0.625;
gap = lngH - lngL;
lngL += gap * 0.25;
lngH -= gap * 0.5;
break;
case '7':
gap = latH - latL;
latL += gap * 0.375;
latH -= gap * 0.5;
gap = lngH - lngL;
lngL += gap * 0.25;
lngH -= gap * 0.5;
break;
case '8':
latH -= (latH - latL) * 0.875;
gap = lngH - lngL;
lngL += gap * 0.5;
lngH -= gap * 0.25;
break;
case '9':
gap = latH - latL;
latL += gap * 0.125;
latH -= gap * 0.75;
gap = lngH - lngL;
lngL += gap * 0.5;
lngH -= gap * 0.25;
break;
case 'b':
latH -= (latH - latL) * 0.875;
lngL += (lngH - lngL) * 0.75;
break;
case 'c':
gap = latH - latL;
latL += gap * 0.125;
latH -= gap * 0.75;
lngL += (lngH - lngL) * 0.75;
break;
case 'd':
gap = latH - latL;
latL += gap * 0.25;
latH -= gap * 0.625;
gap = lngH - lngL;
lngL += gap * 0.5;
lngH -= gap * 0.25;
break;
case 'e':
gap = latH - latL;
latL += gap * 0.375;
latH -= gap * 0.5;
gap = lngH - lngL;
lngL += gap * 0.5;
lngH -= gap * 0.25;
break;
case 'f':
gap = latH - latL;
latL += gap * 0.25;
latH -= gap * 0.625;
lngL += (lngH - lngL) * 0.75;
break;
case 'g':
gap = latH - latL;
latL += gap * 0.375;
latH -= gap * 0.5;
lngL += (lngH - lngL) * 0.75;
break;
case 'h':
gap = latH - latL;
latL += gap * 0.5;
latH -= gap * 0.375;
lngH -= (lngH - lngL) * 0.75;
break;
case 'j':
gap = latH - latL;
latL += gap * 0.625;
latH -= gap * 0.25;
lngH -= (lngH - lngL) * 0.75;
break;
case 'k':
gap = latH - latL;
latL += gap * 0.5;
latH -= gap * 0.375;
gap = lngH - lngL;
lngL += gap * 0.25;
lngH -= gap * 0.5;
break;
case 'm':
gap = latH - latL;
latL += gap * 0.625;
latH -= gap * 0.25;
gap = lngH - lngL;
lngL += gap * 0.25;
lngH -= gap * 0.5;
break;
case 'n':
gap = latH - latL;
latL += gap * 0.75;
latH -= gap * 0.125;
lngH -= (lngH - lngL) * 0.75;
break;
case 'p':
latL += (latH - latL) * 0.875;
lngH -= (lngH - lngL) * 0.75;
break;
case 'q':
gap = latH - latL;
latL += gap * 0.75;
latH -= gap * 0.125;
gap = lngH - lngL;
lngL += gap * 0.25;
lngH -= gap * 0.5;
break;
case 'r':
latL += (latH - latL) * 0.875;
gap = lngH - lngL;
lngL += gap * 0.25;
lngH -= gap * 0.5;
break;
case 's':
gap = latH - latL;
latL += gap * 0.5;
latH -= gap * 0.375;
gap = lngH - lngL;
lngL += gap * 0.5;
lngH -= gap * 0.25;
break;
case 't':
gap = latH - latL;
latL += gap * 0.625;
latH -= gap * 0.25;
gap = lngH - lngL;
lngL += gap * 0.5;
lngH -= gap * 0.25;
break;
case 'u':
gap = latH - latL;
latL += gap * 0.5;
latH -= gap * 0.375;
lngL += (lngH - lngL) * 0.75;
break;
case 'v':
gap = latH - latL;
latL += gap * 0.625;
latH -= gap * 0.25;
lngL += (lngH - lngL) * 0.75;
break;
case 'w':
gap = latH - latL;
latL += gap * 0.75;
latH -= gap * 0.125;
gap = lngH - lngL;
lngL += gap * 0.5;
lngH -= gap * 0.25;
break;
case 'x':
latL += (latH - latL) * 0.875;
gap = lngH - lngL;
lngL += gap * 0.5;
lngH -= gap * 0.25;
break;
case 'y':
gap = latH - latL;
latL += gap * 0.75;
latH -= gap * 0.125;
lngL += (lngH - lngL) * 0.75;
break;
case 'z':
latL += (latH - latL) * 0.875;
lngL += (lngH - lngL) * 0.75;
break;
}
}
return new double[] { (latL + latH) / 2D, (lngL + lngH) / 2D };
}
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
