PHP WSG84转BD09 地理坐标系互转

1 篇文章 0 订阅
1 篇文章 0 订阅

使用

代码在最下面, 包含了wgs84,百度坐标系,火星坐标系等相互转换的PHP版本,参考(https://blog.csdn.net/luan666/article/details/87639818

$lng = "112°47′23.16″";
$lat = "36°49′47.31″";

// 度分秒转十进制度
$lng = CoordinateTransform::degreeMinuteSecondToDecimal($lng);
$lat = CoordinateTransform::degreeMinuteSecondToDecimal($lat);
dump([$lng,$lat]);

// 本地函数经纬度转换
dump(CoordinateTransform::wgs84ToBd09($lng, $lat));

$baiduService = $this->get('licence.baidu_map_service');
// 百度API经纬度转换
dump($baiduService->geoconv([[$lng,$lat]])[0]);

输出结果

// 度分秒转十进制度
array:2 [▼
  0 => 112.78976666667
  1 => 36.829808333333
]
// 本地函数调用结果
array:2 [▼
  0 => 112.80251813585
  1 => 36.836394940245
]
// 百度API调用结果
array:2 [▼
  "lng" => 112.80252353368
  "lat" => 36.836399221616
]

显示在地图上的差距(百度地图放到最大几乎重合)

PHP版源码

// 坐标转换库
class CoordinateTransform
{
    const x_PI = 3.14159265358979324 * 3000.0 / 180.0;
    const PI = 3.1415926535897932384626;
    const a = 6378245.0;
    const ee = 0.00669342162296594323;

    /**
     * 度分秒转十进制度
     * @param $deg
     * @return bool|float|int|mixed|string
     */
    public static function degreeMinuteSecondToDecimal($deg)
    {
        $_oldCon = $deg;
        $deg = rtrim(str_replace(['‘’', '’‘', '’', '°', '′', '″', ''', '“', '”'], '.', $deg), '.');
        $pointCount = substr_count($deg, '.');
        if ($pointCount == 1) { // 形如: 111.23412 需要生成第二个点
            if ($_oldCon == $deg) return $deg;
            [$str1, $str2] = explode('.', $deg);
            if (strlen($str2) > 2) {
                $str2 = substr($str2, 0, 2).'.'.substr($str2, 2);
                $deg = $str1.'.'.$str2;
            }
        } else if ($pointCount == 2) {
            $deg .= '.0';
        }

        try {
            // 形如: 111.23.412 或 111.23.41.2
            [$deg1, $deg2, $deg3] = explode('.', $deg, 3);

            $deg = $deg1 + $deg2/60 + $deg3/3600;
            return $deg;

        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
     * 即 百度 转 谷歌、高德
     * @param $bdLon float|string
     * @param $bdLat float|string
     * @return array
     */
    public static function bd09ToGcj02($bdLon, $bdLat)
    {
        $x = $bdLon - 0.0065;
        $y = $bdLat - 0.006;
        $z = sqrt($x * $x + $y * $y) - 0.00002 * sin($y * self::PI);
        $theta = atan2($y, $x) - 0.000003 * cos($x * self::PI);
        $gg_lng = $z * cos($theta);
        $gg_lat = $z * sin($theta);
        // Point point=new Point($gg_lng, $gg_lat);
        // return point;
        return [$gg_lng, $gg_lat];
    }

    /**
     * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
     * 即谷歌、高德 转 百度
     * @param $lng float|string
     * @param $lat float|string
     * @return array
     */
    public static function gcj02ToBd09($lng, $lat)
    {
        $z = sqrt($lng * $lng + $lat * $lat) + 0.00002 * sin($lat * self::PI);
        $theta = atan2($lat, $lng) + 0.000003 * cos($lng * self::PI);
        $bd_lng = $z * cos($theta) + 0.0065;
        $bdLat = $z * sin($theta) + 0.006;
        //Point point=new Point(bd_$lng, $bdLat);
        // return point;
        return [$bd_lng, $bdLat];
    }

    /**
     * WGS84转GCj02
     * @param $lng float|string
     * @param $lat float|string
     * @return array
     */
    public static function wgs84ToGcj02($lng, $lat)
    {
        $dlat = self::transformlat($lng - 105.0, $lat - 35.0);
        $dlng = self::transformlng($lng - 105.0, $lat - 35.0);
        $radlat = $lat / 180.0 * self::PI;
        $magic = sin($radlat);
        $magic = 1 - self::ee * $magic * $magic;
        $sqrtmagic = sqrt($magic);
        $dlat = ($dlat * 180.0) / ((self::a * (1 - self::ee)) / ($magic * $sqrtmagic) * self::PI);
        $dlng = ($dlng * 180.0) / (self::a / $sqrtmagic * cos($radlat) * self::PI);
        $mglat = $lat + $dlat;
        $mglng = $lng + $dlng;
        //Point point=new Point($mglng, $mglat);
        // return point;
        return [$mglng, $mglat];
    }

    /**
     * GCJ02 转换为 WGS84
     * @param $lng float|string
     * @param $lat float|string
     * @return array
     */
    public function gcj02ToWgs84($lng, $lat)
    {
        $dlat = self::transformlat($lng - 105.0, $lat - 35.0);
        $dlng = self::transformlng($lng - 105.0, $lat - 35.0);
        $radlat = $lat / 180.0 * self::PI;
        $magic = sin($radlat);
        $magic = 1 - self::ee * $magic * $magic;
        $sqrtmagic = sqrt($magic);
        $dlat = ($dlat * 180.0) / ((self::a * (1 - self::ee)) / ($magic * $sqrtmagic) * self::PI);
        $dlng = ($dlng * 180.0) / (self::a / $sqrtmagic * cos($radlat) * self::PI);
        $mglat = $lat + $dlat;
        $mglng = $lng + $dlng;
        // Point point=new Point($mglng, $mglat);
        // return point;
        return [$mglat, $mglng];
    }

    /**
     * WGS84 转换为 BD-09
     * @param $lng float|string
     * @param $lat float|string
     * @return array
     */
    public static function wgs84ToBd09($lng, $lat)
    {
        //第一次转换
        $dlat = self::transformlat($lng - 105.0, $lat - 35.0);
        $dlng = self::transformlng($lng - 105.0, $lat - 35.0);
        $radlat = $lat / 180.0 * self::PI;
        $magic = sin($radlat);
        $magic = 1 - self::ee * $magic * $magic;
        $sqrtmagic = sqrt($magic);
        $dlat = ($dlat * 180.0) / ((self::a * (1 - self::ee)) / ($magic * $sqrtmagic) * self::PI);
        $dlng = ($dlng * 180.0) / (self::a / $sqrtmagic * cos($radlat) * self::PI);
        $mglat = $lat + $dlat;
        $mglng = $lng + $dlng;

        //第二次转换
        $z = sqrt($mglng * $mglng + $mglat * $mglat) + 0.00002 * sin($mglat * self::x_PI);
        $theta = atan2($mglat, $mglng) + 0.000003 * cos($mglng * self::x_PI);
        $bd_lng = $z * cos($theta) + 0.0065;
        $bdLat = $z * sin($theta) + 0.006;
        return [$bd_lng, $bdLat];
    }

    private static function transformlat($lng, $lat)
    {
        $ret = -100.0 + 2.0 * $lng + 3.0 * $lat + 0.2 * $lat * $lat + 0.1 * $lng * $lat + 0.2 * sqrt(abs($lng));
        $ret += (20.0 * sin(6.0 * $lng * self::PI) + 20.0 * sin(2.0 * $lng * self::PI)) * 2.0 / 3.0;
        $ret += (20.0 * sin($lat * self::PI) + 40.0 * sin($lat / 3.0 * self::PI)) * 2.0 / 3.0;
        $ret += (160.0 * sin($lat / 12.0 * self::PI) + 320 * sin($lat * self::PI / 30.0)) * 2.0 / 3.0;
        return $ret;
    }

    private static function transformlng($lng, $lat)
    {
        $ret = 300.0 + $lng + 2.0 * $lat + 0.1 * $lng * $lng + 0.1 * $lng * $lat + 0.1 * sqrt(abs($lng));
        $ret += (20.0 * sin(6.0 * $lng * self::PI) + 20.0 * sin(2.0 * $lng * self::PI)) * 2.0 / 3.0;
        $ret += (20.0 * sin($lng * self::PI) + 40.0 * sin($lng / 3.0 * self::PI)) * 2.0 / 3.0;
        $ret += (150.0 * sin($lng / 12.0 * self::PI) + 300.0 * sin($lng / 30.0 * self::PI)) * 2.0 / 3.0;
        return $ret;
    }

}

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值