11<?php
2- namespace leoding86 \CoordTransform ;
32
4- class Coord extends Transform
3+ namespace labs7in0 \coord ;
4+
5+ use labs7in0 \coord \Exceptions \UnknownTypeException ;
6+
7+ class Coord
58{
6- public function __construct ($ lng , $ lat , $ type )
9+ const WGS84 = 1 ;
10+ const GCJ02 = 2 ;
11+ const BD09 = 3 ;
12+ const X_PI = 52.359877559829887333333333333333 ; // 3.14159265358979324 * 3000.0 / 180.0;
13+ const PI = 3.1415926535897932384626 ;
14+ const A = 6378245.0 ;
15+ const EE = 0.00669342162296594323 ;
16+
17+ private $ longitude ;
18+ private $ latitude ;
19+ private $ type ;
20+
21+ public function __construct (float $ longitude , float $ latitude , int $ type = self ::WGS84 )
722 {
8- $ this ->lng = $ lng ;
9- $ this ->lat = $ lat ;
23+ if (!in_array ($ type , [1 , 2 , 3 ])) {
24+ throw new UnknownTypeException ($ this ->type );
25+ }
26+
27+ $ this ->longitude = $ longitude ;
28+ $ this ->latitude = $ latitude ;
1029 $ this ->type = $ type ;
1130 }
1231
32+ private function gcj02ToWgs84 ()
33+ {
34+ if ($ this ->isOutOfChina ()) {
35+ return $ this ;
36+ } else {
37+ $ dlatitude = $ this ->transformLatitude ($ this ->longitude - 105.0 , $ this ->latitude - 35.0 );
38+ $ dlongitude = $ this ->transformLongitude ($ this ->longitude - 105.0 , $ this ->latitude - 35.0 );
39+ $ radlatitude = $ this ->latitude / 180.0 * self ::PI ;
40+ $ magic = sin ($ radlatitude );
41+ $ magic = 1 - self ::EE * $ magic * $ magic ;
42+ $ sqrtmagic = sqrt ($ magic );
43+ $ dlatitude = ($ dlatitude * 180.0 ) / ((self ::A * (1 - self ::EE )) / ($ magic * $ sqrtmagic ) * self ::PI );
44+ $ dlongitude = ($ dlongitude * 180.0 ) / (self ::A / $ sqrtmagic * cos ($ radlatitude ) * self ::PI );
45+ $ mglatitude = $ this ->latitude + $ dlatitude ;
46+ $ mglongitude = $ this ->longitude + $ dlongitude ;
47+
48+ return new self ($ this ->longitude * 2 - $ mglongitude , $ this ->latitude * 2 - $ mglatitude , self ::WGS84 );
49+ }
50+ }
51+
52+ private function wgs84ToGcj02 ()
53+ {
54+ if ($ this ->isOutOfChina ()) {
55+ return $ this ;
56+ } else {
57+ $ dlatitude = $ this ->transformLatitude ($ this ->longitude - 105.0 , $ this ->latitude - 35.0 );
58+ $ dlongitude = $ this ->transformLongitude ($ this ->longitude - 105.0 , $ this ->latitude - 35.0 );
59+ $ radlatitude = $ this ->latitude / 180.0 * self ::PI ;
60+ $ magic = sin ($ radlatitude );
61+ $ magic = 1 - self ::EE * $ magic * $ magic ;
62+ $ sqrtmagic = sqrt ($ magic );
63+ $ dlatitude = ($ dlatitude * 180.0 ) / ((self ::A * (1 - self ::EE )) / ($ magic * $ sqrtmagic ) * self ::PI );
64+ $ dlongitude = ($ dlongitude * 180.0 ) / (self ::A / $ sqrtmagic * cos ($ radlatitude ) * self ::PI );
65+ $ mglatitude = $ this ->latitude + $ dlatitude ;
66+ $ mglongitude = $ this ->longitude + $ dlongitude ;
67+
68+ return new self ($ mglongitude , $ mglatitude , self ::GCJ02 );
69+ }
70+ }
71+
72+ private function bd09ToGcj02 ()
73+ {
74+ $ x = $ this ->longitude - 0.0065 ;
75+ $ y = $ this ->latitude - 0.006 ;
76+ $ z = sqrt ($ x * $ x + $ y * $ y ) - 0.00002 * sin ($ y * self ::X_PI );
77+ $ theta = atan2 ($ y , $ x ) - 0.000003 * cos ($ x * self ::X_PI );
78+
79+ return new self ($ z * cos ($ theta ), $ z * sin ($ theta ), self ::GCJ02 );
80+ }
81+
82+ private function gcj02ToBd09 ()
83+ {
84+ $ z = sqrt ($ this ->longitude * $ this ->longitude + $ this ->latitude * $ this ->latitude ) + 0.00002 * sin ($ this ->latitude * self ::X_PI );
85+ $ theta = atan2 ($ this ->latitude , $ this ->longitude ) + 0.000003 * cos ($ this ->longitude * self ::X_PI );
86+ $ bd_longitude = $ z * cos ($ theta ) + 0.0065 ;
87+ $ bd_latitude = $ z * sin ($ theta ) + 0.006 ;
88+
89+ return new self ($ bd_longitude , $ bd_latitude , self ::BD09 );
90+ }
91+
92+ private function bd09ToWgs84 ()
93+ {
94+ return $ this ->bd09ToGcj02 ()->gcj02ToWgs84 ();
95+ }
96+
97+ private function wgs84ToBd09 ()
98+ {
99+ return $ this ->wgs84ToGcj02 ()->gcj02ToBd09 ();
100+ }
101+
102+ private function transformLatitude (float $ longitude , float $ latitude )
103+ {
104+ $ ret = -100.0 + 2.0 * $ longitude + 3.0 * $ latitude + 0.2 * $ latitude * $ latitude + 0.1 * $ longitude * $ latitude + 0.2 * sqrt (abs ($ longitude ));
105+ $ ret += (20.0 * sin (6.0 * $ longitude * self ::PI ) + 20.0 * sin (2.0 * $ longitude * self ::PI )) * 2.0 / 3.0 ;
106+ $ ret += (20.0 * sin ($ latitude * self ::PI ) + 40.0 * sin ($ latitude / 3.0 * self ::PI )) * 2.0 / 3.0 ;
107+ $ ret += (160.0 * sin ($ latitude / 12.0 * self ::PI ) + 320 * sin ($ latitude * self ::PI / 30.0 )) * 2.0 / 3.0 ;
108+ return $ ret ;
109+ }
110+
111+ private function transformLongitude (float $ longitude , float $ latitude )
112+ {
113+ $ ret = 300.0 + $ longitude + 2.0 * $ latitude + 0.1 * $ longitude * $ longitude + 0.1 * $ longitude * $ latitude + 0.1 * sqrt (abs ($ longitude ));
114+ $ ret += (20.0 * sin (6.0 * $ longitude * self ::PI ) + 20.0 * sin (2.0 * $ longitude * self ::PI )) * 2.0 / 3.0 ;
115+ $ ret += (20.0 * sin ($ longitude * self ::PI ) + 40.0 * sin ($ longitude / 3.0 * self ::PI )) * 2.0 / 3.0 ;
116+ $ ret += (150.0 * sin ($ longitude / 12.0 * self ::PI ) + 300.0 * sin ($ longitude / 30.0 * self ::PI )) * 2.0 / 3.0 ;
117+ return $ ret ;
118+ }
119+
120+ public function isOutOfChina ()
121+ {
122+ return ($ this ->longitude < 72.004 || $ this ->longitude > 137.8347 )
123+ || ($ this ->latitude < 0.8293 || $ this ->latitude > 55.8271 );
124+ }
125+
126+ public function toWgs84 ()
127+ {
128+ switch ($ this ->type ) {
129+ case self ::WGS84 :
130+ return $ this ;
131+ break ;
132+ case self ::GCJ02 :
133+ return $ this ->gcj02ToWgs84 ();
134+ break ;
135+ case self ::BD09 :
136+ return $ this ->bd09ToWgs84 ();
137+ break ;
138+ default :
139+ throw new UnknownTypeException ($ this ->type );
140+ }
141+ }
142+
143+ public function toGcj02 ()
144+ {
145+ switch ($ this ->type ) {
146+ case self ::WGS84 :
147+ return $ this ->wgs84ToGcj02 ();
148+ break ;
149+ case self ::GCJ02 :
150+ return $ this ;
151+ break ;
152+ case self ::BD09 :
153+ return $ this ->bd09ToGcj02 ();
154+ break ;
155+ default :
156+ throw new UnknownTypeException ($ this ->type );
157+ }
158+ }
159+
160+ public function toBd09 ()
161+ {
162+ switch ($ this ->type ) {
163+ case self ::WGS84 :
164+ return $ this ->wgs84ToBd09 ();
165+ break ;
166+ case self ::GCJ02 :
167+ return $ this ->gcj02ToBd09 ();
168+ break ;
169+ case self ::BD09 :
170+ return $ this ;
171+ break ;
172+ default :
173+ throw new UnknownTypeException ($ this ->type );
174+ }
175+ }
176+
177+ public function to (int $ type )
178+ {
179+ switch ($ type ) {
180+ case self ::WGS84 :
181+ return $ this ->toWgs84 ();
182+ break ;
183+ case self ::GCJ02 :
184+ return $ this ->toGcj02 ();
185+ break ;
186+ case self ::BD09 :
187+ return $ this ->toBd09 ();
188+ break ;
189+ default :
190+ throw new UnknownTypeException ($ this ->type );
191+ }
192+ }
193+
194+ public function distanceTo (Coord $ destination )
195+ {
196+ $ destination = $ destination ->to ($ this ->type );
197+
198+ $ latitudeRadA = deg2rad ($ this ->latitude );
199+ $ longitudeRadA = deg2rad ($ this ->longitude );
200+ $ latitudeRadB = deg2rad ($ destination ->latitude );
201+ $ longitudeRadB = deg2rad ($ destination ->longitude );
202+
203+ return 2 * asin (sqrt (
204+ pow (sin (($ latitudeRadA - $ latitudeRadB ) / 2 ), 2 )
205+ + cos ($ latitudeRadA ) * cos ($ latitudeRadB )
206+ * pow (sin (($ longitudeRadA - $ longitudeRadB ) / 2 ), 2 )
207+ )) * 6378.137 * 1000 ;
208+ }
209+
210+ public function string ()
211+ {
212+ return $ this ->longitude . ', ' . $ this ->latitude ;
213+ }
214+
13215 public function __toString ()
14216 {
15- return $ this ->type . ' : ' . $ this -> lng . ' , ' . $ this -> lat . PHP_EOL ;
217+ return $ this ->string () ;
16218 }
17- }
219+ }
0 commit comments