技术饭
PHP WSG84转BD09 地理坐标系互转
最近使用了微信公众号的地理定位服务,获取得到的纬度与经度用来转换成功详细地址信息,腾讯使用的地图地位坐标系是WSG84,如果获取地理位置信息使用的是腾讯地图服务的话就不需要转换,如果使用的是百度或者其他精度的坐标系,则需要进行转换。
使用代码:
PHP的WSG84转BD09 地理坐标系互转处理类:
<?php
/**
* Author: [ CopyLian ]
* Date: [ 2017.02.23 ]
* Email: [ copylian@aikehou.com ]
* Site: [ http://www.copylian.com ]
* Description [ WSG84转BD09 地理坐标系互转处理类 ]
*/
namespace wechat;
// 坐标转换库
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;
list($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
list($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;
}
}
参考资料:https://blog.csdn.net/yynan555/article/details/106360633
文明上网理性发言!