예제 #1
0
        /// <summary>
        /// Computes the ellipsoid.
        /// </summary>
        /// <returns>The ellipsoid.</returns>
        /// <exception cref="System.IO.InvalidDataException">Prime meridian code is invalid.</exception>
        private Ellipsoid ComputeEllipsoid()
        {
            Int32 code = Convert.ToInt32(_currentGeoKeys[GeoKey.GeodeticEllipsoid]);

            // EPSG ellipsoid codes
            if (code >= 8000 && code <= 8999)
            {
                return(Ellipsoids.FromIdentifier("EPSG::" + code).FirstOrDefault());
            }
            // user-defined ellipsoid
            if (code == Int16.MaxValue)
            {
                Double semiMajorAxis = Convert.ToDouble(_currentGeoKeys[GeoKey.GeodeticSemiMajorAxis]);

                // either semi-minor axis or the inverse flattening is defined
                if (_currentGeoKeys.ContainsKey(GeoKey.GeodeticSemiMinorAxis))
                {
                    Double semiMinorAxis = Convert.ToDouble(_currentGeoKeys[2058]);
                    return(Ellipsoid.FromSemiMinorAxis(Ellipsoid.UserDefinedIdentifier, Ellipsoid.UserDefinedName, semiMajorAxis, semiMinorAxis));
                }
                else
                {
                    Double inverseFlattening = Convert.ToDouble(_currentGeoKeys[GeoKey.GeodeticInverseFlattening]);
                    return(Ellipsoid.FromInverseFlattening(Ellipsoid.UserDefinedIdentifier, Ellipsoid.UserDefinedName, semiMajorAxis, inverseFlattening));
                }
            }

            throw new InvalidDataException("Prime meridian code is invalid.");
        }
예제 #2
0
        /// <summary>
        /// 空间坐标转大地坐标
        /// </summary>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        /// <param name="Z"></param>
        /// <param name="ellipsoid"></param>
        /// <returns></returns>
        public static PointBLH TranslateXYZToBLH(double X, double Y, double Z, Ellipsoids ellipsoid)
        {
            Ellipsoid ellipsoidTemp = Ellipsoid.Instance(ellipsoid);
            double    ee = ellipsoidTemp.e * ellipsoidTemp.e;
            double    p = 180 / Math.PI;
            double    B, L, H;

            L = Math.Atan(Y / X);
            if (X < 0)
            {
                L += Math.PI;
            }
            double r = Math.Sqrt(X * X + Y * Y);
            double B1 = Math.Atan(Z / r);
            double B2;

            while (true)
            {
                double W1 = Math.Sqrt(1 - ee * (Math.Sin(B1) * Math.Sin(B1)));
                double N1 = ellipsoidTemp.a / W1;
                B2 = Math.Atan((Z + N1 * ee * Math.Sin(B1)) / r);
                if (Math.Abs(B2 - B1) <= 0.0000000001)
                {
                    break;
                }
                B1 = B2;
            }
            B = B2;
            double W = Math.Sqrt(1 - ee * (Math.Sin(B2) * Math.Sin(B2)));
            double N = ellipsoidTemp.a / W;

            H = r / Math.Cos(B2) - N;
            return(new PointBLH(B * p, L * p, H));
        }
예제 #3
0
        /// <summary>
        /// 大地坐标转空间坐标
        /// </summary>
        /// <param name="B"></param>
        /// <param name="L"></param>
        /// <param name="H"></param>
        /// <param name="ellipsoid"></param>
        /// <returns></returns>
        public static Point3D TranslateBLHToXYZ(double B, double L, double H, Ellipsoids ellipsoid)
        {
            double p = 180 / Math.PI;

            B = B / p;
            L = L / p;
            double    x = 0, y = 0, z = 0;
            Ellipsoid ellipsoidTemp = Ellipsoid.Instance(ellipsoid);
            double    ee            = ellipsoidTemp.e * ellipsoidTemp.e;
            double    N             = ellipsoidTemp.a / (Math.Sqrt(1 - (ee * Math.Sin(B) * Math.Sin(B))));

            x = (N + H) * Math.Cos(B) * Math.Cos(L);
            y = (N + H) * Math.Cos(B) * Math.Sin(L);
            z = (N * (1 - ee) + H) * Math.Sin(B);

            return(new Point3D(x, y, z));
        }
예제 #4
0
        /// <summary>
        /// Инициализирует новый экземпляр класса <see cref="Ellipsoid"/>.
        /// </summary>
        /// <param name="ell"> Имя эллипсоида из коллекции доступных эллипсоидов. </param>
        public Ellipsoid(Ellipsoids ell)
        {
            double[,] ellParams = new double[, ]
            {
                // Эллипсоид Красовского
                { 6378245.000, 298.3 },
                // Эллипсоид WGS 84
                { 6378137.000, 298.257223563 },
                // Эллипсоид ПЗ-90
                { 6378136.000, 298.25784 }
            };

            this.a = ellParams[(int)ell, 0];
            this.f = 1 / ellParams[(int)ell, 1];

            e1_2 = 1 - b * b / (a * a);
            e2_2 = a * a / (b * b) - 1;
        }
예제 #5
0
        /// <summary>
        /// 创建常用的标准椭球
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static Ellipsoid Instance(Ellipsoids ellipsoidstype)
        {
            switch (ellipsoidstype)
            {
            case Ellipsoids.XiAn1980:
                return(new Ellipsoid(6378140.0, 6356755.288157528));

            case Ellipsoids.CGCS2000:
                return(new Ellipsoid(6378137, 6356752.31414035615));

            case Ellipsoids.BeiJing1954:
                return(new Ellipsoid(6378245.0, 6356863.018773047));

            case Ellipsoids.WGS1984:
                return(new Ellipsoid(6378137, 6356752.3142451793));

            default:
                return(new Ellipsoid(6378137, 6356752.31414035615));
            }
        }
예제 #6
0
        /// <summary>
        /// 平面坐标转大地坐标,高斯反算(X值为横坐标,且不带带号)
        /// </summary>
        /// <param name="X">横坐标值(不带带号)</param>
        /// <param name="Y">纵坐标</param>
        /// <param name="ZoneWidth">带宽</param>
        /// <param name="longitude0">中央经度</param>
        /// <param name="ellipsoid">椭球</param>
        /// <returns></returns>
        public static PointBLH ProjectToBL(double X, double Y, double H, int ZoneWidth, double longitude0, Ellipsoids ellipsoid)
        {
            //对于有带号的坐标,去除带号(超过六位数,只取六位)
            if (X > 10000000)
            {
                X = X - X / 1000000 * 1000000;
            }

            Ellipsoid ellipsoidTemp = Ellipsoid.Instance(ellipsoid); //椭球
            double    longitude1, latitude1, X0, Y0;
            double    p = 180.0 / Math.PI;                           //弧度常数

            longitude0 = longitude0 / p;                             // 中央经线

            //带内起算坐标
            X0 = 500000;
            Y0 = 0;
            //带内坐标值
            double xval = X - X0;
            double yval = Y - Y0;

            //相关参数
            double e2 = 2 * ellipsoidTemp.f - ellipsoidTemp.f * ellipsoidTemp.f;
            double e1 = (1.0 - Math.Sqrt(1 - e2)) / (1.0 + Math.Sqrt(1 - e2));
            double ee = e2 / (1 - e2);
            double M  = yval;
            double u  = M / (ellipsoidTemp.a * (1 - e2 / 4 - 3 * e2 * e2 / 64 - 5 * e2 * e2 * e2 / 256));
            double bf = u + (3 * e1 / 2 - 27 * e1 * e1 * e1 / 32) * Math.Sin(2 * u) + (21 * e1 * e1 / 16 - 55 * e1 * e1 * e1 * e1 / 32) * Math.Sin(4 * u) + (151 * e1 * e1 * e1 / 96) * Math.Sin(6 * u) + (1097 * e1 * e1 * e1 * e1 / 512) * Math.Sin(8 * u);
            double C  = ee * Math.Cos(bf) * Math.Cos(bf);
            double T  = Math.Tan(bf) * Math.Tan(bf);
            double NN = ellipsoidTemp.a / Math.Sqrt(1.0 - e2 * Math.Sin(bf) * Math.Sin(bf));
            double R  = ellipsoidTemp.a * (1 - e2) / Math.Sqrt((1 - e2 * Math.Sin(bf) * Math.Sin(bf)) * (1 - e2 * Math.Sin(bf) * Math.Sin(bf)) * (1 - e2 * Math.Sin(bf) * Math.Sin(bf)));
            double D  = xval / NN;

            // 计算经度(Longitude) 纬度(Latitude)
            longitude1 = longitude0 + (D - (1 + 2 * T + C) * D * D * D / 6 + (5 - 2 * C + 28 * T - 3 * C * C + 8 * ee + 24 * T * T) * D * D * D * D * D / 120) / Math.Cos(bf);
            latitude1  = bf - (NN * Math.Tan(bf) / R) * (D * D / 2 - (5 + 3 * T + 10 * C - 4 * C * C - 9 * ee) * D * D * D * D / 24 + (61 + 90 * T + 298 * C + 45 * T * T - 256 * ee - 3 * C * C) * D * D * D * D * D * D / 720);

            // 弧度转换为度
            double L = longitude1 * p;
            double B = latitude1 * p;

            return(new PointBLH(B, L, H));
        }
예제 #7
0
        /// <summary>
        /// 大地坐标转平面坐标,高斯正算(输出X值为横坐标,且不带带号)
        /// </summary>
        /// <param name="B">纬度</param>
        /// <param name="L">经度</param>
        /// <param name="ZoneWidth">带宽</param>
        /// <param name="longitude0">中央经度</param>
        /// <returns></returns>
        public static Point2D ProjectToXY(double B, double L, double H, int ZoneWidth, double longitude0, Ellipsoids ellipsoid)
        {
            Ellipsoid ellipsoidTemp = Ellipsoid.Instance(ellipsoid);//椭球

            double longitude1, latitude1;
            double p = 180.0 / Math.PI;

            longitude0 = longitude0 / p;

            // 转换为弧度
            longitude1 = L / p;
            latitude1  = B / p;

            double e2 = 2 * ellipsoidTemp.f - ellipsoidTemp.f * ellipsoidTemp.f;
            double ee = e2 * (1.0 - e2);
            double NN = ellipsoidTemp.a / Math.Sqrt(1.0 - e2 * Math.Sin(latitude1) * Math.Sin(latitude1));
            double T  = Math.Tan(latitude1) * Math.Tan(latitude1);
            double C  = ee * Math.Cos(latitude1) * Math.Cos(latitude1);
            double A  = (longitude1 - longitude0) * Math.Cos(latitude1);
            double M  = ellipsoidTemp.a * ((1 - e2 / 4 - 3 * e2 * e2 / 64 - 5 * e2 * e2 * e2 / 256) * latitude1 - (3 * e2 / 8 + 3 * e2 * e2 / 32 + 45 * e2 * e2 * e2 / 1024) * Math.Sin(2 * latitude1) + (15 * e2 * e2 / 256 + 45 * e2 * e2 * e2 / 1024) * Math.Sin(4 * latitude1) - (35 * e2 * e2 * e2 / 3072) * Math.Sin(6 * latitude1));

            //计算x y坐标值
            double xval = NN * (A + (1 - T + C) * A * A * A / 6 + (5 - 18 * T + T * T + 72 * C - 58 * ee) * A * A * A * A * A / 120);
            double yval = M + NN * Math.Tan(latitude1) * (A * A / 2 + (5 - T + 9 * C + 4 * C * C) * A * A * A * A / 24 + (61 - 58 * T + T * T + 600 * C - 330 * ee) * A * A * A * A * A * A / 720);
            //起算坐标值
            double X0 = 500000;
            double Y0 = 0;

            xval = xval + X0;
            yval = yval + Y0;
            return(new Point2D(xval, yval, H));
        }