Example #1
0
        /// <summary>
        /// Returns new geodetic coordinate in radians
        /// </summary>
        /// <param name="lat1">Latitude in radians</param>
        /// <param name="lon1">Longitude in radians</param>
        /// <param name="crs12">Bearing</param>
        /// <param name="d12">Distance</param>
        /// <returns>double[]</returns>
        public static double[] Direct(double lat1, double lon1, double crs12, double d12)
        {
            lon1 *= -1;                 //REVERSE LONG FOR CALC 2.1.1.1
            var    EPS = 0.00000000005; //Used to determine if near pole.
            double dlon, lat, lon;

            d12 = d12 * 0.0005399565;         //convert meter to nm
            d12 = d12 / (180 * 60 / Math.PI); //Convert to Radian
            //Determine if near pole
            if ((Math.Abs(Math.Cos(lat1)) < EPS) && !(Math.Abs(Math.Sin(crs12)) < EPS))
            {
                Debug.WriteLine("Warning: Location is at earth's pole. Only N-S courses are meaningful at this location.");
            }

            lat = Math.Asin(Math.Sin(lat1) * Math.Cos(d12) +
                            Math.Cos(lat1) * Math.Sin(d12) * Math.Cos(crs12));
            if (Math.Abs(Math.Cos(lat)) < EPS)
            {
                lon = 0.0; //endpoint a pole
            }
            else
            {
                dlon = Math.Atan2(Math.Sin(crs12) * Math.Sin(d12) * Math.Cos(lat1),
                                  Math.Cos(d12) - Math.Sin(lat1) * Math.Sin(lat));
                lon = ModM.Mod(lon1 - dlon + Math.PI, 2 * Math.PI) - Math.PI;
            }

            return(new double[] { lat, lon });
        }
Example #2
0
        /// <summary>
        /// Returns new geodetic coordinate in radians
        /// </summary>
        /// <param name="glat1">Latitude in Radians</param>
        /// <param name="glon1">Longitude in Radians</param>
        /// <param name="faz">Bearing</param>
        /// <param name="s">Distance</param>
        /// <param name="ellipse">Earth Ellipse Values</param>
        /// <returns>double[]</returns>
        public static double[] Direct_Ell(double glat1, double glon1, double faz, double s, double[] ellipse)
        {
            glon1 *= -1;                //REVERSE LONG FOR CALC 2.1.1.1
            double EPS = 0.00000000005; //Used to determine if starting at pole.
            double r, tu, sf, cf, b, cu, su, sa, c2a, x, c, d, y, sy = 0, cy = 0, cz = 0, e = 0;
            double glat2, glon2, f;

            //Determine if near pole
            if ((Math.Abs(Math.Cos(glat1)) < EPS) && !(Math.Abs(Math.Sin(faz)) < EPS))
            {
                Debug.WriteLine("Warning: Location is at earth's pole. Only N-S courses are meaningful at this location.");
            }


            double a = ellipse[0]; //Equitorial Radius

            f  = 1 / ellipse[1];   //Flattening
            r  = 1 - f;
            tu = r * Math.Tan(glat1);
            sf = Math.Sin(faz);
            cf = Math.Cos(faz);
            if (cf == 0)
            {
                b = 0.0;
            }
            else
            {
                b = 2.0 * Math.Atan2(tu, cf);
            }
            cu  = 1.0 / Math.Sqrt(1 + tu * tu);
            su  = tu * cu;
            sa  = cu * sf;
            c2a = 1 - sa * sa;
            x   = 1.0 + Math.Sqrt(1.0 + c2a * (1.0 / (r * r) - 1.0));
            x   = (x - 2.0) / x;
            c   = 1.0 - x;
            c   = (x * x / 4.0 + 1.0) / c;
            d   = (0.375 * x * x - 1.0) * x;
            tu  = s / (r * a * c);
            y   = tu;
            c   = y + 1;
            while (Math.Abs(y - c) > EPS)
            {
                sy = Math.Sin(y);
                cy = Math.Cos(y);
                cz = Math.Cos(b + y);
                e  = 2.0 * cz * cz - 1.0;
                c  = y;
                x  = e * cy;
                y  = e + e - 1.0;
                y  = (((sy * sy * 4.0 - 3.0) * y * cz * d / 6.0 + x) *
                      d / 4.0 - cz) * sy * d + tu;
            }

            b = cu * cy * cf - su * sy;
            c = r * Math.Sqrt(sa * sa + b * b);
            d = su * cy + cu * sy * cf;

            glat2 = ModM.ModLat(Math.Atan2(d, c));
            c     = cu * cy - su * sy * cf;
            x     = Math.Atan2(sy * sf, c);
            c     = ((-3.0 * c2a + 4.0) * f + 4.0) * c2a * f / 16.0;
            d     = ((e * cy * c + cz) * sy * c + y) * sa;
            glon2 = ModM.ModLon(glon1 + x - (1.0 - c) * d * f);  //Adjust for IDL
            //baz = ModM.ModCrs(Math.Atan2(sa, b) + Math.PI);
            return(new double[] { glat2, glon2 });
        }
Example #3
0
        public static double[] Dist_Ell(double glat1, double glon1, double glat2, double glon2, double[] ellipse)
        {
            double a = ellipse[0];     //Equitorial Radius
            double f = 1 / ellipse[1]; //Flattening

            double r, tu1, tu2, cu1, su1, cu2, s1, b1, f1;
            double x = 0, sx = 0, cx = 0, sy = 0, cy = 0, y = 0, sa = 0, c2a = 0, cz = 0, e = 0, c = 0, d = 0;
            double EPS = 0.00000000005;
            double faz, baz, s;
            double iter    = 1;
            double MAXITER = 100;

            if ((glat1 + glat2 == 0.0) && (Math.Abs(glon1 - glon2) == Math.PI))
            {
                Debug.WriteLine("Warning: Course and distance between antipodal points is undefined");
                glat1 = glat1 + 0.00001; // allow algorithm to complete
            }
            if (glat1 == glat2 && (glon1 == glon2 || Math.Abs(Math.Abs(glon1 - glon2) - 2 * Math.PI) < EPS))
            {
                Debug.WriteLine("Warning: Points 1 and 2 are identical- course undefined");
                //D
                //crs12
                //crs21
                return(new double[] { 0, 0, Math.PI });
            }
            r   = 1 - f;
            tu1 = r * Math.Tan(glat1);
            tu2 = r * Math.Tan(glat2);
            cu1 = 1.0 / Math.Sqrt(1.0 + tu1 * tu1);
            su1 = cu1 * tu1;
            cu2 = 1.0 / Math.Sqrt(1.0 + tu2 * tu2);
            s1  = cu1 * cu2;
            b1  = s1 * tu2;
            f1  = b1 * tu1;
            x   = glon2 - glon1;
            d   = x + 1; // force one pass
            while ((Math.Abs(d - x) > EPS) && (iter < MAXITER))
            {
                iter = iter + 1;
                sx   = Math.Sin(x);
                cx   = Math.Cos(x);
                tu1  = cu2 * sx;
                tu2  = b1 - su1 * cu2 * cx;
                sy   = Math.Sqrt(tu1 * tu1 + tu2 * tu2);
                cy   = s1 * cx + f1;
                y    = Math.Atan2(sy, cy);
                sa   = s1 * sx / sy;
                c2a  = 1 - sa * sa;
                cz   = f1 + f1;
                if (c2a > 0.0)
                {
                    cz = cy - cz / c2a;
                }
                e = cz * cz * 2.0 - 1.0;
                c = ((-3.0 * c2a + 4.0) * f + 4.0) * c2a * f / 16.0;
                d = x;
                x = ((e * cy * c + cz) * sy * c + y) * sa;
                x = (1.0 - c) * x * f + glon2 - glon1;
            }
            faz = ModM.ModCrs(Math.Atan2(tu1, tu2));
            baz = ModM.ModCrs(Math.Atan2(cu1 * sx, b1 * cx - su1 * cu2) + Math.PI);
            x   = Math.Sqrt((1 / (r * r) - 1) * c2a + 1);
            x  += 1;
            x   = (x - 2.0) / x;
            c   = 1.0 - x;
            c   = (x * x / 4.0 + 1.0) / c;
            d   = (0.375 * x * x - 1.0) * x;
            x   = e * cy;
            s   = ((((sy * sy * 4.0 - 3.0) * (1.0 - e - e) * cz * d / 6.0 - x) * d / 4.0 + cz) * sy * d + y) * c * a * r;

            if (Math.Abs(iter - MAXITER) < EPS)
            {
                Debug.WriteLine("Warning: Distance algorithm did not converge");
            }

            return(new double[] { s, faz, baz });
        }