盘古开地

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

地图坐标转换

  1 <?php
  2 define('X_PI', 3.14159265358979324 * 3000.0 / 180.0);
  3 
  4 class Coordinate {
  5     // lat
  6     public $x = 0;
  7     // lon
  8     public $y = 0;
  9     // other
 10     public $z = 0;
 11 
 12     public function __construct($lat, $lon) {
 13         $this->x = $lat;
 14         $this->y = $lon;
 15     }
 16 }
 17 
 18 class CoordinateService {
 19 
 20     const GEOTYPEWGS = 1;
 21     const GEOTYPEGCJ = 2;
 22     const GEOTYPEBD  = 3;
 23 
 24     public static $GeoTypeMap = [
 25         self::GEOTYPEWGS => '地球坐标',
 26         self::GEOTYPEGCJ => '火星坐标',
 27         self::GEOTYPEBD => '百度坐标'
 28     ];
 29 
 30     private static $x_pi = X_PI;
 31     private static $pi = 3.14159265358979324;
 32     private static $a = 6378245.0;
 33     private static $ee = 0.00669342162296594323;
 34 
 35     public function format_coordinate($lat, $lon) {
 36         return new Coordinate($lat, $lon);
 37     }
 38     //火星坐标(GCJ02坐标,高德,谷歌,腾讯坐标)到百度坐标BD-09
 39     public static function gcjTObd($from) {
 40         $to = new Coordinate();
 41         $x = $from->y;
 42         $y = $from->x;
 43         $z = sqrt($x * $x + $y * $y) + 0.00002 * sin($y * self::$x_pi);
 44         $theta = atan2($y, $x) + 0.000003 * cos($x * self::$x_pi);
 45         $to->y = $z * cos($theta) + 0.0065;
 46         $to->x = $z * sin($theta) + 0.006;
 47 
 48         return ($to);
 49     }
 50 
 51     //百度坐标BD-09到火星坐标GCJ02(高德,谷歌,腾讯坐标)
 52     public static function bdTOgcj($from) {
 53         $to = new Coordinate();
 54         $x = $from->y - 0.0065;
 55         $y = $from->x - 0.006;
 56         $z = sqrt($x * $x + $y * $y) - 0.00002 * sin($y * self::$x_pi);
 57         $theta = atan2($y, $x) - 0.000003 * cos($x * self::$x_pi);
 58         $to->y = $z * cos($theta);
 59         $to->x = $z * sin($theta);
 60         return ($to);
 61     }
 62 
 63     // WGS-84(GPS坐标,谷歌地球坐标) 到 GCJ-02(火星坐标) 的转换
 64     public static function wgsTOgcj($from) {
 65         //double wgLat, double wgLon, out double mgLat, out double mgLon
 66         $wgLat = $from->x;
 67         $wgLon = $from->y;
 68         if (self::outOfChina($wgLat, $wgLon)) {
 69             return (new Coordinate($wgLat, $wgLon));
 70         }
 71 
 72         $dLat = self::transformLat($wgLon - 105.0, $wgLat - 35.0);
 73         $dLon = self::transformLon($wgLon - 105.0, $wgLat - 35.0);
 74         $radLat = $wgLat / 180.0 * self::$pi;
 75         $magic = sin($radLat);
 76         $magic = 1 - self::$ee * $magic * $magic;
 77         $sqrtMagic = sqrt($magic);
 78         $dLat = ($dLat * 180.0) / ((self::$a * (1 - self::$ee)) / ($magic * $sqrtMagic) * self::$pi);
 79         $dLon = ($dLon * 180.0) / (self::$a / $sqrtMagic * cos($radLat) * self::$pi);
 80 
 81         $mgLat = $wgLat + $dLat;
 82         $mgLon = $wgLon + $dLon;
 83 
 84         return (new Coordinate($mgLat, $mgLon));
 85     }
 86 
 87     // GCJ-02 到 WGS-84 的转换
 88     public static function gcjTOwgs($from) {
 89         $to = self::wgsTOgcj($from);
 90         $lat = $from->x;
 91         $lon = $from->y;
 92         $g_lat = $to->x;
 93         $g_lon = $to->y;
 94         $d_lat = $g_lat - $lat;
 95         $d_lon = $g_lon - $lon;
 96 
 97         return new Coordinate($lat - $d_lat, $lon - $d_lon);
 98     }
 99 
100     // 把地球经纬度转换为lat和lon
101     public static function earthCoordinate($t1, $t2) {
102         $tt1 = $t1->x + $t1->y / 60.0 + $t1->z / 3600.0;
103         $tt2 = $t2->x + $t2->y / 60.0 + $t2->z / 3600.0;
104 
105         return (new Coordinate($tt1, $tt2));
106     }
107 
108     private static function outOfChina($lat, $lon) {
109         if ($lon < 72.004 || $lon > 137.8347)
110             return TRUE;
111         if ($lat < 0.8293 || $lat > 55.8271)
112             return TRUE;
113 
114         return FALSE;
115     }
116 
117     private static function transformLat($x, $y) {
118         $ret = -100.0 + 2.0 * $x + 3.0 * $y + 0.2 * $y * $y + 0.1 * $x * $y + 0.2 * sqrt(abs($x));
119         $ret += (20.0 * sin(6.0 * $x * self::$pi) + 20.0 * sin(2.0 * $x * self::$pi)) * 2.0 / 3.0;
120         $ret += (20.0 * sin($y * self::$pi) + 40.0 * sin($y / 3.0 * self::$pi)) * 2.0 / 3.0;
121         $ret += (160.0 * sin($y / 12.0 * self::$pi) + 320 * sin($y * self::$pi / 30.0)) * 2.0 / 3.0;
122         return $ret;
123     }
124 
125     private static function transformLon($x, $y) {
126         $ret = 300.0 + $x + 2.0 * $y + 0.1 * $x * $x + 0.1 * $x * $y + 0.1 * sqrt(abs($x));
127         $ret += (20.0 * sin(6.0 * $x * self::$pi) + 20.0 * sin(2.0 * $x * self::$pi)) * 2.0 / 3.0;
128         $ret += (20.0 * sin($x * self::$pi) + 40.0 * sin($x / 3.0 * self::$pi)) * 2.0 / 3.0;
129         $ret += (150.0 * sin($x / 12.0 * self::$pi) + 300.0 * sin($x / 30.0 * self::$pi)) * 2.0 / 3.0;
130         return $ret;
131     }
132 
133 }

 

posted on 2017-05-08 17:24  盘古开地  阅读(236)  评论(0编辑  收藏  举报