Example #1
0
 private static void Lam_phi_reduction(com.epl.geometry.PeDouble p_lam, com.epl.geometry.PeDouble p_phi)
 {
     p_lam.val = Lam_delta(p_lam.val);
     p_phi.val = Lam_delta(p_phi.val);
     if (PE_ABS(p_phi.val) > PE_PI2)
     {
         p_lam.val = Lam_delta(p_lam.val + PE_PI);
         p_phi.val = PE_SGN(PE_PI, p_phi.val) - p_phi.val;
     }
 }
        internal static double GeodesicDistanceOnWGS84Impl(com.epl.geometry.Point ptFrom, com.epl.geometry.Point ptTo)
        {
            double a = 6378137.0;
            // radius of spheroid for WGS_1984
            double e2 = 0.0066943799901413165;
            // ellipticity for WGS_1984
            double rpu = System.Math.PI / 180.0;

            com.epl.geometry.PeDouble answer = new com.epl.geometry.PeDouble();
            com.epl.geometry.GeoDist.Geodesic_distance_ngs(a, e2, ptFrom.GetX() * rpu, ptFrom.GetY() * rpu, ptTo.GetX() * rpu, ptTo.GetY() * rpu, answer, null, null);
            return(answer.val);
        }
Example #3
0
        public static void Geodesic_distance_ngs(double a, double e2, double lam1, double phi1, double lam2, double phi2, com.epl.geometry.PeDouble p_dist, com.epl.geometry.PeDouble p_az12, com.epl.geometry.PeDouble p_az21)
        {
            /* Highly edited version (plus lots of additions) of NGS FORTRAN code */

            /*
             * inverse for long-line and antipodal cases.* latitudes may be 90
             * degrees exactly.* latitude positive north, longitude positive east,
             * radians.* azimuth clockwise from north, radians.* original programmed
             * by thaddeus vincenty, 1975, 1976* removed back side solution option,
             * debugged, revised -- 2011may01 -- dgm* this version of code is
             * interim -- antipodal boundary needs work
             *
             * * output (besides az12, az21, and dist):* These have been removed
             * from this esri version of the ngs code* it, iteration count* sigma,
             * spherical distance on auxiliary sphere* lam_sph, longitude difference
             * on auxiliary sphere* kind, solution flag: kind=1, long-line; kind=2,
             * antipodal
             *
             *
             * All references to Rapp are Part II
             */
            double tol         = 1.0e-14;
            double eps         = 1.0e-15;
            double boa         = 0.0;
            double dlam        = 0.0;
            double eta1        = 0.0;
            double sin_eta1    = 0.0;
            double cos_eta1    = 0.0;
            double eta2        = 0.0;
            double sin_eta2    = 0.0;
            double cos_eta2    = 0.0;
            double prev        = 0.0;
            double test        = 0.0;
            double sin_lam_sph = 0.0;
            double cos_lam_sph = 0.0;
            double temp        = 0.0;
            double sin_sigma   = 0.0;
            double cos_sigma   = 0.0;
            double sin_azeq    = 0.0;
            double cos2_azeq   = 0.0;
            double costm       = 0.0;
            double costm2      = 0.0;
            double c           = 0.0;
            double d           = 0.0;
            double tem1        = 0.0;
            double tem2        = 0.0;
            double ep2         = 0.0;
            double bige        = 0.0;
            double bigf        = 0.0;
            double biga        = 0.0;
            double bigb        = 0.0;
            double z           = 0.0;
            double dsigma      = 0.0;
            bool   q_continue_looping;
            double f       = 0.0;
            double az12    = 0.0;
            double az21    = 0.0;
            double dist    = 0.0;
            double sigma   = 0.0;
            double lam_sph = 0.0;
            int    it      = 0;
            int    kind    = 0;

            com.epl.geometry.PeDouble lam = new com.epl.geometry.PeDouble();
            com.epl.geometry.PeDouble phi = new com.epl.geometry.PeDouble();
            /* Are there any values to calculate? */
            if (p_dist == null && p_az12 == null && p_az21 == null)
            {
                return;
            }
            /* Normalize point 1 and 2 */
            lam.val = lam1;
            phi.val = phi1;
            Lam_phi_reduction(lam, phi);
            lam1    = lam.val;
            phi1    = phi.val;
            lam.val = lam2;
            phi.val = phi2;
            Lam_phi_reduction(lam, phi);
            lam2 = lam.val;
            phi2 = phi.val;
            dlam = Lam_delta(lam2 - lam1);
            /* longitude difference [-Pi, Pi] */
            if (PE_EQ(phi1, phi2) && (PE_ZERO(dlam) || PE_EQ(PE_ABS(phi1), PE_PI2)))
            {
                /* Check that the points are not the same */
                if (p_dist != null)
                {
                    p_dist.val = 0.0;
                }
                if (p_az12 != null)
                {
                    p_az12.val = 0.0;
                }
                if (p_az21 != null)
                {
                    p_az21.val = 0.0;
                }
                return;
            }
            else
            {
                if (PE_EQ(phi1, -phi2))
                {
                    /* Check if they are perfectly antipodal */
                    if (PE_EQ(PE_ABS(phi1), PE_PI2))
                    {
                        /* Check if they are at opposite poles */
                        if (p_dist != null)
                        {
                            p_dist.val = 2.0 * Q90(a, e2);
                        }
                        if (p_az12 != null)
                        {
                            p_az12.val = phi1 > 0.0 ? Lam_delta(PE_PI - Lam_delta(lam2)) : Lam_delta(lam2);
                        }
                        if (p_az21 != null)
                        {
                            p_az21.val = phi1 > 0.0 ? Lam_delta(lam2) : Lam_delta(PE_PI - Lam_delta(lam2));
                        }
                        return;
                    }
                    else
                    {
                        if (PE_EQ(PE_ABS(dlam), PE_PI))
                        {
                            /* Other antipodal */
                            if (p_dist != null)
                            {
                                p_dist.val = 2.0 * Q90(a, e2);
                            }
                            if (p_az12 != null)
                            {
                                p_az12.val = 0.0;
                            }
                            if (p_az21 != null)
                            {
                                p_az21.val = 0.0;
                            }
                            return;
                        }
                    }
                }
            }
            if (PE_ZERO(e2))
            {
                /* Sphere */
                double cos_phi1;
                double cos_phi2;
                double sin_phi1;
                double sin_phi2;
                cos_phi1 = System.Math.Cos(phi1);
                cos_phi2 = System.Math.Cos(phi2);
                sin_phi1 = System.Math.Sin(phi1);
                sin_phi2 = System.Math.Sin(phi2);
                if (p_dist != null)
                {
                    tem1       = System.Math.Sin((phi2 - phi1) / 2.0);
                    tem2       = System.Math.Sin(dlam / 2.0);
                    sigma      = 2.0 * System.Math.Asin(System.Math.Sqrt(tem1 * tem1 + cos_phi1 * cos_phi2 * tem2 * tem2));
                    p_dist.val = sigma * a;
                }
                if (p_az12 != null)
                {
                    if (PE_EQ(PE_ABS(phi1), PE_PI2))
                    {
                        /* Origin at N or S Pole */
                        p_az12.val = phi1 < 0.0 ? lam2 : Lam_delta(PE_PI - lam2);
                    }
                    else
                    {
                        p_az12.val = System.Math.Atan2(cos_phi2 * System.Math.Sin(dlam), cos_phi1 * sin_phi2 - sin_phi1 * cos_phi2 * System.Math.Cos(dlam));
                    }
                }
                if (p_az21 != null)
                {
                    if (PE_EQ(PE_ABS(phi2), PE_PI2))
                    {
                        /* Destination at N or S Pole */
                        p_az21.val = phi2 < 0.0 ? lam1 : Lam_delta(PE_PI - lam1);
                    }
                    else
                    {
                        p_az21.val = System.Math.Atan2(cos_phi1 * System.Math.Sin(dlam), sin_phi2 * cos_phi1 * System.Math.Cos(dlam) - cos_phi2 * sin_phi1);
                        p_az21.val = Lam_delta(p_az21.val + PE_PI);
                    }
                }
                return;
            }
            f    = 1.0 - System.Math.Sqrt(1.0 - e2);
            boa  = 1.0 - f;
            eta1 = System.Math.Atan(boa * System.Math.Tan(phi1));
            /* better reduced latitude */
            sin_eta1 = System.Math.Sin(eta1);
            cos_eta1 = System.Math.Cos(eta1);
            eta2     = System.Math.Atan(boa * System.Math.Tan(phi2));
            /* better reduced latitude */
            sin_eta2 = System.Math.Sin(eta2);
            cos_eta2 = System.Math.Cos(eta2);
            prev     = dlam;
            test     = dlam;
            it       = 0;
            kind     = 1;
            lam_sph  = dlam;
            /* v13 (Rapp ) */
            /* top of the long-line loop (kind = 1) */
            q_continue_looping = true;
            while (q_continue_looping && it < 100)
            {
                it = it + 1;
                if (kind == 1)
                {
                    sin_lam_sph = System.Math.Sin(lam_sph);

                    /*
                     * if ( PE_ABS(PE_PI - PE_ABS(dlam)) < 2.0e-11 ) sin_lam_sph =
                     * 0.0 no--troublesome
                     */
                    cos_lam_sph = System.Math.Cos(lam_sph);
                    tem1        = cos_eta2 * sin_lam_sph;
                    temp        = cos_eta1 * sin_eta2 - sin_eta1 * cos_eta2 * cos_lam_sph;
                    sin_sigma   = System.Math.Sqrt(tem1 * tem1 + temp * temp);

                    /*
                     * v14 (Rapp
                     * 1.87)
                     */
                    cos_sigma = sin_eta1 * sin_eta2 + cos_eta1 * cos_eta2 * cos_lam_sph;
                    /* v15 (Rapp 1.88) */
                    sigma = System.Math.Atan2(sin_sigma, cos_sigma);
                    /* (Rapp 1.89) */
                    if (PE_ABS(sin_sigma) < eps)
                    {
                        /* avoid division by 0 */
                        sin_azeq = cos_eta1 * cos_eta2 * sin_lam_sph / PE_SGN(eps, sin_sigma);
                    }
                    else
                    {
                        sin_azeq = cos_eta1 * cos_eta2 * sin_lam_sph / sin_sigma;
                    }
                    /* v17 (Rapp 1.90) */
                    cos2_azeq = 1.0 - sin_azeq * sin_azeq;
                    if (PE_ABS(cos2_azeq) < eps)
                    {
                        /* avoid division by 0 */
                        costm = cos_sigma - 2.0 * (sin_eta1 * sin_eta2 / PE_SGN(eps, cos2_azeq));
                    }
                    else
                    {
                        costm = cos_sigma - 2.0 * (sin_eta1 * sin_eta2 / cos2_azeq);
                    }
                    /* v18 (Rapp 1.91) */
                    costm2 = costm * costm;
                    c      = ((-3.0 * cos2_azeq + 4.0) * f + 4.0) * cos2_azeq * f / 16.0;
                }

                /*
                 * v10
                 * (
                 * Rapp
                 * 1.83
                 * )
                 */
                /* entry point of the antipodal loop (kind = 2) */
                d = (1.0 - c) * f * (sigma + c * sin_sigma * (costm + cos_sigma * c * (2.0 * costm2 - 1.0)));
                /* v11 (Rapp 1.84) */
                if (kind == 1)
                {
                    lam_sph = dlam + d * sin_azeq;
                    if (PE_ABS(lam_sph - test) < tol)
                    {
                        q_continue_looping = false;
                        continue;
                    }
                    if (PE_ABS(lam_sph) > PE_PI)
                    {
                        kind    = 2;
                        lam_sph = PE_PI;
                        if (dlam < 0.0)
                        {
                            lam_sph = -lam_sph;
                        }
                        sin_azeq  = 0.0;
                        cos2_azeq = 1.0;
                        test      = 2.0;
                        prev      = test;
                        sigma     = PE_PI - PE_ABS(System.Math.Atan(sin_eta1 / cos_eta1) + System.Math.Atan(sin_eta2 / cos_eta2));
                        sin_sigma = System.Math.Sin(sigma);
                        cos_sigma = System.Math.Cos(sigma);
                        c         = ((-3.0 * cos2_azeq + 4.0) * f + 4.0) * cos2_azeq * f / 16.0;
                        /* v10 (Rapp 1.83) */
                        if (PE_ABS(sin_azeq - prev) < tol)
                        {
                            q_continue_looping = false;
                            continue;
                        }
                        if (PE_ABS(cos2_azeq) < eps)
                        {
                            /* avoid division by 0 */
                            costm = cos_sigma - 2.0 * (sin_eta1 * sin_eta2 / PE_SGN(eps, cos2_azeq));
                        }
                        else
                        {
                            costm = cos_sigma - 2.0 * (sin_eta1 * sin_eta2 / cos2_azeq);
                        }
                        /* v18 (Rapp 1.91) */
                        costm2 = costm * costm;
                        continue;
                    }
                    if (((lam_sph - test) * (test - prev)) < 0.0 && it > 5)
                    {
                        /* refined converge */
                        lam_sph = (2.0 * lam_sph + 3.0 * test + prev) / 6.0;
                    }
                    prev = test;
                    test = lam_sph;
                    continue;
                }
                else
                {
                    /* kind == 2 */
                    sin_azeq = (lam_sph - dlam) / d;
                    if (((sin_azeq - test) * (test - prev)) < 0.0 && it > 5)
                    {
                        /* refined converge */
                        sin_azeq = (2.0 * sin_azeq + 3.0 * test + prev) / 6.0;
                    }
                    prev        = test;
                    test        = sin_azeq;
                    cos2_azeq   = 1.0 - sin_azeq * sin_azeq;
                    sin_lam_sph = sin_azeq * sin_sigma / (cos_eta1 * cos_eta2);
                    cos_lam_sph = -System.Math.Sqrt(PE_ABS(1.0 - sin_lam_sph * sin_lam_sph));
                    lam_sph     = System.Math.Atan2(sin_lam_sph, cos_lam_sph);
                    tem1        = cos_eta2 * sin_lam_sph;
                    temp        = cos_eta1 * sin_eta2 - sin_eta1 * cos_eta2 * cos_lam_sph;
                    sin_sigma   = System.Math.Sqrt(tem1 * tem1 + temp * temp);
                    cos_sigma   = sin_eta1 * sin_eta2 + cos_eta1 * cos_eta2 * cos_lam_sph;
                    sigma       = System.Math.Atan2(sin_sigma, cos_sigma);
                    c           = ((-3.0 * cos2_azeq + 4.0) * f + 4.0) * cos2_azeq * f / 16.0;

                    /*
                     * v10
                     * (
                     * Rapp
                     * 1.83
                     * )
                     */
                    if (PE_ABS(sin_azeq - prev) < tol)
                    {
                        q_continue_looping = false;
                        continue;
                    }
                    if (PE_ABS(cos2_azeq) < eps)
                    {
                        /* avoid division by 0 */
                        costm = cos_sigma - 2.0 * (sin_eta1 * sin_eta2 / PE_SGN(eps, cos2_azeq));
                    }
                    else
                    {
                        costm = cos_sigma - 2.0 * (sin_eta1 * sin_eta2 / cos2_azeq);
                    }
                    /* v18 (Rapp 1.91) */
                    costm2 = costm * costm;
                    continue;
                }
            }
            /* End of while q_continue_looping */
            /* Convergence */
            if (p_dist != null)
            {
                /*
                 * Helmert 1880 from Vincenty's
                 * "Geodetic inverse solution between antipodal points"
                 */
                ep2  = 1.0 / (boa * boa) - 1.0;
                bige = System.Math.Sqrt(1.0 + ep2 * cos2_azeq);
                /* 15 */
                bigf = (bige - 1.0) / (bige + 1.0);
                /* 16 */
                biga = (1.0 + bigf * bigf / 4.0) / (1.0 - bigf);
                /* 17 */
                bigb = bigf * (1.0 - 0.375 * bigf * bigf);
                /* 18 */
                z      = bigb / 6.0 * costm * (-3.0 + 4.0 * sin_sigma * sin_sigma) * (-3.0 + 4.0 * costm2);
                dsigma = bigb * sin_sigma * (costm + bigb / 4.0 * (cos_sigma * (-1.0 + 2.0 * costm2) - z));
                /* 19 */
                dist = (boa * a) * biga * (sigma - dsigma);
                /* 20 */
                p_dist.val = dist;
            }
            if (p_az12 != null || p_az21 != null)
            {
                if (kind == 2)
                {
                    /* antipodal */
                    az12 = sin_azeq / cos_eta1;
                    az21 = System.Math.Sqrt(1.0 - az12 * az12);
                    if (temp < 0.0)
                    {
                        az21 = -az21;
                    }
                    az12 = System.Math.Atan2(az12, az21);
                    tem1 = -sin_azeq;
                    tem2 = sin_eta1 * sin_sigma - cos_eta1 * cos_sigma * az21;
                    az21 = System.Math.Atan2(tem1, tem2);
                }
                else
                {
                    /* long-line */
                    tem1 = cos_eta2 * sin_lam_sph;
                    tem2 = cos_eta1 * sin_eta2 - sin_eta1 * cos_eta2 * cos_lam_sph;
                    az12 = System.Math.Atan2(tem1, tem2);
                    tem1 = -cos_eta1 * sin_lam_sph;
                    tem2 = sin_eta1 * cos_eta2 - cos_eta1 * sin_eta2 * cos_lam_sph;
                    az21 = System.Math.Atan2(tem1, tem2);
                }
                if (p_az12 != null)
                {
                    p_az12.val = Lam_delta(az12);
                }
                if (p_az21 != null)
                {
                    p_az21.val = Lam_delta(az21);
                }
            }
        }