static int GeodSolve2() { /* Check fix for antipodal prolate bug found 2010-09-04 */ double azi1, azi2, s12; struct geod_geodesic g; int result = 0; geod_init(&g, 6.4e6, -1/150.0); geod_inverse(&g, 0.07476, 0, -0.07476, 180, &s12, &azi1, &azi2); result += checkEquals(azi1, 90.00078, 0.5e-5); result += checkEquals(azi2, 90.00078, 0.5e-5); result += checkEquals(s12, 20106193, 0.5); geod_inverse(&g, 0.1, 0, -0.1, 180, &s12, &azi1, &azi2); result += checkEquals(azi1, 90.00105, 0.5e-5); result += checkEquals(azi2, 90.00105, 0.5e-5); result += checkEquals(s12, 20106193, 0.5); return result; }
SEXP inversegeodesic(SEXP longitude1, SEXP latitude1, SEXP longitude2, SEXP latitude2, SEXP pa, SEXP pf) { PROTECT(latitude1 = coerceVector(latitude1, REALSXP)); PROTECT(longitude1 = coerceVector(longitude1, REALSXP)); PROTECT(latitude2 = coerceVector(latitude2, REALSXP)); PROTECT(longitude2 = coerceVector(longitude2, REALSXP)); double a = REAL(pa)[0]; double f = REAL(pf)[0]; double *lat1, *lon1, *lat2, *lon2, *xr; lat1 = REAL(latitude1); lon1 = REAL(longitude1); lat2 = REAL(latitude2); lon2 = REAL(longitude2); SEXP r; PROTECT( r = allocVector(REALSXP, length(latitude1) )); xr = REAL(r); double azi1, azi2, s12; struct geod_geodesic g; geod_init(&g, a, f); for (int i=0; i < length(latitude1); i++) { geod_inverse(&g, lat1[i], lon1[i], lat2[i], lon2[i], &s12, &azi1, &azi2); xr[i] = s12; } UNPROTECT(5); return r; }
static int GeodSolve6() { /* Check fix for volatile sbet12a bug found 2011-06-25 (gcc 4.4.4 * x86 -O3). Found again on 2012-03-27 with tdm-mingw32 (g++ 4.6.1). */ double s12; struct geod_geodesic g; int result = 0; geod_init(&g, wgs84_a, wgs84_f); geod_inverse(&g, 88.202499451857, 0, -88.202499451857, 179.981022032992859592, &s12, nullptr, nullptr); result += checkEquals(s12, 20003898.214, 0.5e-3); geod_inverse(&g, 89.262080389218, 0, -89.262080389218, 179.992207982775375662, &s12, nullptr, nullptr); result += checkEquals(s12, 20003925.854, 0.5e-3); geod_inverse(&g, 89.333123580033, 0, -89.333123580032997687, 179.99295812360148422, &s12, nullptr, nullptr); result += checkEquals(s12, 20003926.881, 0.5e-3); return result; }
/* Geodesic distance (in meter) between two points with angular 2D coordinates */ double proj_lp_dist (const PJ *P, PJ_COORD a, PJ_COORD b) { double s12, azi1, azi2; /* Note: the geodesic code takes arguments in degrees */ geod_inverse (P->geod, PJ_TODEG(a.lpz.phi), PJ_TODEG(a.lpz.lam), PJ_TODEG(b.lpz.phi), PJ_TODEG(b.lpz.lam), &s12, &azi1, &azi2 ); return s12; }
static int GeodSolve0() { double azi1, azi2, s12; struct geod_geodesic g; int result = 0; geod_init(&g, wgs84_a, wgs84_f); geod_inverse(&g, 40.6, -73.8, 49.01666667, 2.55, &s12, &azi1, &azi2); result += checkEquals(azi1, 53.47022, 0.5e-5); result += checkEquals(azi2, 111.59367, 0.5e-5); result += checkEquals(s12, 5853226, 0.5); return result; }
static int GeodSolve9() { /* Check fix for volatile x bug found 2011-06-25 (gcc 4.4.4 x86 -O3) */ double s12; struct geod_geodesic g; int result = 0; geod_init(&g, wgs84_a, wgs84_f); geod_inverse(&g, 56.320923501171, 0, -56.320923501171, 179.664747671772880215, &s12, nullptr, nullptr); result += checkEquals(s12, 19993558.287, 0.5e-3); return result; }
static int GeodSolve4() { /* Check fix for short line bug found 2010-05-21 */ double s12; struct geod_geodesic g; int result = 0; geod_init(&g, wgs84_a, wgs84_f); geod_inverse(&g, 36.493349428792, 0, 36.49334942879201, .0000008, &s12, nullptr, nullptr); result += checkEquals(s12, 0.072, 0.5e-3); return result; }
/* Geodesic distance (in meter) + fwd and rev azimuth between two points on the ellipsoid */ PJ_COORD proj_geod (const PJ *P, PJ_COORD a, PJ_COORD b) { PJ_COORD c; /* Note: the geodesic code takes arguments in degrees */ geod_inverse (P->geod, PJ_TODEG(a.lpz.phi), PJ_TODEG(a.lpz.lam), PJ_TODEG(b.lpz.phi), PJ_TODEG(b.lpz.lam), c.v, c.v+1, c.v+2 ); return c; }
static int GeodSolve78() { /* An example where the NGS calculator fails to converge */ double azi1, azi2, s12; struct geod_geodesic g; int result = 0; geod_init(&g, wgs84_a, wgs84_f); geod_inverse(&g, 27.2, 0.0, -27.1, 179.5, &s12, &azi1, &azi2); result += checkEquals(azi1, 45.82468716758, 0.5e-11); result += checkEquals(azi2, 134.22776532670, 0.5e-11); result += checkEquals(s12, 19974354.765767, 0.5e-6); return result; }
static int GeodSolve59() { /* Check for points close with longitudes close to 180 deg apart. */ double azi1, azi2, s12; struct geod_geodesic g; int result = 0; geod_init(&g, wgs84_a, wgs84_f); geod_inverse(&g, 5, 0.00000000000001, 10, 180, &s12, &azi1, &azi2); result += checkEquals(azi1, 0.000000000000035, 1.5e-14); result += checkEquals(azi2, 179.99999999999996, 1.5e-14); result += checkEquals(s12, 18345191.174332713, 5e-9); return result; }
static int GeodSolve11() { /* Check fix for bet2 = -bet1 bug found 2011-06-25 (Visual Studio * 10 rel + debug) */ double s12; struct geod_geodesic g; int result = 0; geod_init(&g, wgs84_a, wgs84_f); geod_inverse(&g, 48.522876735459, 0, -48.52287673545898293, 179.599720456223079643, &s12, nullptr, nullptr); result += checkEquals(s12, 19989144.774, 0.5e-3); return result; }
static int GeodSolve10() { /* Check fix for adjust tol1_ bug found 2011-06-25 (Visual Studio * 10 rel + debug) */ double s12; struct geod_geodesic g; int result = 0; geod_init(&g, wgs84_a, wgs84_f); geod_inverse(&g, 52.784459512564, 0, -52.784459512563990912, 179.634407464943777557, &s12, nullptr, nullptr); result += checkEquals(s12, 19991596.095, 0.5e-3); return result; }
static int GeodSolve55() { /* Check fix for nan + point on equator or pole not returning all nans in * Geodesic::Inverse, found 2015-09-23. */ double azi1, azi2, s12, nan; struct geod_geodesic g; int result = 0; { double minus1 = -1; /* cppcheck-suppress wrongmathcall */ nan = sqrt(minus1); } geod_init(&g, wgs84_a, wgs84_f); geod_inverse(&g, nan, 0, 0, 90, &s12, &azi1, &azi2); result += checkNaN(azi1); result += checkNaN(azi2); result += checkNaN(s12); geod_inverse(&g, nan, 0, 90, 9, &s12, &azi1, &azi2); result += checkNaN(azi1); result += checkNaN(azi2); result += checkNaN(s12); return result; }
static int GeodSolve76() { /* The distance from Wellington and Salamanca (a classic failure of Vincenty) */ double azi1, azi2, s12; struct geod_geodesic g; int result = 0; geod_init(&g, wgs84_a, wgs84_f); geod_inverse(&g, -(41+19/60.0), 174+49/60.0, 40+58/60.0, -(5+30/60.0), &s12, &azi1, &azi2); result += checkEquals(azi1, 160.39137649664, 0.5e-11); result += checkEquals(azi2, 19.50042925176, 0.5e-11); result += checkEquals(s12, 19960543.857179, 0.5e-6); return result; }
static int GeodSolve12() { /* Check fix for inverse geodesics on extreme prolate/oblate * ellipsoids Reported 2012-08-29 Stefan Guenther * <*****@*****.**>; fixed 2012-10-07 */ double azi1, azi2, s12; struct geod_geodesic g; int result = 0; geod_init(&g, 89.8, -1.83); geod_inverse(&g, 0, 0, -10, 160, &s12, &azi1, &azi2); result += checkEquals(azi1, 120.27, 1e-2); result += checkEquals(azi2, 105.15, 1e-2); result += checkEquals(s12, 266.7, 1e-1); return result; }
static int GeodSolve14() { /* Check fix for inverse ignoring lon12 = nan */ double azi1, azi2, s12, nan; struct geod_geodesic g; int result = 0; { double minus1 = -1; /* cppcheck-suppress wrongmathcall */ nan = sqrt(minus1); } geod_init(&g, wgs84_a, wgs84_f); geod_inverse(&g, 0, 0, 1, nan, &s12, &azi1, &azi2); result += checkNaN(azi1); result += checkNaN(azi2); result += checkNaN(s12); return result; }
static int Planimeter15() { /* Coverage tests, includes Planimeter15 - Planimeter18 (combinations of reverse and sign) + calls to testpoint, testedge, geod_polygonarea. */ struct geod_geodesic g; struct geod_polygon p; double lat[] = {2, 1, 3}, lon[] = {1, 2, 3}; double area, s12, azi1; double r = 18454562325.45119, a0 = 510065621724088.5093; /* ellipsoid area */ int result = 0; geod_init(&g, wgs84_a, wgs84_f); geod_polygon_init(&p, 0); geod_polygon_addpoint(&g, &p, lat[0], lon[0]); geod_polygon_addpoint(&g, &p, lat[1], lon[1]); geod_polygon_testpoint(&g, &p, lat[2], lon[2], 0, 1, &area, nullptr); result += checkEquals(area, r, 0.5); geod_polygon_testpoint(&g, &p, lat[2], lon[2], 0, 0, &area, nullptr); result += checkEquals(area, r, 0.5); geod_polygon_testpoint(&g, &p, lat[2], lon[2], 1, 1, &area, nullptr); result += checkEquals(area, -r, 0.5); geod_polygon_testpoint(&g, &p, lat[2], lon[2], 1, 0, &area, nullptr); result += checkEquals(area, a0-r, 0.5); geod_inverse(&g, lat[1], lon[1], lat[2], lon[2], &s12, &azi1, nullptr); geod_polygon_testedge(&g, &p, azi1, s12, 0, 1, &area, nullptr); result += checkEquals(area, r, 0.5); geod_polygon_testedge(&g, &p, azi1, s12, 0, 0, &area, nullptr); result += checkEquals(area, r, 0.5); geod_polygon_testedge(&g, &p, azi1, s12, 1, 1, &area, nullptr); result += checkEquals(area, -r, 0.5); geod_polygon_testedge(&g, &p, azi1, s12, 1, 0, &area, nullptr); result += checkEquals(area, a0-r, 0.5); geod_polygon_addpoint(&g, &p, lat[2], lon[2]); geod_polygon_compute(&g, &p, 0, 1, &area, nullptr); result += checkEquals(area, r, 0.5); geod_polygon_compute(&g, &p, 0, 0, &area, nullptr); result += checkEquals(area, r, 0.5); geod_polygon_compute(&g, &p, 1, 1, &area, nullptr); result += checkEquals(area, -r, 0.5); geod_polygon_compute(&g, &p, 1, 0, &area, nullptr); result += checkEquals(area, a0-r, 0.5); geod_polygonarea(&g, lat, lon, 3, &area, nullptr); result += checkEquals(area, r, 0.5); return result; }
GAIAGEO_DECLARE double gaiaGeodesicDistance (double a, double b, double rf, double lat1, double lon1, double lat2, double lon2) { /* / Calculate geodesic distance (in m) / between two points specified by latitude/longitude / (in decimal degrees) */ #if PROJ_GEODESIC /* / using the PROJ.4 own implementation / / requires PROJ.4 >= 4.9.0 / / (accepting a patch suggested by Charles Karney <*****@*****.**> */ double s12; struct geod_geodesic gd; geod_init (&gd, a, 1 / rf); geod_inverse (&gd, lat1, lon1, lat2, lon2, &s12, 0, 0); return s12; #else /* / using Vincenty inverse formula for ellipsoids / / based on original JavaScript by (c) Chris Veness 2002-2008 / http://www.movable-type.co.uk/scripts/latlong-vincenty.html / */ double f = 1.0 / rf; double L = (lon2 - lon1) * DEG2RAD; double U1 = atan ((1.0 - f) * tan (lat1 * DEG2RAD)); double U2 = atan ((1.0 - f) * tan (lat2 * DEG2RAD)); double sinU1 = sin (U1); double cosU1 = cos (U1); double sinU2 = sin (U2); double cosU2 = cos (U2); double lambda = L; double lambdaP; double sinLambda; double cosLambda; double sinSigma; double cosSigma; double sigma; double sinAlpha; double cosSqAlpha; double cos2SigmaM; double C; double uSq; double A; double B; double deltaSigma; double s; int iterLimit = 100; do { sinLambda = sin (lambda); cosLambda = cos (lambda); sinSigma = sqrt ((cosU2 * sinLambda) * (cosU2 * sinLambda) + (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda)); if (sinSigma == 0.0) return 0.0; /* co-incident points */ cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda; sigma = atan2 (sinSigma, cosSigma); sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma; cosSqAlpha = 1.0 - sinAlpha * sinAlpha; cos2SigmaM = cosSigma - 2.0 * sinU1 * sinU2 / cosSqAlpha; if (isnan (cos2SigmaM)) cos2SigmaM = 0; /* equatorial line */ C = f / 16.0 * cosSqAlpha * (4.0 + f * (4.0 - 3.0 * cosSqAlpha)); lambdaP = lambda; lambda = L + (1.0 - C) * f * sinAlpha * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1.0 + 2.0 * cos2SigmaM * cos2SigmaM))); } while (fabs (lambda - lambdaP) > 1e-12 && --iterLimit > 0); if (iterLimit == 0) return -1.0; /* formula failed to converge */ uSq = cosSqAlpha * (a * a - b * b) / (b * b); A = 1.0 + uSq / 16384.0 * (4096.0 + uSq * (-768.0 + uSq * (320.0 - 175.0 * uSq))); B = uSq / 1024.0 * (256.0 + uSq * (-128.0 + uSq * (74.0 - 47.0 * uSq))); deltaSigma = B * sinSigma * (cos2SigmaM + B / 4.0 * (cosSigma * (-1.0 + 2.0 * cos2SigmaM * cos2SigmaM) - B / 6.0 * cos2SigmaM * (-3.0 + 4.0 * sinSigma * sinSigma) * (-3.0 + 4.0 * cos2SigmaM * cos2SigmaM))); s = b * A * (sigma - deltaSigma); return s; #endif /* end Vincenty formula */ }
static int GeodSolve33() { /* Check max(-0.0,+0.0) issues 2015-08-22 (triggered by bugs in Octave -- * sind(-0.0) = +0.0 -- and in some version of Visual Studio -- * fmod(-0.0, 360.0) = +0.0. */ double azi1, azi2, s12; struct geod_geodesic g; int result = 0; geod_init(&g, wgs84_a, wgs84_f); geod_inverse(&g, 0, 0, 0, 179, &s12, &azi1, &azi2); result += checkEquals(azi1, 90.00000, 0.5e-5); result += checkEquals(azi2, 90.00000, 0.5e-5); result += checkEquals(s12, 19926189, 0.5); geod_inverse(&g, 0, 0, 0, 179.5, &s12, &azi1, &azi2); result += checkEquals(azi1, 55.96650, 0.5e-5); result += checkEquals(azi2, 124.03350, 0.5e-5); result += checkEquals(s12, 19980862, 0.5); geod_inverse(&g, 0, 0, 0, 180, &s12, &azi1, &azi2); result += checkEquals(azi1, 0.00000, 0.5e-5); result += checkEquals(fabs(azi2), 180.00000, 0.5e-5); result += checkEquals(s12, 20003931, 0.5); geod_inverse(&g, 0, 0, 1, 180, &s12, &azi1, &azi2); result += checkEquals(azi1, 0.00000, 0.5e-5); result += checkEquals(fabs(azi2), 180.00000, 0.5e-5); result += checkEquals(s12, 19893357, 0.5); geod_init(&g, 6.4e6, 0); geod_inverse(&g, 0, 0, 0, 179, &s12, &azi1, &azi2); result += checkEquals(azi1, 90.00000, 0.5e-5); result += checkEquals(azi2, 90.00000, 0.5e-5); result += checkEquals(s12, 19994492, 0.5); geod_inverse(&g, 0, 0, 0, 180, &s12, &azi1, &azi2); result += checkEquals(azi1, 0.00000, 0.5e-5); result += checkEquals(fabs(azi2), 180.00000, 0.5e-5); result += checkEquals(s12, 20106193, 0.5); geod_inverse(&g, 0, 0, 1, 180, &s12, &azi1, &azi2); result += checkEquals(azi1, 0.00000, 0.5e-5); result += checkEquals(fabs(azi2), 180.00000, 0.5e-5); result += checkEquals(s12, 19994492, 0.5); geod_init(&g, 6.4e6, -1/300.0); geod_inverse(&g, 0, 0, 0, 179, &s12, &azi1, &azi2); result += checkEquals(azi1, 90.00000, 0.5e-5); result += checkEquals(azi2, 90.00000, 0.5e-5); result += checkEquals(s12, 19994492, 0.5); geod_inverse(&g, 0, 0, 0, 180, &s12, &azi1, &azi2); result += checkEquals(azi1, 90.00000, 0.5e-5); result += checkEquals(azi2, 90.00000, 0.5e-5); result += checkEquals(s12, 20106193, 0.5); geod_inverse(&g, 0, 0, 0.5, 180, &s12, &azi1, &azi2); result += checkEquals(azi1, 33.02493, 0.5e-5); result += checkEquals(azi2, 146.97364, 0.5e-5); result += checkEquals(s12, 20082617, 0.5); geod_inverse(&g, 0, 0, 1, 180, &s12, &azi1, &azi2); result += checkEquals(azi1, 0.00000, 0.5e-5); result += checkEquals(fabs(azi2), 180.00000, 0.5e-5); result += checkEquals(s12, 20027270, 0.5); return result; }