Sample code

Sample code implementations for GeoPo encoding and decoding methods are provided in various programming languages. Please note that these codes may contain programming errors or bugs, and have not been thoroughly tested.

If you implement more efficient algorithms or sample code in other languages, please contact us. We will post them here with your permission.

Existing sample codes
  1. JavaScript
  2. PHP
  3. C++
  4. Objective-C
  5. Perl
  6. Ruby
  7. Java
  8. Python
  9. Haskell
  10. 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;
}		

Note: Requires standard libraries "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		

Ruby implementation by id:faw. Thank you for the contribution.
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;

}		

Java implementation by takimura. Thank you for the contribution.

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		

Python implementation by id:faw. Thank you for the contribution.
http://d.hatena.ne.jp/faw/20090306/1236306272

10. Excel


GeoPo Encode in Excel function

The following "[]" notation refers to cell locations (e.g., A1, B4)

[latitude] = cell location containing latitude value
[longitude] = cell location containing longitude value
[chars] = cell location containing encoding characters, enter:
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"
(without quotes)

To display the 1st GeoPo code character, enter:
"=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)"
For the 2nd character:
"=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)"
For subsequent characters, decrease the second argument of POWER by 1 for each character.

Combine these GeoPo code cells using the "&" operator to create the complete code.

Example:
A1 = latitude, B1 = longitude, C1 = encoding characters
Enter the following formulas:
A2: "=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)"
B2: "=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)"
C2: "=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)"
D2: "=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)"
E2: "=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)"
F2: "=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)"
A3: "=A2&B2&C2&D2&E2&F2" (displays 6-character GeoPo code)
		

GeoPo Decode in Excel function

The following "[]" notation refers to cell locations (e.g., A1, B4)

[GeoPo] = cell location containing GeoPo code
[chars] = cell location containing encoding characters, enter:
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"
(without quotes)
This example uses a 6-character scale for demonstration.

To display latitude, enter:
"=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)"
To display longitude, enter:
"=(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"

Example:
A3 = 6-character GeoPo code, C1 = encoding characters
A1 (latitude): "=(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"
B1 (longitude): "=(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"
A1 will display latitude and B1 will display longitude.