From e7bc726cdbdd315d497929ed51b0a902f7a35c04 Mon Sep 17 00:00:00 2001 From: Saikiran Ch Date: Sun, 4 Feb 2018 21:21:54 +0530 Subject: [PATCH] Update changes --- composer.json | 2 +- src/Geohash.php | 71 +++++++++++++++++++------------------------ tests/GeohashTest.php | 59 +++++++++++++++++++++++++++++------ 3 files changed, 83 insertions(+), 49 deletions(-) diff --git a/composer.json b/composer.json index 2d8d57c..0ede255 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ }, "autoload": { "psr-4": { - "ImSaikiran\\Geohash\\": "src" + "Sk\\Geohash\\": "src" } } } diff --git a/src/Geohash.php b/src/Geohash.php index 7ee32af..b142b0d 100644 --- a/src/Geohash.php +++ b/src/Geohash.php @@ -1,9 +1,9 @@ + * @author Saikiran Ch * @class Geohash * @description Algorithm to encode geographic coordinates to a string of letters and digits */ @@ -14,29 +14,6 @@ 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 @@ -44,23 +21,24 @@ public function characterMapping($geohash) { * @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; } -} +} \ No newline at end of file diff --git a/tests/GeohashTest.php b/tests/GeohashTest.php index da3302f..5313f34 100644 --- a/tests/GeohashTest.php +++ b/tests/GeohashTest.php @@ -1,18 +1,59 @@ 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") + ); } } \ No newline at end of file