= $prec) { if ($isEven) { $next = ($minlng + $maxlng) / 2; if ($lng > $next) { $chr |= self::$bits[$b]; $minlng = $next; } else { $maxlng = $next; } } else { $next = ($minlat + $maxlat) / 2; if ($lat > $next) { $chr |= self::$bits[$b]; $minlat = $next; } else { $maxlat = $next; } } $isEven = !$isEven; if ($b < 4) { $b++; } else { $hash[] = self::$table[$chr]; $error = max($maxlng - $minlng, $maxlat - $minlat); $b = 0; $chr = 0b00000; } } return join('', $hash); } public static function expand($hash, $prec = 0.00001) { list($minlng, $maxlng, $minlat, $maxlat) = self::decode($hash); $dlng = ($maxlng - $minlng) / 2; $dlat = ($maxlat - $minlat) / 2; return array( self::encode($minlng - $dlng, $maxlat + $dlat, $prec), self::encode($minlng + $dlng, $maxlat + $dlat, $prec), self::encode($maxlng + $dlng, $maxlat + $dlat, $prec), self::encode($minlng - $dlng, $maxlat - $dlat, $prec), self::encode($maxlng + $dlng, $maxlat - $dlat, $prec), self::encode($minlng - $dlng, $minlat - $dlat, $prec), self::encode($minlng + $dlng, $minlat - $dlat, $prec), self::encode($maxlng + $dlng, $minlat - $dlat, $prec), ); } public static function getRect($hash) { list($minlng, $maxlng, $minlat, $maxlat) = self::decode($hash); return array( array($minlng, $minlat), array($minlng, $maxlat), array($maxlng, $maxlat), array($maxlng, $minlat), ); } /** * decode a geohash string to a geographical area * * @var $hash string geohash * @return array array($minlng, $maxlng, $minlat, $maxlat); */ public static function decode($hash) { $minlng = -180; $maxlng = 180; $minlat = -90; $maxlat = 90; for ($i=0,$c=strlen($hash); $i<$c; $i++) { $v = strpos(self::$table, $hash[$i]); if (1&$i) { if (16&$v) { $minlat = ($minlat + $maxlat) / 2; } else { $maxlat = ($minlat + $maxlat) / 2; } if (8&$v) { $minlng = ($minlng + $maxlng) / 2; } else { $maxlng = ($minlng + $maxlng) / 2; } if (4&$v) { $minlat = ($minlat + $maxlat) / 2; } else { $maxlat = ($minlat + $maxlat) / 2; } if (2&$v) { $minlng = ($minlng + $maxlng) / 2; } else { $maxlng = ($minlng + $maxlng) / 2; } if (1&$v) { $minlat = ($minlat + $maxlat) / 2; } else { $maxlat = ($minlat + $maxlat) / 2; } } else { if (16&$v) { $minlng = ($minlng + $maxlng) / 2; } else { $maxlng = ($minlng + $maxlng) / 2; } if (8&$v) { $minlat = ($minlat + $maxlat) / 2; } else { $maxlat = ($minlat + $maxlat) / 2; } if (4&$v) { $minlng = ($minlng + $maxlng) / 2; } else { $maxlng = ($minlng + $maxlng) / 2; } if (2&$v) { $minlat = ($minlat + $maxlat) / 2; } else { $maxlat = ($minlat + $maxlat) / 2; } if (1&$v) { $minlng = ($minlng + $maxlng) / 2; } else { $maxlng = ($minlng + $maxlng) / 2; } } } return array($minlng, $maxlng, $minlat, $maxlat); } }