@@ -54,6 +54,13 @@ ZEND_BEGIN_ARG_INFO_EX(cartesian_to_polar_args, 0, 0, 4)
54
54
ZEND_ARG_INFO (0 , reference_ellipsoid )
55
55
ZEND_END_ARG_INFO ()
56
56
57
+ ZEND_BEGIN_ARG_INFO_EX (change_datum_args , 0 , 0 , 4 )
58
+ ZEND_ARG_INFO (0 , latitude )
59
+ ZEND_ARG_INFO (0 , longitude )
60
+ ZEND_ARG_INFO (0 , from_reference_ellipsoid )
61
+ ZEND_ARG_INFO (0 , to_reference_ellipsoid )
62
+ ZEND_END_ARG_INFO ()
63
+
57
64
/* {{{ geospatial_functions[]
58
65
*
59
66
* Every user visible function must have an entry in geospatial_functions[].
@@ -63,6 +70,7 @@ const zend_function_entry geospatial_functions[] = {
63
70
PHP_FE (helmert , helmert_args )
64
71
PHP_FE (polar_to_cartesian , polar_to_cartesian_args )
65
72
PHP_FE (cartesian_to_polar , cartesian_to_polar_args )
73
+ PHP_FE (change_datum , change_datum_args )
66
74
/* End of functions */
67
75
{ NULL , NULL , NULL }
68
76
};
@@ -122,17 +130,25 @@ PHP_MINFO_FUNCTION(geospatial)
122
130
}
123
131
/* }}} */
124
132
125
- PHP_FUNCTION ( helmert )
133
+ geo_ellipsoid get_ellipsoid ( long ellipsoid_const )
126
134
{
127
- double x , y , z ;
128
- double xOut , yOut , zOut ;
129
- double rX , rY , rZ ;
130
-
131
- if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "ddd" , & x , & y , & z ) == FAILURE ) {
132
- return ;
135
+ switch (ellipsoid_const ) {
136
+ case GEO_AIRY_1830 :
137
+ return airy_1830 ;
138
+ break ;
139
+ case GEO_WGS84 :
140
+ default :
141
+ return wgs84 ;
142
+ break ;
133
143
}
144
+ }
145
+
146
+ geo_cartesian php_helmert (double x , double y , double z )
147
+ {
148
+ double rX , rY , rZ ;
149
+ double xOut , yOut , zOut ;
150
+ geo_cartesian point ;
134
151
135
- array_init (return_value );
136
152
rX = ROTATION_X / GEO_SEC_IN_DEG * GEO_DEG_TO_RAD ;
137
153
rY = ROTATION_Y / GEO_SEC_IN_DEG * GEO_DEG_TO_RAD ;
138
154
rZ = ROTATION_Z / GEO_SEC_IN_DEG * GEO_DEG_TO_RAD ;
@@ -146,25 +162,33 @@ PHP_FUNCTION(helmert)
146
162
zOut = WGS84_OSGB36_Z ;
147
163
zOut += ((-1 * rY * x ) + (rX * y ) + z ) * SCALE_CHANGE ;
148
164
149
- add_assoc_double (return_value , "x" , xOut );
150
- add_assoc_double (return_value , "y" , yOut );
151
- add_assoc_double (return_value , "z" , zOut );
165
+ point .x = xOut ;
166
+ point .y = yOut ;
167
+ point .z = zOut ;
168
+ return point ;
152
169
}
153
170
154
- PHP_FUNCTION (polar_to_cartesian )
171
+
172
+ PHP_FUNCTION (helmert )
155
173
{
156
- double latitude , longitude ;
157
174
double x , y , z ;
158
- long reference_ellipsoid ;
159
- if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "dd|l " , & latitude , & longitude , & reference_ellipsoid ) == FAILURE ) {
175
+ geo_cartesian point ;
176
+ if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "ddd " , & x , & y , & z ) == FAILURE ) {
160
177
return ;
161
178
}
162
- geo_ellipsoid eli = {WGS84_A , WGS84_B };
163
- if (reference_ellipsoid == GEO_AIRY_1830 ) {
164
- eli .a = AIRY_1830_A ;
165
- eli .b = AIRY_1830_B ;
166
- }
179
+
167
180
array_init (return_value );
181
+ point = php_helmert (x , y , z );
182
+ add_assoc_double (return_value , "x" , point .x );
183
+ add_assoc_double (return_value , "y" , point .y );
184
+ add_assoc_double (return_value , "z" , point .z );
185
+ }
186
+
187
+ geo_cartesian php_polar_to_cartesian (double latitude , double longitude , geo_ellipsoid eli )
188
+ {
189
+ double x , y , z ;
190
+
191
+ geo_cartesian point ;
168
192
double phi = latitude * GEO_DEG_TO_RAD ;
169
193
double lambda = longitude * GEO_DEG_TO_RAD ;
170
194
double eSq = ((eli .a * eli .a ) - (eli .b * eli .b )) / (eli .a * eli .a );
@@ -175,43 +199,96 @@ PHP_FUNCTION(polar_to_cartesian)
175
199
y *= cos (phi ) * sin (lambda );
176
200
z = ((1 - eSq ) * nu ) + HEIGHT ;
177
201
z *= sin (phi );
178
- add_assoc_double (return_value , "x" , x );
179
- add_assoc_double (return_value , "y" , y );
180
- add_assoc_double (return_value , "z" , z );
202
+ point .x = x ;
203
+ point .y = y ;
204
+ point .z = z ;
205
+ return point ;
181
206
}
182
207
183
- PHP_FUNCTION (cartesian_to_polar )
208
+ PHP_FUNCTION (polar_to_cartesian )
184
209
{
185
210
double latitude , longitude ;
186
- double x , y , z ;
187
- double nu , lambda , h ;
188
211
long reference_ellipsoid ;
189
- if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "ddd|l" , & x , & y , & z , & reference_ellipsoid ) == FAILURE ) {
212
+ geo_cartesian point ;
213
+
214
+ if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "dd|l" , & latitude , & longitude , & reference_ellipsoid ) == FAILURE ) {
190
215
return ;
191
216
}
192
- geo_ellipsoid eli = {WGS84_A , WGS84_B };
193
- if (reference_ellipsoid == GEO_AIRY_1830 ) {
194
- eli .a = AIRY_1830_A ;
195
- eli .b = AIRY_1830_B ;
196
- }
217
+ geo_ellipsoid eli = get_ellipsoid (reference_ellipsoid );
218
+ array_init (return_value );
219
+ point = php_polar_to_cartesian (latitude , longitude , eli );
220
+ add_assoc_double (return_value , "x" , point .x );
221
+ add_assoc_double (return_value , "y" , point .y );
222
+ add_assoc_double (return_value , "z" , point .z );
223
+ }
224
+
225
+ geo_lat_long php_cartesian_to_polar (double x , double y , double z , geo_ellipsoid eli )
226
+ {
227
+
228
+ double latitude , longitude ;
229
+ double nu , lambda , h ;
230
+ geo_lat_long polar ;
231
+
197
232
//aiming for 1m accuracy
198
233
double precision = 0.1 / eli .a ;
199
- array_init (return_value );
200
234
double eSq = ((eli .a * eli .a ) - (eli .b * eli .b )) / (eli .a * eli .a );
201
235
double p = sqrt (x * x + y * y );
202
236
double phi = atan2 (z , p * (1 - eSq ));
203
237
double phiP = 2 * M_PI ;
204
238
while (abs (phi - phiP ) > precision ) {
205
- nu = AIRY_1830_A / sqrt (1 - eSq * sin (phi ) * sin (phi ));
239
+ nu = eli . a / sqrt (1 - eSq * sin (phi ) * sin (phi ));
206
240
phiP = phi ;
207
241
phi = atan2 (z + eSq * nu * sin (phi ), p );
208
242
}
209
243
lambda = atan2 (y ,x );
210
244
h = p / cos (phi ) - nu ;
245
+ polar .latitude = phi / GEO_DEG_TO_RAD ;
246
+ polar .longitude = lambda / GEO_DEG_TO_RAD ;
247
+ polar .height = h ;
248
+
249
+ return polar ;
250
+ }
211
251
212
- add_assoc_double (return_value , "lat" , phi / GEO_DEG_TO_RAD );
213
- add_assoc_double (return_value , "long" , lambda / GEO_DEG_TO_RAD );
214
- add_assoc_double (return_value , "height" , h );
252
+ PHP_FUNCTION (cartesian_to_polar )
253
+ {
254
+ double x , y , z ;
255
+ long reference_ellipsoid ;
256
+ geo_lat_long polar ;
257
+
258
+ if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "ddd|l" , & x , & y , & z , & reference_ellipsoid ) == FAILURE ) {
259
+ return ;
260
+ }
261
+ geo_ellipsoid eli = get_ellipsoid (reference_ellipsoid );
262
+ array_init (return_value );
263
+ polar = php_cartesian_to_polar (x , y , z , eli );
264
+ add_assoc_double (return_value , "lat" , polar .latitude );
265
+ add_assoc_double (return_value , "long" , polar .longitude );
266
+ add_assoc_double (return_value , "height" , polar .height );
267
+ }
268
+
269
+
270
+
271
+
272
+
273
+ PHP_FUNCTION (change_datum )
274
+ {
275
+ double latitude , longitude ;
276
+ long from_reference_ellipsoid , to_reference_ellipsoid ;
277
+ geo_cartesian point , converted_point ;
278
+ geo_lat_long polar ;
279
+ if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "ddll" , & latitude , & longitude , & from_reference_ellipsoid , & to_reference_ellipsoid ) == FAILURE ) {
280
+ return ;
281
+ }
282
+ geo_ellipsoid eli_from = get_ellipsoid (from_reference_ellipsoid );
283
+ geo_ellipsoid eli_to = get_ellipsoid (to_reference_ellipsoid );
284
+ point = php_polar_to_cartesian (latitude , longitude , eli_from );
285
+ converted_point = php_helmert (point .x , point .y , point .z );
286
+ polar = php_cartesian_to_polar (converted_point .x , converted_point .y , converted_point .z , eli_to );
287
+
288
+ array_init (return_value );
289
+ add_assoc_double (return_value , "lat" , polar .latitude );
290
+ add_assoc_double (return_value , "long" , polar .longitude );
291
+ add_assoc_double (return_value , "height" , polar .height );
215
292
}
216
293
217
294
/* {{{ proto haversine(double fromLat, double fromLong, double toLat, double toLong [, double radius ])
0 commit comments