Skip to content

Commit

Permalink
Merge pull request phayes#92 from mprins/adjacent-geohash
Browse files Browse the repository at this point in the history
Add adjacent geohash function
  • Loading branch information
phayes committed Nov 30, 2014
2 parents 478a1a0 + df36b7f commit d5b508a
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 0 deletions.
83 changes: 83 additions & 0 deletions lib/adapters/GeoHash.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,64 @@
*
*/
class GeoHash extends GeoAdapter{

/**
* base32 encoding character map.
*/
private $table = "0123456789bcdefghjkmnpqrstuvwxyz";

/**
* array of neighbouring hash character maps.
*/
private $neighbours = array (
// north
'top' => array (
'even' => 'p0r21436x8zb9dcf5h7kjnmqesgutwvy',
'odd' => 'bc01fg45238967deuvhjyznpkmstqrwx'
),
// east
'right' => array (
'even' => 'bc01fg45238967deuvhjyznpkmstqrwx',
'odd' => 'p0r21436x8zb9dcf5h7kjnmqesgutwvy'
),
// west
'left' => array (
'even' => '238967debc01fg45kmstqrwxuvhjyznp',
'odd' => '14365h7k9dcfesgujnmqp0r2twvyx8zb'
),
// south
'bottom' => array (
'even' => '14365h7k9dcfesgujnmqp0r2twvyx8zb',
'odd' => '238967debc01fg45kmstqrwxuvhjyznp'
)
);

/**
* array of bordering hash character maps.
*/
private $borders = array (
// north
'top' => array (
'even' => 'prxz',
'odd' => 'bcfguvyz'
),
// east
'right' => array (
'even' => 'bcfguvyz',
'odd' => 'prxz'
),
// west
'left' => array (
'even' => '0145hjnp',
'odd' => '028b'
),
// south
'bottom' => array (
'even' => '028b',
'odd' => '0145hjnp'
)
);

/**
* Convert the geohash to a Point. The point is 2-dimensional.
* @return Point the converted geohash
Expand Down Expand Up @@ -163,4 +219,31 @@ private function decode($hash){
$ll['medlon'] = round(($minlon+$maxlon)/2, max(1, -round(log10($lonE)))-1);
return $ll;
}

/**
* Calculates the adjacent geohash of the geohash in the specified direction.
* This algorithm is available in various ports that seem to point back to
* geohash-js by David Troy under MIT notice.
*
*
* @see https://github.com/davetroy/geohash-js
* @see https://github.com/lyokato/objc-geohash
* @see https://github.com/lyokato/libgeohash
* @see https://github.com/masuidrive/pr_geohash
* @see https://github.com/sunng87/node-geohash
* @see https://github.com/davidmoten/geo
*
* @param string $hash the geohash (lowercase)
* @param string $direction the direction of the neighbor (top, bottom, left or right)
* @return string the geohash of the adjacent cell
*/
public function adjacent($hash, $direction){
$last = substr($hash, -1);
$type = (strlen($hash) % 2)? 'odd': 'even';
$base = substr($hash, 0, strlen($hash) - 1);
if(strpos(($this->borders[$direction][$type]), $last) !== false){
$base = $this->adjacent($base, $direction);
}
return $base.$this->table[strpos($this->neighbours[$direction][$type], $last)];
}
}
20 changes: 20 additions & 0 deletions tests/tests/geohashTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php
require_once ('../geoPHP.inc');

class GeoHashTest extends PHPUnit_Framework_TestCase {

function setUp() {
}

/**
* test cases for adjacent geohashes.
*/
function testAdjacent() {
$geohash = new Geohash();
$this->assertEquals ( 'xne', $geohash->adjacent ( 'xn7', 'top' ), 'Did not find correct top adjacent geohash for xn7' );
$this->assertEquals ( 'xnk', $geohash->adjacent ( 'xn7', 'right' ), 'Did not find correct right adjacent geohash for xn7' );
$this->assertEquals ( 'xn5', $geohash->adjacent ( 'xn7', 'bottom' ), 'Did not find correct bottom adjacent geohash for xn7' );
$this->assertEquals ( 'xn6', $geohash->adjacent ( 'xn7', 'left' ), 'Did not find correct left adjacent geohash for xn7' );
$this->assertEquals ( 'xnd', $geohash->adjacent ( $geohash->adjacent ( 'xn7', 'left' ), 'top' ), 'Did not find correct top-left adjacent geohash for xn7' );
}
}

0 comments on commit d5b508a

Please sign in to comment.