There are sample codes implemented encoding and decoding method of GeoPo code in various computer languages. Also these has mistakes of programing or bug codes. And we didn't enough tests.
Please contact us when you implement efficient algorithm or sample codes in other languages. We will post there, if you allow to public.
Existing sample codes
- JavaScript
- PHP
- C++
- Objective-C
- Perl
- Ruby
- Java
- Python
- Haskell
- Excel
1. JavaScript
/*
* GeoPo Encode in JavaScript
* @author : Shintaro Inagaki
* @param location (Object)
* @return geopo (String)
*/
function geopoEncode(location){
// 64characters (number + big and small letter + hyphen + underscore)
var chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
var geopo = new String();
var lat = parseFloat(location.lat); // Parse as float
var lng = parseFloat(location.lng); // Parse as float
var scale = parseInt(location.scale); // Parse as int
// Change a degree measure to a decimal number
lat = (lat + 90) / 180 * Math.pow(8, 10);
lng = (lng + 180) / 360 * Math.pow(8, 10);
// Compute a GeoPo code from head and concatenate
for(var i = 0; i < scale; i++) {
geopo = geopo + chars.substr(Math.floor(lat / Math.pow(8, 9 - i) % 8) + Math.floor(lng / Math.pow(8, 9 - i) % 8) * 8, 1);
}
return geopo;
}
/*
* GeoPo Decode in JavaScript
* @author : Shintaro Inagaki
* @param geopo (String)
* @return location (Object)
*/
function geopoDecode(geopo){
// 64characters (number + big and small letter + hyphen + underscore)
var chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
var location = new Object();
var lat = 0;
var lng = 0;
var scale = geopo.length; // Scale is length of GeoPo code
var order = 0;
for (var i = 0; i < scale; i++) {
// What number of character that equal to a GeoPo code (0-63)
order = chars.indexOf(geopo.substr(i, 1));
// Lat/Lng plus geolocation value of scale
lat = lat + Math.floor(order % 8) * Math.pow(8, 9 - i);
lng = lng + Math.floor(order / 8) * Math.pow(8, 9 - i);
}
// Change a decimal number to a degree measure, and plus revised value that shift center of area
location.lat = lat * 180 / Math.pow(8, 10) + 180 / Math.pow(8, scale) / 2 - 90;
location.lng = lng * 360 / Math.pow(8, 10) + 360 / Math.pow(8, scale) / 2 - 180;
location.scale = scale;
return location;
}
2. PHP
/*
* GeoPo Encode in PHP
* @author : Shintaro Inagaki
* @param $location (Array)
* @return $geopo (String)
*/
function geopoEncode($location) {
// 64characters (number + big and small letter + hyphen + underscore)
$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
$geopo = "";
$lat = $location['lat'];
$lng = $location['lng'];
$scale = $location['scale'];
// Change a degree measure to a decimal number
$lat = ($lat + 90) / 180 * pow(8, 10);
$lng = ($lng + 180) / 360 * pow(8, 10);
// Compute a GeoPo code from head and concatenate
for($i = 0; $i < $scale; $i++) {
$geopo .= substr($chars, floor($lat / pow(8, 9 - $i) % 8) + floor($lng / pow(8, 9 - $i) % 8) * 8, 1);
}
return $geopo;
}
/*
* GeoPo Decode in PHP
* @author : Shintaro Inagaki
* @param $geopo (String)
* @return $location (Array)
*/
function geopoDecode($geopo) {
// 64characters (number + big and small letter + hyphen + underscore)
$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
// Array for geolocation
$location = array ();
for ($i = 0; $i < strlen($geopo); $i++) {
// What number of character that equal to a GeoPo code (0-63)
$order = strpos($chars, substr($geopo, $i, 1));
// Lat/Lng plus geolocation value of scale
$location['lat'] = $location['lat'] + floor($order % 8) * pow(8, 9 - $i);
$location['lng'] = $location['lng'] + floor($order / 8) * pow(8, 9 - $i);
}
// Change a decimal number to a degree measure, and plus revised value that shift center of area
$location['lat'] = $location['lat'] * 180 / pow(8, 10) + 180 / pow(8, strlen($geopo)) / 2 - 90;
$location['lng'] = $location['lng'] * 360 / pow(8, 10) + 360 / pow(8, strlen($geopo)) / 2 - 180;
$location['scale'] = strlen($geopo);
return $location;
}
3. C++
/*
* GeoPo Encode in C++
* @author : Shintaro Inagaki
* @param geopo, lat lng, scale (pointer)
*/
void geopoEncode(char *geopo, double &lat, double &lng, int &scale)
{
// 64characters (number + big and small letter + hyphen + underscore)
char chars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
int i;
// Change a degree measure to a decimal number
lat = (lat + 90) / 180 * pow(8.0, 10.0);
lng = (lng + 180) / 360 * pow(8.0, 10.0);
// Compute a GeoPo code from head and concatenate
for(i = 0;i < scale;i++){
geopo[i] = chars[(int)(floor(fmod(lat / pow(8.0, 9.0 - i), 8.0)) + floor(fmod(lng / pow(8.0, 9.0 - i), 8.0)) * 8)];
}
geopo[i] = '\0';
}
/*
* GeoPo Decode in C++
* @author : Shintaro Inagaki
* @param geopo, lat lng, scale (pointer)
*/
void geopoDecode(char *geopo, double &lat, double &lng, int &scale)
{
// 64characters (number + big and small letter + hyphen + underscore)
char chars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
int order, i;
scale = strlen(geopo);
for(i = 0;i < scale;i++){
// What number of character that equal to a GeoPo code (0-63)
order = (strchr(chars, geopo[i]) - chars);
// Lat/Lng plus geolocation value of scale
lat = lat + fmod(order, 8.0) * pow(8.0, 9.0 - i);
lng = lng + floor((double)order / 8.0) * pow(8.0, 9.0 - i);
}
// Change a decimal number to a degree measure, and plus revised value that shift center of area
lat = lat * 180 / pow(8.0, 10.0) - 90 + 180 / pow(8.0, scale) / 2;
lng = lng * 360 / pow(8.0, 10.0) - 180 + 360 / pow(8.0, scale) / 2;
}
Caution:use standard library "stdio.h", "math.h" and "string.h"
4. Objective-C
/*
* GeoPo Encode in Objective-C
* @author : Shintaro Inagaki
* @param geopo, latitude, longitude, scale (pointer)
*/
-(void)encodeGeopo:(id)geopo latitude:(double *)lat longitude:(double *)lng scale:(int *)scale {
NSString *chars = @"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
*lat = (*lat + 90) / 180 * pow(8.0, 10.0);
*lng = (*lng + 180) / 360 * pow(8.0, 10.0);
for(int i = 0; i < *scale; i++){
[geopo appendString:[chars substringWithRange:NSMakeRange(floor(fmod(*lat / pow(8.0, 9.0 - i), 8.0)) + floor(fmod(*lng / pow(8.0, 9.0 - i), 8.0)) * 8, 1)]];
}
}
/*
* GeoPo Decode in Objective-C
* @author : Shintaro Inagaki
* @param geopo, latitude, longitude, scale (pointer)
*/
-(void)decodeGeopo:(id)geopo latitude:(double *)lat longitude:(double *)lng scale:(int *)scale {
NSString *chars = @"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
int order;
*scale = [geopo length];
for (int i = 0; i < *scale; i++) {
order = NSMaxRange([chars rangeOfString:[geopo substringWithRange:NSMakeRange(i, 1)]]) - 1;
*lat += (order % 8) * pow(8, 9 - i);
*lng += floor(order / 8) * pow(8, 9 - i);
}
*lat = *lat * 180 / pow(8, 10) + 180 / pow(8, *scale) / 2 - 90;
*lng = *lng * 360 / pow(8, 10) + 360 / pow(8, *scale) / 2 - 180;
}
5. Perl
#
# GeoPo Encode in Perl
# @author : Shintaro Inagaki
# @param %location (Hash) [lat (Float), lng (Float), scale(Int)]
# @return $geopo (String)
#
sub geopoEncode(%location) {
# 64characters (number + big and small letter + hyphen + underscore)
$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
$geopo = "";
$lat = $location{'lat'};
$lng = $location{'lng'};
$scale = $location{'scale'};
# Change a degree measure to a decimal number
$lat = ($lat + 90) / 180 * 8 ** 10;
$lng = ($lng + 180) / 360 * 8 ** 10;
# Compute a GeoPo code from head and concatenate
for($i = 0; $i < $scale; $i++) {
$geopo .= substr($chars, int($lat / 8 ** (9 - $i) % 8) + int($lng / 8 ** (9 - $i) % 8) * 8, 1);
}
return $geopo;
}
#
# GeoPo Decode in Perl
# @author : Shintaro Inagaki
# @param $geopo (String)
# @return %location (Hash) [lat (Float), lng (Float), scale(Int)]
#
sub geopoDecode($geopo) {
# 64characters (number + big and small letter + hyphen + underscore)
$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
# Hash for geolocation
%location = ();
for ($i = 0; $i < length($geopo); $i++) {
# What number of character that equal to a GeoPo code (0-63)
$order = index($chars, substr($geopo, $i, 1));
# Lat/Lng plus geolocation value of scale
$location{'lat'} += $order % 8 * 8 ** (9 - $i);
$location{'lng'} += int($order / 8) * 8 ** (9 - $i);
}
# Change a decimal number to a degree measure, and plus revised value that shift center of area
$location{'lat'} = $location{'lat'} * 180 / 8 ** 10 - 90 + 180 / 8 ** length($geopo) / 2;
$location{'lng'} = $location{'lng'} * 360 / 8 ** 10 - 180 + 360 / 8 ** length($geopo) / 2;
$location{'scale'} = length($geopo);
return %location;
}
6. Ruby
#
# GeoPo Encode in Ruby
# @author : Shintaro Inagaki
# @param location (Hash) [lat (Float), lng (Float), scale(Int)]
# @return geopo (String)
#
def geopoEncode(location)
# 64characters (number + big and small letter + hyphen + underscore)
chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"
geopo = ""
lat = location['lat']
lng = location['lng']
scale = location['scale']
# Change a degree measure to a decimal number
lat = (lat + 90.0) / 180 * 8 ** 10; # 90.0 is forced FLOAT type when lat is INT
lng = (lng + 180.0) / 360 * 8 ** 10; # 180.0 is same
# Compute a GeoPo code from head and concatenate
for i in 0..scale
geopo += chars[(lat / 8 ** (9 - i) % 8).floor + (lng / 8 ** (9 - i) % 8).floor * 8, 1];
end
return geopo;
end
#
# GeoPo Decode in Ruby
# @author : Shintaro Inagaki
# @param geopo (String)
# @return location (Hash) [lat (Float), lng (Float), scale(Int)]
#
def geopoDecode(geopo)
# 64characters (number + big and small letter + hyphen + underscore)
chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"
# Hash for geolocation
location = {}
lat = 0.0
lng = 0.0
scale = geopo.size # Scale is length of GeoPo code
order = 0
for i in 0..(scale - 1)
# What number of character that equal to a GeoPo code (0-63)
order = chars.index(geopo[i])
# Lat/Lng plus geolocation value of scale
lat = lat + order % 8 * 8 ** (9 - i)
lng = lng + (order / 8).floor * 8 ** (9 - i)
end
# Change a decimal number to a degree measure, and plus revised value that shift center of area
location['lat'] = lat * 180 / 8 ** 10 - 90 + 180 / 8 ** scale / 2
location['lng'] = lng * 360 / 8 ** 10 - 180 + 360 / 8 ** scale / 2
location['scale'] = scale
return location
end
Implemented in Ruby by id:faw. Thank you for coding.
http://d.hatena.ne.jp/faw/20090306/1236310192
7. Java
/**
* GeoPo Encode in Java.
*
* @param lat latitude
* @param lng longnitude
* @param scale scale of map
* @return geopo code
*/
public static String encode(double lat, double lng, int scale) {
// 64characters (number + big and small letter + hyphen + underscore).
final String chars =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
StringBuffer geopo = new StringBuffer();
lat = (lat + 90) / 180 * Math.pow(8, 10);
lng = (lng + 180) / 360 * Math.pow(8, 10);
for(int i = 0; i < scale; i++) {
geopo.append(
chars.charAt((int)(Math.floor(lat / Math.pow(8, 9 - i) % 8)
+ Math.floor(lng / Math.pow(8, 9 - i) % 8) * 8)));
}
return geopo.toString();
}
/**
* GeoPo Decode in Java.
*
* @param geopo geopo code
* @return latitude and longnitude
*/
public static double[] decode(String geopo) {
// 64characters (number + big and small letter + hyphen + underscore).
final String chars =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
int scale = geopo.length();
double[] loc = new double[2];
loc[0] = 0;
loc[1] = 0;
for(int i = 0; i < scale; i++) {
int order = chars.indexOf(geopo.charAt(i));
loc[0] += Math.floor(order % 8) * Math.pow(8, 9 - i);
loc[1] += Math.floor(order / 8) * Math.pow(8, 9 - i);
}
loc[0] = loc[0] * 180 / Math.pow(8, 10) - 90 + 180 / Math.pow(8, scale) / 2;
loc[1] = loc[1] * 360 / Math.pow(8, 10) - 180 + 360 / Math.pow(8, scale) / 2;
return loc;
}
Above code was implemented in Java by takimura. Thank you for coding.
8. Python
#
# GeoPo Encode in Python
# @author : Shintaro Inagaki
# @param location (Dictionary) [lat (Float), lng (Float), scale(Int)]
# @return geopo (String)
#
def geopoEncode(location) :
# 64characters (number + big and small letter + hyphen + underscore)
chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"
geopo = ""
lat = location['lat']
lng = location['lng']
scale = location['scale']
# Change a degree measure to a decimal number
lat = (lat + 90.0) / 180 * 8 ** 10 # 90.0 is forced FLOAT type when lat is INT
lng = (lng + 180.0) / 360 * 8 ** 10 # 180.0 is same
# Compute a GeoPo code from head and concatenate
for i in range(scale):
order = int(lat / (8 ** (9 - i)) % 8) + int(lng / (8 ** (9 - i)) % 8) * 8
geopo = geopo + chars[order]
return geopo
#
# GeoPo Decode in Python
# @author : Shintaro Inagaki
# @param geopo (String)
# @return location (Dictionary) [lat (Float), lng (Float), scale(Int)]
#
def geopoDecode(geopo) :
# 64characters (number + big and small letter + hyphen + underscore)
chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"
lat = 0.0
lng = 0.0
scale = len(geopo) # Scale is length of GeoPo code
order = 0
for i in range(scale):
# What number of character that equal to a GeoPo code (0-63)
order = chars.find(geopo[i])
# Lat/Lng plus geolocation value of scale
lat = lat + order % 8 * 8 ** (9 - i)
lng = lng + int(order / 8) * 8 ** (9 - i)
# Change a decimal number to a degree measure, and plus revised value
that shift center of area
location['lat'] = lat * 180 / 8 ** 10 - 90 + 180 / 8 ** scale / 2
location['lng'] = lng * 360 / 8 ** 10 - 180 + 360 / 8 ** scale / 2
location['scale'] = scale
return location
Implemented in Python by id:faw. Thank you for coding.
http://d.hatena.ne.jp/faw/20090306/1236306272
10. Excel
GeoPo Encode in Excel function
Following "[]" means location of cell (ex. A1,B4)
[latitude] is location of latitude entry cell
[longitude] is location of longitude entry cell
[chars] is location of characters to use encoding entry cell and
enter "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"
(exclude "")
Enter the cell of display 1st GeoPo code
"=MID([chars],INT(MOD(([latitude]+90)/180*POWER(8,10)/POWER(8,9),8))+INT(MOD(([longitude]+180)/360*POWER(8,10)/POWER(8,9),8))*8+1,1)"
by the same token,
"=MID([chars],INT(MOD(([latitude]+90)/180*POWER(8,10)/POWER(8,8),8))+INT(MOD(([longitude]+180)/360*POWER(8,10)/POWER(8,8),8))*8+1,1)"
2nd argument of POWER minus 1 is 2nd GeoPo code, and repeat after 2nd character.
Then, you can make GeoPo code characters to combine these GeoPo code cells using by "&"
(Ex.)
A1 is latitude, B1 is longintude and C1 is characters to use encoding
Enter "=MID(C1,INT(MOD((A1+90)/180*POWER(8,10)/POWER(8,9),8))+INT(MOD((B1+180)/360*POWER(8,10)/POWER(8,9),8))*8+1,1)" at A2
Enter "=MID(C1,INT(MOD((A1+90)/180*POWER(8,10)/POWER(8,8),8))+INT(MOD((B1+180)/360*POWER(8,10)/POWER(8,8),8))*8+1,1)" at B2
Enter "=MID(C1,INT(MOD((A1+90)/180*POWER(8,10)/POWER(8,7),8))+INT(MOD((B1+180)/360*POWER(8,10)/POWER(8,7),8))*8+1,1)" at C2
Enter "=MID(C1,INT(MOD((A1+90)/180*POWER(8,10)/POWER(8,6),8))+INT(MOD((B1+180)/360*POWER(8,10)/POWER(8,6),8))*8+1,1)" at D2
Enter "=MID(C1,INT(MOD((A1+90)/180*POWER(8,10)/POWER(8,5),8))+INT(MOD((B1+180)/360*POWER(8,10)/POWER(8,5),8))*8+1,1)" at E2
Enter "=MID(C1,INT(MOD((A1+90)/180*POWER(8,10)/POWER(8,4),8))+INT(MOD((B1+180)/360*POWER(8,10)/POWER(8,4),8))*8+1,1)" at F2
Enter "=A2&B2&C2&D2&E2&F2" at A3, A3 display 6 characters GeoPo code.
GeoPo Decode in Excel function
Following "[]" means location of cell (ex. A1,B4)
[GeoPo] is location of GeoPo code entry cell
[chars] is location of characters to use encoding entry cell and
enter "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"
(exclude "")
Scale is 6 characters for descriptive purposes.
Enter the cell of display latitude
"=MOD(FIND(MID([GeoPo],1,1),[chars])-1,8)*POWER(8,9)+MOD(FIND(MID([GeoPo],2,1),[chars])-1,8)*POWER(8,8)+MOD(FIND(MID([GeoPo],3,1),[chars])-1,8)*POWER(8,7)+MOD(FIND(MID([GeoPo],4,1),[chars])-1,8)*POWER(8,6)+MOD(FIND(MID([GeoPo],5,1),[chars])-1,8)*POWER(8,5)+MOD(FIND(MID([GeoPo],6,1),[chars])-1,8)*POWER(8,4)"
Enter the cell of display longitude
"=(INT((FIND(MID([GeoPo],1,1),[chars])-1)/8)*POWER(8,9)+INT((FIND(MID([GeoPo],2,1),[chars])-1)/8)*POWER(8,8)+INT((FIND(MID([GeoPo],3,1),[chars])-1)/8)*POWER(8,7)+INT((FIND(MID([GeoPo],4,1),[chars])-1)/8)*POWER(8,6)+INT((FIND(MID([GeoPo],5,1),[chars])-1)/8)*POWER(8,5)+INT((FIND(MID([GeoPo],6,1),[chars])-1)/8)*POWER(8,4))*360/POWER(8,10)+360/POWER(8,6)/2-180"
(Ex.)
A3 is 6 characters GeoPo code and C1 is characters to use encoding
Enter "=(MOD(FIND(MID(A3,1,1),C1)-1,8)*POWER(8,9)+MOD(FIND(MID(A3,2,1),C1)-1,8)*POWER(8,8)+MOD(FIND(MID(A3,3,1),C1)-1,8)*POWER(8,7)+MOD(FIND(MID(A3,4,1),C1)-1,8)*POWER(8,6)+MOD(FIND(MID(A3,5,1),C1)-1,8)*POWER(8,5)+MOD(FIND(MID(A3,6,1),C1)-1,8)*POWER(8,4))*180/POWER(8,10)+180/POWER(8,6)/2-90" at A1
Enter "=(INT((FIND(MID(A3,1,1),C1)-1)/8)*POWER(8,9)+INT((FIND(MID(A3,2,1),C1)-1)/8)*POWER(8,8)+INT((FIND(MID(A3,3,1),C1)-1)/8)*POWER(8,7)+INT((FIND(MID(A3,4,1),C1)-1)/8)*POWER(8,6)+INT((FIND(MID(A3,5,1),C1)-1)/8)*POWER(8,5)+INT((FIND(MID(A3,6,1),C1)-1)/8)*POWER(8,4))*360/POWER(8,10)+360/POWER(8,6)/2-180" at B1
A1 display latitude and B1 display longitude.