地球坐标转高德的火星坐标
<?php /** * latlng转换器:从wgs84转换到gcj02 * * 此处转换仅针对互联网民用地图,并假定: * 无测定时间(wg_week,wg_time永远为0),地图原点(0,0)(wg_flag永远为1) * * conf_random为true时,返回结果随机偏移。若要发布到外网服务,必须随机偏移! * * 验证方法可以从高德地图中验证。验证url: * http://mo.amap.com/?q=纬度,经度&name=park&dev=0#thirdpoi * * 也有在线转换方法,文档见:document/latlng_conv_online_wgs84_2_gcj02.txt * * @link http://blog.csdn.net/coolypf/article/details/8686588 * @link https://on4wp7.codeplex.com/SourceControl/changeset/view/21483#353936 * @author wgtochina_lb * @author coolypf * @author hl * @version 0.1 * */ class LDB8{ /** * @link http://bbs.esrichina-bj.cn/esri/viewthread.php?tid=65098 * @var float */ const DIMS_FULL_SCENE = 3686400.0; /** * Krasovsky 1940 (北京54)椭球长半轴 * @var float */ const ELLIPSOID_PARAM_A = 6378245.0; /** * Krasovsky 1940 (北京54)椭球长半轴第一偏心率平方 * 计算方式: * 长半轴: * a = 6378245.0 * 扁率: * 1/f = 298.3(变量相关计算为:(a-b)/a) * 短半轴: * b = 6356863.0188 (变量相关计算方法为:b = a * (1 - f)) * 第一偏心率平方: * e2 = (a^2 - b^2) / a^2; */ const ELLIPSOID_PARAM_E2 = 0.00669342162296594323; /** * 输出的中间量需要random混淆? * 如果要对外暴露使用,必须为true * @var bool */ static protected $conf_random = true; /** * random值。self::$conf_random有效时使用 * 初始值:0或者0.3 * @var float */ static protected $casm_rr = 0; /** * pi除以某个系数的结果 * @var array */ static protected $pi_div_result = array(); /** * pi乘以某个系数的结果 * @var array */ static protected $pi_mul_result = array(); /** * 转换接口 * @param float|array $lat wgs84坐标系的纬度、或者array('lat'=>lat, 'lng'=>lng) * @param float $lng wgs84坐标系的经度 * @param int $wg_heit wgs84坐标系的高度。缺省为0 * @param int $random 输出的中间量需要random混淆?默认为0,表示跟随配置;-1表示强制禁用random混淆;其余数值表示强制启用random混淆 * @return array 转换后的gcj02坐标(高德坐标系)。格式array('lat'=>lat, 'lng'=>lng) */ static public function conv($lat, $lng = 0, $wg_heit = 0, $random = 0){ if(is_array($lat)){ $lng = isset($lat['lng']) ? $lat['lng'] : 0; $lat = isset($lat['lat']) ? $lat['lat'] : 0; } if(!self::is_conv_range($lat, $lng, $wg_heit)){ return array( 'lat' => $lat, 'lng' => $lng, ); } $x_l = $lng; $y_l = $lat; //此处直入 $x_add = self::Transform_yj5($x_l - 105, $y_l - 35) ; $y_add = self::Transform_yjy5($x_l - 105, $y_l - 35) ; $h_add = $wg_heit; //由于猜测$wg_time = 0(个人猜测,应该是全部等于0,否则数据迁移很难搞...),后面的计算可省略 $x_add = $x_add + $h_add * 0.001 /* + self::yj_sin2($wg_time*self::pi_div(180)) */; $y_add = $y_add + $h_add * 0.001 /* + self::yj_sin2($wg_time*self::pi_div(180)) */; if(0 == $random){ if(false != self::$conf_random){ $x_add += self::random_yj(); $y_add += self::random_yj(); } }elseif($random != -1){ $x_add += self::random_yj(); $y_add += self::random_yj(); } return array( 'lat' => ($y_l + self::Transform_jyj5($y_l, $y_add)), 'lng' => ($x_l + self::Transform_jy5($y_l, $x_add)), ); } /** * 是在需要转换的范畴么? * @param float $lat * @param float $lng * @return bool 不需要转换时,返回false */ static public function is_conv_range($lat, $lng, $wg_heit = 0){ if($lng < 72.004 || $lng > 137.8347){ return false; } if($lat < 0.8293 || $lat > 55.8271){ return false; } if($wg_heit > 5000){ return false; } return true; } static public function Transform_yj5($x, $y){ $tt = 300 + $x + 2 * $y + 0.1 * pow($x, 2) + 0.1 * $x * $y + 0.1 * sqrt(abs($x)); $tt += (20 * self::yj_sin2(self::pi_mul(6) * $x) + 20 * self::yj_sin2(self::pi_mul(2) * $x))*2.0/3.0; $tt += (20 * self::yj_sin2(M_PI * $x) + 40 * self::yj_sin2(self::pi_div(3) * $x))*2.0/3.0; $tt += (150 * self::yj_sin2(self::pi_div(12) * $x) + 300 * self::yj_sin2(self::pi_div(30) * $x))*2.0/3.0; return $tt; } static public function Transform_yjy5($x , $y){ $tt = -100 + 2 * $x + 3 * $y + 0.2 * pow($y, 2) + 0.1 * $x * $y + 0.2 * sqrt(abs($x)); $tt = $tt + (20 * self::yj_sin2(self::pi_mul(6) * $x) + 20 * self::yj_sin2(self::pi_mul(2) * $x))*2.0/3.0; $tt = $tt + (20 * self::yj_sin2(M_PI * $y)+ 40 * self::yj_sin2(self::pi_div(3) * $y))*2.0/3.0; $tt = $tt + (160 * self::yj_sin2(self::pi_div(12) * $y) + 320 * self::yj_sin2(self::pi_div(30) * $y))*2.0/3.0; return $tt; } /** * * @param float $x * @return float */ static public function yj_sin2($x){ //另一种是直接返回sin($x) //return sin($x); $tt = $ss = $s2 = 0.0; $ff = 0; if($x < 0){ $x *= -1; $ff = 1; } $tt = $x - intval($x / self::pi_mul(2)) * self::pi_mul(2); //如果不考虑intval,$tt必定等于0 if ($tt > M_PI){ $tt -= M_PI; if ($ff==1){ $ff=0; }elseif ($ff==0){ $ff=1; } } //中间量若为0,则所有后续运算全部归0 if(0 == $tt){ return 0; } $x = $ss = $s2 = $tt; $tt=pow($tt, 2); //分别为3!,5!,7!,9!,11! foreach(array(6, 120, 5040, 362880, 39916800) as $index => $value){ $s2 *= $tt; if(0 == $index % 2){ $ss -= $s2 / $value; }else{ $ss += $s2 / $value; } } if ($ff==1){ $ss *= -1; } return $ss; } static public function random_yj(){ $casm_rr = self::$casm_rr; $casm_rr = 314159269 * $casm_rr + 453806245; $casm_rr = $casm_rr - intval($casm_rr / 2) * 2; $casm_rr = $casm_rr / 2 ; self::$casm_rr = $casm_rr; return $casm_rr; } static public function Transform_jyj5($x, $yy){ $mm = 1 - self::ELLIPSOID_PARAM_E2 * self::yj_sin2($x * self::pi_div(180)) * self::yj_sin2($x * self::pi_div(180)) ; $m = (self::ELLIPSOID_PARAM_A * (1 - self::ELLIPSOID_PARAM_E2)) / ($mm * sqrt($mm)); return ($yy * 180) / ($m * M_PI); } static public function Transform_jy5($x , $xx){ $n = sqrt (1 - self::ELLIPSOID_PARAM_E2 * self::yj_sin2($x * self::pi_div(180)) * self::yj_sin2($x * self::pi_div(180))); $n = ($xx * 180) /(self::ELLIPSOID_PARAM_A / $n * cos($x * self::pi_div(180)) * M_PI) ; return $n; } /** * pi除以 * @param int $x */ static public function pi_div($x = 1){ if(!isset(self::$pi_div_result[$x])){ self::$pi_div_result[$x] = (1 == $x) ? M_PI : (M_PI / $x); } return self::$pi_div_result[$x]; } /** * pi乘以 * @param int $x * @return float */ static public function pi_mul($x = 1){ if(!isset(self::$pi_mul_result[$x])){ self::$pi_mul_result[$x] = (1 == $x) ? M_PI : (M_PI * $x); } return self::$pi_mul_result[$x]; } /** * 获取或者设置conf_random的值 * @param bool|null $val 为bool值时,表示要设置为对应值;其余情况下,返回当前设置值 * @return bool */ static public function conf_random($val = null){ if(!is_bool($val)){ return self::$conf_random; } self::$conf_random = $val; return $val; } }