世界那么大,我带你去看看

php版本的geohash类库,包括查询周边8个格子的hash编码

首先看用法,代码来自github,修改了,习惯lat在前,lng在后。

$geohash = new GeoHash();

$geohash->encode(‘39.9232111’,‘116.3906111’);

$geohash->decode(‘wx4g0ec19cc’);

//下面是展示获取周围8个的

$geohash->expand(‘wx4g0ec19cc’);

<?php

class GeoHash

{

    private static $table = “0123456789bcdefghjkmnpqrstuvwxyz”;

    private static $bits = array(

        0b10000, 0b01000, 0b00100, 0b00010, 0b00001

    );

    public static function encode($lat, $lng, $prec = 0.00001)

    {

        $minlng = -180;

        $maxlng = 180;

        $minlat = -90;

        $maxlat = 90;

        $hash = array();

        $error = 180;

        $isEven = true;

        $chr = 0b00000;

        $b = 0;

        while ($error >= $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($minlat, $maxlat, $minlng, $maxlng);

    }

}

未经允许不得转载:互联网骚操作 » php版本的geohash类库,包括查询周边8个格子的hash编码

分享到:更多 ()

评论 抢沙发

评论前必须登录!

世界那么大,跟着我去看看

联系我们阿里云运行