@@ -37,6 +37,13 @@ ZEND_BEGIN_ARG_INFO_EX(haversine_args, 0, 0, 4)
37
37
ZEND_ARG_INFO (0 , radius )
38
38
ZEND_END_ARG_INFO ()
39
39
40
+ ZEND_BEGIN_ARG_INFO_EX (vincenty_args , 0 , 0 , 3 )
41
+ ZEND_ARG_INFO (0 , fromLatitude )
42
+ ZEND_ARG_INFO (0 , fromLongitude )
43
+ ZEND_ARG_INFO (0 , toLatitude )
44
+ ZEND_ARG_INFO (0 , toLongitude )
45
+ ZEND_END_ARG_INFO ()
46
+
40
47
ZEND_BEGIN_ARG_INFO_EX (fraction_along_gc_line_args , 0 , 0 , 3 )
41
48
ZEND_ARG_INFO (0 , geoJsonPoint1 )
42
49
ZEND_ARG_INFO (0 , geoJsonPoint2 )
@@ -100,6 +107,7 @@ const zend_function_entry geospatial_functions[] = {
100
107
PHP_FE (transform_datum , transform_datum_args )
101
108
PHP_FE (dms_to_decimal , dms_to_decimal_args )
102
109
PHP_FE (decimal_to_dms , decimal_to_dms_args )
110
+ PHP_FE (vincenty , vincenty_args )
103
111
PHP_FE (rdp_simplify , rdp_simplify_args )
104
112
/* End of functions */
105
113
{ NULL , NULL , NULL }
@@ -229,29 +237,70 @@ double php_geo_haversine(double from_lat, double from_long, double to_lat, doubl
229
237
return result ;
230
238
}
231
239
240
+
232
241
geo_ellipsoid get_ellipsoid (long ellipsoid_const )
233
242
{
234
243
switch (ellipsoid_const ) {
235
244
case GEO_AIRY_1830 :
236
245
return airy_1830 ;
237
- break ;
238
246
case GEO_WGS84 :
239
247
default :
240
248
return wgs84 ;
241
- break ;
242
249
}
243
250
}
244
251
252
+ double php_geo_vincenty (double from_lat , double from_long , double to_lat , double to_long , geo_ellipsoid eli )
253
+ {
254
+ double U1 , U2 , L , lambda , lambdaP ;
255
+ double sinSigma , cosSigma , sigma , sinLambda , cosLambda ;
256
+ double sinU1 , sinU2 , cosU1 , cosU2 ;
257
+ double sinAlpha , cos2Alpha ;
258
+ double cosof2sigma , A , B , C , uSq , deltaSigma , s ;
259
+ int loopLimit = 100 ;
260
+ double precision = 0.000000000001 ;
261
+
262
+ U1 = atan ((1.0 - eli .f ) * tan (from_lat ));
263
+ U2 = atan ((1.0 - eli .f ) * tan (to_lat ));
264
+ L = to_long - from_long ;
265
+ sinU1 = sin (U1 );
266
+ cosU1 = cos (U1 );
267
+ sinU2 = sin (U2 );
268
+ cosU2 = cos (U2 );
269
+ lambda = L ;
270
+ do {
271
+ sinLambda = sin (lambda );
272
+ cosLambda = cos (lambda );
273
+ sinSigma = sqrt ((cosU2 * sinLambda ) * (cosU2 * sinLambda ) +
274
+ (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda ) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda ));
275
+ cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda ;
276
+ sigma = atan2 (sinSigma , cosSigma );
277
+ sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma ;
278
+ cos2Alpha = 1.0 - sinAlpha * sinAlpha ;
279
+ cosof2sigma = cosSigma - 2.0 * sinU1 * sinU2 / cos2Alpha ;
280
+ C = eli .f / 16.0 * cos2Alpha * (4.0 + eli .f * (4.0 - 3.0 * cos2Alpha ));
281
+ lambdaP = lambda ;
282
+ lambda = L + (1.0 - C ) * eli .f * sinAlpha *
283
+ (sigma + C * sinSigma * (cosof2sigma + C * cosSigma * (-1.0 + 2.0 * cosof2sigma * cosof2sigma )));
284
+ -- loopLimit ;
285
+ } while (fabs (lambda - lambdaP ) > precision && loopLimit > 0 );
286
+ uSq = cos2Alpha * (eli .a * eli .a - eli .b * eli .b ) / (eli .b * eli .b );
287
+ A = 1.0 + uSq / 16384.0 * (4096.0 + uSq * (-768.0 + uSq * (320.0 - 175.0 * uSq )));
288
+ B = uSq / 1024.0 * ( 256.0 + uSq * (-128.0 + uSq * (74.0 - 47.0 * uSq )));
289
+ deltaSigma = B * sinSigma * (cosof2sigma + B /4.0 * (cosSigma * (-1.0 + 2.0 * cosof2sigma * cosof2sigma )-
290
+ B / 6.0 * cosof2sigma * (-3.0 + 4.0 * sinSigma * sinSigma ) * (-3.0 + 4.0 * cosof2sigma * cosof2sigma )));
291
+ s = eli .b * A * (sigma - deltaSigma );
292
+ s = floor (s * 1000 ) / 1000 ;
293
+ return s ;
294
+ }
295
+
245
296
geo_helmert_constants get_helmert_constants (long from , long to )
246
297
{
247
298
switch (from - to ) {
248
299
case 1 :
249
300
return osgb36_wgs84 ;
250
- break ;
251
301
default :
252
302
case -1 :
253
303
return wgs84_osgb36 ;
254
- break ;
255
304
}
256
305
}
257
306
@@ -500,6 +549,19 @@ PHP_FUNCTION(haversine)
500
549
}
501
550
/* }}} */
502
551
552
+ PHP_FUNCTION (vincenty )
553
+ {
554
+ double from_lat , from_long , to_lat , to_long ;
555
+ double radius = GEO_EARTH_RADIUS ;
556
+ long reference_ellipsoid ;
557
+
558
+ if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "dddd|l" , & from_lat , & from_long , & to_lat , & to_long , & reference_ellipsoid ) == FAILURE ) {
559
+ return ;
560
+ }
561
+ geo_ellipsoid eli = get_ellipsoid (reference_ellipsoid );
562
+ RETURN_DOUBLE (php_geo_vincenty (from_lat * GEO_DEG_TO_RAD , from_long * GEO_DEG_TO_RAD , to_lat * GEO_DEG_TO_RAD , to_long * GEO_DEG_TO_RAD , eli ));
563
+ }
564
+
503
565
void php_geo_fraction_along_gc_line (double from_lat , double from_long , double to_lat , double to_long , double fraction , double radius , double * res_lat , double * res_long )
504
566
{
505
567
double distance ;
0 commit comments