Geo-Distance-XS
view release on metacpan or search on metacpan
double s, c, omega, rr, aa, bb, pp, qq, d2, qp, eps1, eps2;
if (s2 == 0.) return 0.;
if (c2 == 0.) return M_PI * RM / KILOMETER_RHO * 0.001;
s = sqrt(s2), c = sqrt(c2);
omega = atan2(s, c);
rr = s * c;
aa = s2g * c2f / s2 + s2f * c2g / c2;
bb = s2g * c2f / s2 - s2f * c2g / c2;
pp = rr / omega;
qq = omega / rr;
d2 = s2 - c2;
qp = qq + 6. * pp;
eps1 = 0.5 * F * (-aa - 3. * bb * pp);
eps2 = 0.25 * F * F * ((-qp * bb + (-3.75 + d2 * (qq + 3.75 * pp)) *
aa + 4. - d2 * qq) * aa - (7.5 * d2 * bb * pp - qp) * bb);
double d = 2. * omega * A * (1. + eps1 + eps2);
return d / KILOMETER_RHO * 0.001;
}
/* TODO: add more guards against unexpected data */
double
_count_units (SV *self, SV *unit) {
dTHX;
STRLEN len;
char *name = SvPV(unit, len);
HV *hash;
SV **svp = hv_fetchs((HV *)SvRV(self), "units", 0);
if (! svp) my_croak("Unknown unit type \"%s\"", name);
hash = (HV *)SvRV(*svp);
svp = hv_fetch(hash, name, len, 0);
if (! svp) my_croak("Unknown unit type \"%s\"", name);
return SvNV(*svp);
}
MODULE = Geo::Distance::XS PACKAGE = Geo::Distance::XS
PROTOTYPES: DISABLE
void
distance (self, unit, lon1, lat1, lon2, lat2)
SV *self
SV *unit
NV lon1
NV lat1
NV lon2
NV lat2
PREINIT:
SV **key;
int index = 1;
double (*func)(double, double, double, double);
CODE:
if (lat2 == lat1 && lon2 == lon1)
XSRETURN_NV(0.);
key = hv_fetchs((HV *)SvRV(self), "formula_index", 0);
if (key) index = SvIV(*key);
switch (index) {
case 1: func = &haversine; break;
case 2: func = &cosines; break;
case 3: func = &vincenty; break;
case 4: func = &great_circle; break;
case 5: func = &polar; break;
case 6: func = &andoyer_lambert_thomas; break;
}
XSRETURN_NV(_count_units(self, unit) * (*func)(lat1, lon1, lat2, lon2));
( run in 1.339 second using v1.01-cache-2.11-cpan-39bf76dae61 )