@@ -41,13 +41,26 @@ ZEND_BEGIN_ARG_INFO_EX(helmert_args, 0, 0, 3)
41
41
ZEND_ARG_INFO (0 , z )
42
42
ZEND_END_ARG_INFO ()
43
43
44
+ ZEND_BEGIN_ARG_INFO_EX (polar_to_cartesian_args , 0 , 0 , 2 )
45
+ ZEND_ARG_INFO (0 , latitude )
46
+ ZEND_ARG_INFO (0 , longitude )
47
+ ZEND_END_ARG_INFO ()
48
+
49
+ ZEND_BEGIN_ARG_INFO_EX (cartesian_to_polar_args , 0 , 0 , 3 )
50
+ ZEND_ARG_INFO (0 , x )
51
+ ZEND_ARG_INFO (0 , y )
52
+ ZEND_ARG_INFO (0 , z )
53
+ ZEND_END_ARG_INFO ()
54
+
44
55
/* {{{ geospatial_functions[]
45
56
*
46
57
* Every user visible function must have an entry in geospatial_functions[].
47
58
*/
48
59
const zend_function_entry geospatial_functions [] = {
49
60
PHP_FE (haversine , haversine_args )
50
61
PHP_FE (helmert , helmert_args )
62
+ PHP_FE (polar_to_cartesian , polar_to_cartesian_args )
63
+ PHP_FE (cartesian_to_polar , cartesian_to_polar_args )
51
64
/* End of functions */
52
65
{ NULL , NULL , NULL }
53
66
};
@@ -145,6 +158,61 @@ PHP_FUNCTION(helmert)
145
158
add_next_index_double (return_value , zOut );
146
159
}
147
160
161
+ PHP_FUNCTION (polar_to_cartesian )
162
+ {
163
+ double latitude , longitude ;
164
+ double x , y , z ;
165
+ if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "dd" , & latitude , & longitude ) == FAILURE ) {
166
+ return ;
167
+ }
168
+
169
+ array_init (return_value );
170
+ double phi = latitude * GEO_DEG_TO_RAD ;
171
+ double lambda = longitude * GEO_DEG_TO_RAD ;
172
+ double eSq = ((AIRY_1830_A * AIRY_1830_A ) - (AIRY_1830_B * AIRY_1830_B )) / (AIRY_1830_A * AIRY_1830_A );
173
+ double nu = AIRY_1830_A / sqrt (1 - (eSq * sin (phi ) * sin (phi )));
174
+ x = nu + HEIGHT ;
175
+ x *= cos (phi ) * cos (lambda );
176
+ y = nu + HEIGHT ;
177
+ y *= cos (phi ) * sin (lambda );
178
+ z = ((1 - eSq ) * nu ) + HEIGHT ;
179
+ z *= sin (phi );
180
+ add_next_index_double (return_value , x );
181
+ add_next_index_double (return_value , y );
182
+ add_next_index_double (return_value , z );
183
+
184
+ }
185
+
186
+ PHP_FUNCTION (cartesian_to_polar )
187
+ {
188
+ double latitude , longitude ;
189
+ double x , y , z ;
190
+ double nu , lambda , h ;
191
+
192
+ if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "ddd" , & x , & y , & z ) == FAILURE ) {
193
+ return ;
194
+ }
195
+ //aiming for 1m accuracy
196
+ double precision = 0.1 / AIRY_1830_A ;
197
+ array_init (return_value );
198
+ double eSq = ((AIRY_1830_A * AIRY_1830_A ) - (AIRY_1830_B * AIRY_1830_B )) / (AIRY_1830_A * AIRY_1830_A );
199
+ double p = sqrt (x * x + y * y );
200
+ double phi = atan2 (z , p * (1 - eSq ));
201
+ double phiP = 2 * M_PI ;
202
+ while (abs (phi - phiP ) > precision ) {
203
+ nu = AIRY_1830_A / sqrt (1 - eSq * sin (phi ) * sin (phi ));
204
+ phiP = phi ;
205
+ phi = atan2 (z + eSq * nu * sin (phi ), p );
206
+ }
207
+ lambda = atan2 (y ,x );
208
+ h = p / cos (phi ) - nu ;
209
+
210
+ add_assoc_double (return_value , "lat" , phi / GEO_DEG_TO_RAD );
211
+ add_assoc_double (return_value , "long" , lambda / GEO_DEG_TO_RAD );
212
+ add_assoc_double (return_value , "height" , h );
213
+
214
+ }
215
+
148
216
/* {{{ proto haversine(double fromLat, double fromLong, double toLat, double toLong [, double radius ])
149
217
* Calculates the greater circle distance between the two lattitude/longitude pairs */
150
218
PHP_FUNCTION (haversine )
0 commit comments