vr-shopxo-plugin/shopxo/extend/base/GeoTransUtil.php

242 lines
8.4 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
// +----------------------------------------------------------------------
// | ShopXO 国内领先企业级B2C免费开源电商系统
// +----------------------------------------------------------------------
// | Copyright (c) 2011~2099 http://shopxo.net All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://opensource.org/licenses/mit-license.php )
// +----------------------------------------------------------------------
// | Author: Devil
// +----------------------------------------------------------------------
namespace base;
/**
* 坐标转换工具
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2018-06-04T21:51:08+0800
*/
class GeoTransUtil
{
private static $x_pi = 3.14159265358979324*3000.0/180.0;
private static $pi = 3.14159265358979324;
private static $a = 6378245.0;
private static $ee = 0.00669342162296594323;
private static $earth_radius = 6378.137;
/**
* 计算两组经纬度坐标 之间的距离
* params lat1 纬度1 lng1 经度1 lat2 纬度2 lng2 经度2 len_type 1:m or 2:km);
* return m or km
*/
/**
* [GetDistance 获取两个坐标之间的距离]
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @datetime 2017-10-23T09:33:58+0800
* @param [float] $lng1 [经度1]
* @param [float] $lat1 [维度1]
* @param [float] $lng2 [经度2]
* @param [float] $lat2 [维度2]
* @param [int] $len_type [返回结果类型1千米, 2公里默认千米]
* @param [int] $decimal [保留小数位数默认2]
* @return [int|float] [返回千米或公里值]
*/
public static function GetDistance($lng1, $lat1, $lng2, $lat2, $len_type = 1, $decimal = 2)
{
$radLat1 = (float) $lat1 * self::$pi / 180.0;
$radLat2 = (float) $lat2 * self::$pi / 180.0;
$a = $radLat1 - $radLat2;
$b = ((float) $lng1 * self::$pi / 180.0) - ((float) $lng2 * self::$pi / 180.0);
$s = 2 * asin(sqrt(pow(sin($a/2),2) + cos($radLat1) * cos($radLat2) * pow(sin($b/2),2)));
$s = $s * self::$earth_radius;
if($len_type == 1)
{
$s = round($s * 1000);
}
return round($s, $decimal);
}
/**
* [GcjToBd 火星坐标(GCJ02坐标高德谷歌腾讯坐标)到百度坐标BD-09]
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @datetime 2017-10-18T13:58:14+0800
* @param [float] $lng [经度]
* @param [float] $lat [纬度]
* @return [array] [转换后的进维度]
*/
public static function GcjToBd($lng, $lat)
{
$result = ['lng'=>0, 'lat'=>0];
if(empty($lng) || empty($lat))
{
return $result;
}
$x = $lng;
$y = $lat;
$z = sqrt($x * $x + $y * $y) + 0.00002 * sin($y * self::$x_pi);
$theta = atan2($y, $x) + 0.000003 * cos($x * self::$x_pi);
$result['lng'] = $z * cos($theta) + 0.0065;
$result['lat'] = $z * sin($theta) + 0.006;
return $result;
}
/**
* [BdToGcj 百度坐标BD-09到火星坐标GCJ02(高德,谷歌,腾讯坐标)]
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @datetime 2017-10-18T13:58:14+0800
* @param [float] $lng [经度]
* @param [float] $lat [纬度]
* @return [array] [转换后的进维度]
*/
public static function BdToGcj($lng, $lat)
{
$result = ['lng'=>0, 'lat'=>0];
if(empty($lng) || empty($lat))
{
return $result;
}
$x = $lng - 0.0065;
$y = $lat - 0.006;
$z = sqrt($x * $x + $y * $y) - 0.00002 * sin($y * self::$x_pi);
$theta = atan2($y, $x) - 0.000003 * cos($x * self::$x_pi);
$result['lng'] = $z * cos($theta);
$result['lat'] = $z * sin($theta);
return $result;
}
/**
* [WgsToGcj WGS-84(GPS坐标谷歌地球坐标) 到 GCJ-02(火星坐标) 的转换]
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @datetime 2017-10-18T14:03:26+0800
* @param [float] $lng [经度]
* @param [float] $lat [纬度]
* @return [array] [转换后的进维度]
*/
public static function WgsToGcj($lng, $lat)
{
$result = ['lng'=>0, 'lat'=>0];
if(empty($lng) || empty($lat))
{
return $result;
}
//double wgLat, double wgLon, out double mgLat, out double mgLon
$wgLat = $lat;
$wgLon = $lng;
if(self::outOfChina($wgLat, $wgLon))
{
return ['lng'=>$wgLon, 'lat'=>$wgLat];
}
$dLat = GeoTransUtil::transformLat($wgLon - 105.0, $wgLat - 35.0);
$dLon = GeoTransUtil::transformLon($wgLon - 105.0, $wgLat - 35.0);
$radLat = $wgLat / 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);
$dLon = ($dLon * 180.0) / (self::$a / $sqrtMagic * cos($radLat) * self::$pi);
$result['lng'] = $wgLon + $dLon;
$result['lat'] = $wgLat + $dLat;
return $result;
}
/**
* [GcjToWgs GCJ-02 到 WGS-84 的转换]
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @datetime 2017-10-18T14:03:26+0800
* @param [float] $lng [经度]
* @param [float] $lat [纬度]
* @return [array] [转换后的进维度]
*/
public static function GcjToWgs($lng, $lat)
{
$result = ['lng'=>0, 'lat'=>0];
if(empty($lng) || empty($lat))
{
return $result;
}
$to = self::WgsToGcj($lng, $lat);
$g_lat = $to->x;
$g_lon = $to->y;
$d_lat = $g_lat - $lat;
$d_lon = $g_lon - $lon;
$result['lng'] = $lon - $d_lon;
$result['lat'] = $lat - $d_lat;
return $result;
}
/**
* 判断坐标是否在中国境外(境外不做偏移)
* @param float $lat 纬度
* @param float $lon 经度
* @return bool
*/
private static function outOfChina($lat,$lon)
{
if ($lon < 72.004 || $lon > 137.8347)
return true;
if ($lat < 0.8293 || $lat > 55.8271)
return true;
return false;
}
/**
* 纬度偏移计算
* @param float $x 经度偏移量相对于105°E
* @param float $y 纬度偏移量相对于35°N
* @return float 纬度偏移值
*/
private static function transformLat($x,$y)
{
$ret = -100.0 + 2.0 * $x + 3.0 * $y + 0.2 * $y * $y + 0.1 * $x * $y + 0.2 * sqrt(abs($x));
$ret += (20.0 * sin(6.0 * $x * self::$pi) + 20.0 * sin(2.0 * $x * self::$pi)) * 2.0 / 3.0;
$ret += (20.0 * sin($y * self::$pi) + 40.0 * sin($y / 3.0 * self::$pi)) * 2.0 / 3.0;
$ret += (160.0 * sin($y / 12.0 * self::$pi) + 320 * sin($y * self::$pi / 30.0)) * 2.0 / 3.0;
return $ret;
}
/**
* 经度偏移计算
* @param float $x 经度偏移量相对于105°E
* @param float $y 纬度偏移量相对于35°N
* @return float 经度偏移值
*/
private static function transformLon($x, $y)
{
$ret = 300.0 + $x + 2.0 * $y + 0.1 * $x * $x + 0.1 * $x * $y + 0.1 * sqrt(abs($x));
$ret += (20.0 * sin(6.0 * $x * self::$pi) + 20.0 * sin(2.0 * $x * self::$pi)) * 2.0 / 3.0;
$ret += (20.0 * sin($x * self::$pi) + 40.0 * sin($x / 3.0 * self::$pi)) * 2.0 / 3.0;
$ret += (150.0 * sin($x / 12.0 * self::$pi) + 300.0 * sin($x / 30.0 * self::$pi)) * 2.0 / 3.0;
return $ret;
}
}
/*// 测试demo
require './GeoTransUtil.class.php';
// 高德转百度
//$ret = GeoTransUtil::GcjToBd(106.504943,29.53319);
// 百度转高德
$ret = GeoTransUtil::BdToGcj(106.518492,29.540528);
echo '</br>';
echo $ret['lng'].','.$ret['lat'];*/
?>