Last active
August 29, 2015 14:13
-
-
Save linggom/aedbfe6ecd7c592951d8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* An utility to encode the point in GoogleMap API | |
* Reference see this {@link https://developers.google.com/maps/documentation/utilities/polylinealgorithm?csw=1} | |
* @author SRIN | |
* | |
*/ | |
public class MapUtil { | |
/** | |
* Step 1 : Take the decimal value and multiply it by 1e5, rounding the | |
* result | |
* | |
* @param value | |
* double value of a point | |
* @return decimal value after multiply it by 1e5 and rounding the result | |
*/ | |
private static int floor(double value) { | |
return (int) java.lang.Math.round(value * 1e5); | |
} | |
/** | |
* Step 3 : Convert the decimal value to binary. Note that a negative value | |
* must be calculated using its two's complement by inverting the binary | |
* value and adding one to the result | |
* | |
* Step 4 : Left-shift the binary value one bit | |
* | |
* Step 5 : If the original | |
* decimal value is negative, invert this encoding | |
* | |
* @param number of the decimal value | |
* @return the encoded point | |
*/ | |
private static String encodeSignedNumber(int num) { | |
int sgn_num = num << 1; | |
if (num < 0) { | |
sgn_num = ~(sgn_num); // inverse the bit : ~(101) will be 010 | |
} | |
return (encodeNumber(sgn_num)); | |
} | |
/** | |
* Step 7 : Place the 5-bit chunks into reverse order | |
* Step 8 : OR each value with 0x20 if another bit chunk | |
* Step 9 : Convert each value to decimal | |
* Step 10 : Add 63 to each value | |
* @param num of decimal value | |
* @return | |
*/ | |
private static String encodeNumber(int num) { | |
StringBuffer encodeString = new StringBuffer(); | |
while (num >= 0x20) { | |
encodeString.append((char) ((0x20 | (num & 0x1f)) + 63)); | |
num >>= 5; | |
} | |
encodeString.append((char) (num + 63)); | |
return encodeString.toString(); | |
} | |
/** | |
* encoded the single double value | |
* @param value single value from a point | |
* @return | |
*/ | |
private static String encoded(double value) { | |
int floor = floor(value); | |
return encodeSignedNumber(floor); | |
} | |
/** | |
* encoded given latitude and longitude of points. | |
* | |
* @param glatlngs | |
* Object with latitude and long given | |
* @return encoded string for the url | |
*/ | |
public static String encoded(GLatLong... glatlngs) { | |
String enc = ""; | |
GLatLong prev = null; | |
for (GLatLong gLatLong : glatlngs) { | |
if (prev == null) { | |
enc += encoded(gLatLong.getLat()) + encoded(gLatLong.getLng()); | |
} else { | |
enc += encoded(gLatLong.getLat() - prev.getLat()) | |
+ encoded(gLatLong.getLng() - prev.getLng()); | |
} | |
prev = gLatLong; | |
} | |
return enc; | |
} | |
/** | |
* Internal class to set a latitude and longitude of a point | |
* | |
* @author SRIN | |
* | |
*/ | |
public static class GLatLong { | |
private double lat; | |
private double lng; | |
public double getLat() { | |
return lat; | |
} | |
private void setLat(double lat) { | |
this.lat = lat; | |
} | |
public double getLng() { | |
return lng; | |
} | |
private void setLng(double lng) { | |
this.lng = lng; | |
} | |
public GLatLong(double lat, double lng) { | |
setLat(lat); | |
setLng(lng); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment