Пример #1
0
        /// <summary>
        /// Решение обратной геодезической задачи на сфероиде
        /// </summary>
        private InverseProblemAnswer OrthodromicSpheroidDistance(Point coord1, Point coord2)
        {
            var ω = coord2.LonR - coord1.LonR;

            var cosSigma = Math.Sin(coord1.LatR) * Math.Sin(coord2.LatR) + Math.Cos(coord1.LatR) * Math.Cos(coord2.LatR) * Math.Cos(ω);

            double s;

            if (cosSigma < 0)
            {
                s = _ellipsoid.PolarRadius * (Math.PI - Math.Abs(Math.Acos(cosSigma)));
            }
            else if (Math.Abs(cosSigma - 1) < TOLERANCE)
            {
                s = 0;
            }
            else
            {
                s = _ellipsoid.PolarRadius * Math.Acos(cosSigma);
            }

            var a1 =
                Math.Atan(Math.Cos(coord2.LatR) * Math.Sin(ω) /
                          (Math.Cos(coord1.LatR) * Math.Sin(coord2.LatR) - Math.Sin(coord1.LatR) * Math.Cos(coord2.LatR) * Math.Cos(ω))) * 180 /
                Math.PI;
            var a2 =
                Math.Atan(Math.Cos(coord1.LatR) * Math.Sin(ω) /
                          (Math.Cos(coord1.LatR) * Math.Sin(coord2.LatR) * Math.Cos(ω) - Math.Sin(coord1.LatR) * Math.Cos(coord2.LatR))) * 180 /
                Math.PI;

            a1 = Azimuth.AzimuthRecovery(coord1, coord2, a1);
            a2 = Azimuth.AzimuthRecovery(coord2, coord1, a2);

            return(new InverseProblemAnswer(a1, a2, s));
        }
Пример #2
0
        /// <summary>
        /// Решение прямой геодезической задачи на сфероиде
        /// </summary>
        private DirectProblemAnswer DirectProblemSpheroid(Point coord, double a1, double s)
        {
            var aDegree = a1;

            a1 = a1 * Math.PI / 180;
            var lat1 = coord.LatR;

            var sigma = s / _ellipsoid.PolarRadius;
            var lat2  = Math.Asin(Math.Sin(lat1) * Math.Cos(sigma) + Math.Cos(lat1) * Math.Sin(sigma) * Math.Cos(a1));

            var lambda = Math.Atan(Math.Sin(sigma) * Math.Sin(a1) /
                                   (Math.Cos(sigma) * Math.Cos(lat1) - Math.Sin(sigma) * Math.Sin(lat1) * Math.Cos(a1)));
            var lon2 = -lambda + coord.LonR;

            var a2 = -Math.Atan(Math.Cos(lat1) * Math.Sin(a1) /
                                (Math.Cos(lat1) * Math.Cos(sigma) * Math.Cos(a1) - Math.Sin(lat1) * Math.Sin(sigma))) *
                     180 / Math.PI;


            lon2 = lon2 * 180 / Math.PI;
            lat2 = lat2 * 180 / Math.PI;

            var point1 = IsPolisIntersect(coord, aDegree, s)
                ? new Point(lon2 + (lon2 < 0 ? 180 : -180), lat2)
                : new Point(lon2, lat2);

            a2 = Azimuth.AzimuthRecovery(point1, new Point(coord.Longitude, lat1 * 180 / Math.PI), a2);

            return(new DirectProblemAnswer(point1, a2));
        }
Пример #3
0
        /// <summary>
        /// Решение обратной геодезической задачи на элипсоиде
        /// </summary>
        private InverseProblemAnswer OrthodromicEllipsoidDistance(Point coord1, Point coord2)
        {
            double l = coord2.LonR - coord1.LonR;                              // Разность геодезических долгот

            double u1 = Math.Atan((1 - _ellipsoid.F) * Math.Tan(coord1.LatR)); // Приведённая широта
            double u2 = Math.Atan((1 - _ellipsoid.F) * Math.Tan(coord2.LatR));
            double sinU1 = Math.Sin(u1), cosU1 = Math.Cos(u1);
            double sinU2 = Math.Sin(u2), cosU2 = Math.Cos(u2);

            double lambda = l, lambdaP;
            double cosSqAlpha, sinSigma, cosSigma, cos2SigmaM, sigma;
            int    iterLimit = 100;

            do
            {
                var sinLambda = Math.Sin(lambda);
                var cosLambda = Math.Cos(lambda);

                sinSigma =
                    Math.Sqrt(Math.Pow(cosU2 * sinLambda, 2) + Math.Pow(cosU1 * sinU2 - sinU1 * cosU2 * cosLambda, 2));

                if (Math.Abs(sinSigma) < TOLERANCE)
                {
                    return(new InverseProblemAnswer(0, 0, 0));
                }

                cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
                sigma    = Math.Atan(sinSigma / cosSigma);
                var sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
                cosSqAlpha = 1 - sinAlpha * sinAlpha;

                if (Math.Abs(cosSqAlpha) > TOLERANCE)
                {
                    cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;
                }
                else
                {
                    cos2SigmaM = 0;
                }

                double c = _ellipsoid.F / 16 * cosSqAlpha * (4 + _ellipsoid.F * (4 - 3 * cosSqAlpha));
                lambdaP = lambda;
                lambda  = l +
                          (1 - c) * _ellipsoid.F * sinAlpha *
                          (sigma + c * sinSigma * (cos2SigmaM + c * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
            } while (Math.Abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0);

            double uSq = cosSqAlpha * (Math.Pow(_ellipsoid.EquatorialRadius, 2) - Math.Pow(_ellipsoid.PolarRadius, 2)) /
                         Math.Pow(_ellipsoid.PolarRadius, 2);
            double a          = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
            double b          = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
            double deltaSigma = b * sinSigma *
                                (cos2SigmaM +
                                 b / 4 *
                                 (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -
                                  b / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) *
                                  (-3 + 4 * cos2SigmaM * cos2SigmaM)));
            double s = _ellipsoid.PolarRadius * a * (sigma - deltaSigma);

            var a1 = Math.Atan(cosU2 * Math.Sin(lambda) / (cosU1 * sinU2 - sinU1 * cosU2 * Math.Cos(lambda))) * 180 /
                     Math.PI;
            var a2 = Math.Atan(cosU1 * Math.Sin(lambda) / (-sinU1 * cosU2 + cosU1 * sinU2 * Math.Cos(lambda))) * 180 /
                     Math.PI;

            a1 = Azimuth.AzimuthRecovery(coord1, coord2, a1);
            a2 = Azimuth.AzimuthRecovery(coord2, coord1, a2);

            return(new InverseProblemAnswer(a1, a2, s));
        }
Пример #4
0
        /// <summary>
        /// Решение прямой геодезической задачи на эллипсоиде
        /// </summary>
        private DirectProblemAnswer DirectProblemEllipsoid(Point coord, double a1, double s)
        {
            var aDegree = a1;

            a1 = a1 * Math.PI / 180;

            double u1       = Math.Atan((1 - _ellipsoid.F) * Math.Tan(coord.LatR));
            double sigma1   = Math.Atan(Math.Tan(u1) / Math.Cos(a1));
            var    sinAlpha = Math.Cos(u1) * Math.Sin(a1);

            var cosSqAlpha = 1 - sinAlpha * sinAlpha;

            double uSq = cosSqAlpha * (Math.Pow(_ellipsoid.EquatorialRadius, 2) - Math.Pow(_ellipsoid.PolarRadius, 2)) /
                         Math.Pow(_ellipsoid.PolarRadius, 2);
            double a = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
            double b = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));

            var    si    = s / _ellipsoid.PolarRadius / a;
            double sigma = si;

            double sigmaP, cos2SigmaM;

            do
            {
                var sinSigma = Math.Sin(sigma);
                var cosSigma = Math.Cos(sigma);

                cos2SigmaM = Math.Cos(2 * sigma1 + sigma);
                double deltaSigma = b * sinSigma *
                                    (cos2SigmaM +
                                     b / 4 *
                                     (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -
                                      b / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) *
                                      (-3 + 4 * cos2SigmaM * cos2SigmaM)));
                sigmaP = sigma;
                sigma  = si + deltaSigma;
            } while (Math.Abs(sigma - sigmaP) > 1e-12);

            var sinU2 = Math.Sin(u1) * Math.Cos(sigma) + Math.Cos(u1) * Math.Sin(sigma) * Math.Cos(a1);
            var lat2  = sinU2 /
                        ((1 - _ellipsoid.F) *
                         Math.Sqrt(sinAlpha * sinAlpha +
                                   Math.Pow(
                                       Math.Sin(u1) * Math.Sin(sigma) - Math.Cos(u1) * Math.Cos(sigma) * Math.Cos(a1), 2)));

            lat2 = Math.Atan(lat2);

            // Разность долгот
            var lamda = Math.Atan(Math.Sin(sigma) * Math.Sin(a1) /
                                  (Math.Cos(u1) * Math.Cos(sigma) - Math.Sin(u1) * Math.Sin(sigma) * Math.Cos(a1)));

            double c = _ellipsoid.F / 16 * cosSqAlpha * (4 + _ellipsoid.F * (4 - 3 * cosSqAlpha));

            var l = lamda - (1 - c) * _ellipsoid.F * sinAlpha *
                    (sigma +
                     c * Math.Sin(sigma) * (cos2SigmaM + c * Math.Cos(sigma) * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
            var lon2 = -l + coord.LonR;

            lon2 = lon2 * 180 / Math.PI;
            lat2 = lat2 * 180 / Math.PI;

            var point1 = IsPolisIntersect(coord, aDegree, s)
                ? new Point(lon2 + (lon2 < 0 ? 180 : -180), lat2)
                : new Point(lon2, lat2);

            var a2 = -Math.Atan(sinAlpha / (-Math.Sin(u1) * Math.Sin(sigma) + Math.Cos(u1) * Math.Cos(sigma) * Math.Cos(a1))) * 180 / Math.PI;

            a2 = Azimuth.AzimuthRecovery(point1, coord, a2);

            return(new DirectProblemAnswer(point1, a2));
        }