-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
83 additions
and
49 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,7 @@ | |
}, | ||
"autoload": { | ||
"psr-4": { | ||
"ImSaikiran\\Geohash\\": "src" | ||
"Sk\\Geohash\\": "src" | ||
} | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
<?php | ||
|
||
namespace ImSaikiran\Geohash; | ||
namespace Sk\Geohash; | ||
|
||
/** | ||
* @author SaikiranCh <[email protected]> | ||
* @author Saikiran Ch <[email protected]> | ||
* @class Geohash | ||
* @description Algorithm to encode geographic coordinates to a string of letters and digits | ||
*/ | ||
|
@@ -14,53 +14,31 @@ class Geohash | |
*/ | ||
protected $base32Mapping = "0123456789bcdefghjkmnpqrstuvwxyz"; | ||
|
||
/** | ||
* Decodes geohash from base 32 | ||
* @param string Geohash | ||
* @return string Binary String | ||
*/ | ||
public function characterMapping($geohash) { | ||
$geohashArray = array(); | ||
|
||
for ($i=0; $i < strlen($geohash); $i++) { | ||
$geohashArray[] = $geohash[$i]; | ||
} | ||
|
||
$r = ""; | ||
foreach($geohashArray as $g) { | ||
if (($position = stripos($this->base32Mapping, $g)) !== FALSE) { | ||
$r .= str_pad(decbin($position), 5, "0", STR_PAD_LEFT); | ||
} else { | ||
$r .= "00000"; | ||
} | ||
} | ||
return $r; | ||
} | ||
|
||
/** | ||
* Encode the latitude and longitude into a hashed string | ||
* @param float Latitude | ||
* @param float longitude | ||
* @param int GeohashLength | ||
* @return string Hashed string obtained from the coordinates | ||
*/ | ||
public function encode($latitude, $Longitude, $geohashLength = 5) { | ||
// Get latitude and longitude bits length from $geohashLength | ||
if ($geohashLength%2 == 0) { | ||
public function encode($latitude, $Longitude, $geohashLength = 5) | ||
{ | ||
// Get latitude and longitude bits length from given geohash Length | ||
if ($geohashLength % 2 == 0) { | ||
$latBitsLength = $lonBitsLength = ($geohashLength/2) * 5; | ||
} else { | ||
$latBitsLength = (ceil($geohashLength/2)*5) - 3; | ||
$latBitsLength = (ceil($geohashLength / 2) * 5) - 3; | ||
$lonBitsLength = $latBitsLength + 1; | ||
} | ||
|
||
// Get the latitude and longitude binary bits | ||
// Convert the coordinates into binary format | ||
$binaryString = ""; | ||
$latbits = $this->getBits($latitude, -90, 90, $latBitsLength); | ||
$lonbits = $this->getBits($Longitude, -180, 180, $lonBitsLength); | ||
$binaryLength = strlen($latbits) + strlen($lonbits); | ||
|
||
// Combine the lat and lon bits and get the binaryString | ||
for ($i=1 ; $i < $binaryLength+1; $i++) { | ||
for ($i=1 ; $i < $binaryLength + 1; $i++) { | ||
if ($i%2 == 0) { | ||
$pos = (int)($i-2)/2; | ||
$binaryString .= $latbits[$pos]; | ||
|
@@ -74,7 +52,7 @@ public function encode($latitude, $Longitude, $geohashLength = 5) { | |
$hash = ""; | ||
for ($i=0; $i< strlen($binaryString); $i+=5) { | ||
$n = bindec(substr($binaryString,$i,5)); | ||
$hash = $hash.$this->base32Mapping[$n]; | ||
$hash = $hash . $this->base32Mapping[$n]; | ||
} | ||
return $hash; | ||
} | ||
|
@@ -85,14 +63,23 @@ public function encode($latitude, $Longitude, $geohashLength = 5) { | |
* @param double Percentage error | ||
* @return mixed Array of Latitude and Longitude | ||
*/ | ||
public function decode($hash, $error = false) { | ||
$hashlength = strlen($hash); | ||
public function decode($hash, $error = false) | ||
{ | ||
$hashLength = strlen($hash); | ||
$latlonbits = base_convert($hash, 32, 2); | ||
$binaryLength = strlen($latlonbits); | ||
$latbits = ""; | ||
$lonbits = ""; | ||
|
||
$latlonbits = $this->characterMapping($hash); | ||
$geohashArray = str_split($hash, 1); | ||
$latlonbits = ""; | ||
foreach($geohashArray as $g) { | ||
if (($position = stripos($this->base32Mapping, $g)) !== FALSE) { | ||
$latlonbits .= str_pad(decbin($position), 5, "0", STR_PAD_LEFT); | ||
} else { | ||
$latlonbits .= "00000"; | ||
} | ||
} | ||
|
||
// Even bits take latitude Code | ||
// Odd bits take longitude Code | ||
|
@@ -103,6 +90,10 @@ public function decode($hash, $error = false) { | |
// Get the Coordinates | ||
$latitude = $this->getCoordinate(-90, 90, $latbits); | ||
$longitude = $this->getCoordinate(-180, 180, $lonbits); | ||
|
||
// Rounding the latitude and longitude values | ||
$latitude = round($latitude, $hashLength - 2); | ||
$longitude = round($longitude, $hashLength - 2); | ||
return array($latitude, $longitude); | ||
} | ||
|
||
|
@@ -113,9 +104,10 @@ public function decode($hash, $error = false) { | |
* @param string $binaryString | ||
* @return float $coordinate | ||
*/ | ||
public function getCoordinate($min, $max, $binaryString) { | ||
public function getCoordinate($min, $max, $binaryString) | ||
{ | ||
$error = 0; | ||
for ($i=0; $i < strlen($binaryString); $i++) { | ||
for ($i = 0; $i < strlen($binaryString); $i++) { | ||
$mid = ($min + $max)/2 ; | ||
if ($binaryString[$i] == 1){ | ||
$min = $mid ; | ||
|
@@ -136,7 +128,8 @@ public function getCoordinate($min, $max, $binaryString) { | |
* @param int bitslength | ||
* @return string binary string for the given coordinate | ||
*/ | ||
public function getBits($coordinate, $min, $max, $bitsLength) { | ||
public function getBits($coordinate, $min, $max, $bitsLength) | ||
{ | ||
$binaryString = ""; | ||
$i = 0; | ||
while ($bitsLength > $i) { | ||
|
@@ -152,4 +145,4 @@ public function getBits($coordinate, $min, $max, $bitsLength) { | |
} | ||
return $binaryString; | ||
} | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,59 @@ | ||
<?php | ||
|
||
use ImSaikiran\Geohash\Geohash; | ||
use Sk\Geohash\Geohash; | ||
|
||
class GeohashTest extends PHPUnit_Framework_TestCase { | ||
|
||
public function testEncode() | ||
class GeohashTest extends PHPUnit_Framework_TestCase | ||
{ | ||
/** | ||
* @dataProvider encodeProvider | ||
*/ | ||
public function testEncode($lat, $lon, $hash, $l) | ||
{ | ||
$geohash = new Geohash(); | ||
$actual = $geohash->encode($lat, $lon, $l); | ||
$this->assertSame($hash, $actual); | ||
} | ||
|
||
public function encodeProvider() | ||
{ | ||
return array( | ||
array(17.57812500, 78.04687500, "tep", 3), | ||
array(17.31445313, 78.57421875, "tepf", 4), | ||
array(17.38037109, 78.42041016, "tepfb", 5), | ||
array(17.41058350, 78.46984863, "tepg19", 6), | ||
array(17.41813660, 78.47328186, "tepg1dy", 7), | ||
array(17.41822243, 78.47311020, "tepg1dyk", 8), | ||
array(17.38502741, 78.48673582, "tepffhb71", 9), | ||
array(17.38500863, 78.48670900, "tepffhb70b", 10), | ||
array(17.38503210, 78.48672040, "tepffhb71hu", 11), | ||
array(17.38503202, 78.48672057, "tepffhb71hue", 12) | ||
); | ||
} | ||
|
||
/** | ||
* @dataProvider decodeProvider | ||
*/ | ||
public function testDecode($lat, $lon, $hash) | ||
{ | ||
$geohash = new Geohash; | ||
$this->assertTrue(true); | ||
$geohash = new Geohash(); | ||
$actual = $geohash->decode($hash); | ||
$this->assertEquals($actual[0], $lat); | ||
$this->assertEquals($actual[1], $lon); | ||
} | ||
|
||
public function testDecode() | ||
public function decodeProvider() | ||
{ | ||
$geohash = new Geohash; | ||
$this->assertTrue(true); | ||
return array( | ||
array(17.60000000, 78.00000000, "tep"), | ||
array(17.31000000, 78.57000000, "tepf"), | ||
array(17.38000000, 78.42000000, "tepfb"), | ||
array(17.41060000, 78.46980000, "tepg19"), | ||
array(17.41608000, 78.46985000, "tepg1dy"), | ||
array(17.41813700, 78.47328200, "tepg1dyk"), | ||
array(17.38502740, 78.48673580, "tepffhb71"), | ||
array(17.38500863, 78.48670900, "tepffhb70b"), | ||
array(17.385032102, 78.486720398, "tepffhb71hu"), | ||
array(17.3850320186, 78.48672056569, "tepffhb71hue") | ||
); | ||
} | ||
} |