Skip to content

Commit

Permalink
Update changes
Browse files Browse the repository at this point in the history
  • Loading branch information
skthon committed Feb 4, 2018
1 parent 7b2d725 commit e7bc726
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 49 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
},
"autoload": {
"psr-4": {
"ImSaikiran\\Geohash\\": "src"
"Sk\\Geohash\\": "src"
}
}
}
71 changes: 32 additions & 39 deletions src/Geohash.php
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
*/
Expand All @@ -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];
Expand All @@ -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;
}
Expand All @@ -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
Expand All @@ -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);
}

Expand All @@ -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 ;
Expand All @@ -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) {
Expand All @@ -152,4 +145,4 @@ public function getBits($coordinate, $min, $max, $bitsLength) {
}
return $binaryString;
}
}
}
59 changes: 50 additions & 9 deletions tests/GeohashTest.php
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")
);
}
}

0 comments on commit e7bc726

Please sign in to comment.