Пример #1
0
        /// <summary>
        /// 解析字符串为实例。
        /// </summary>
        /// <param name="toString"></param>
        /// <returns></returns>
        public static new GeoCoord Parse(string toString,
                                         AngleUnit from          = AngleUnit.Degree,
                                         AngleUnit to            = AngleUnit.Degree,
                                         AngleUnit fromDegFormat = AngleUnit.Degree)
        {
            toString = toString.Replace("(", "").Replace(")", "");
            string[] spliters = new string[] { ",", "\t", " " };
            string[] strs     = toString.Split(spliters, StringSplitOptions.RemoveEmptyEntries);

            double lon = double.Parse(strs[0]);
            double lat = double.Parse(strs[1]);

            if (from == AngleUnit.Degree)//转换为标准的度小数再说。
            {
                lon = AngularConvert.ConvertDegree(lon, fromDegFormat);
                lat = AngularConvert.ConvertDegree(lat, fromDegFormat);
            }

            lon = AngularConvert.Convert(lon, from, to);
            lat = AngularConvert.Convert(lat, from, to);

            double h = 0;

            if (strs.Length > 2)
            {
                h = double.Parse(strs[2]);
            }
            return(new GeoCoord(lon, lat, h));
        }
Пример #2
0
        /// <summary>
        /// 旋转方位角
        /// </summary>
        /// <param name="val"></param>
        /// <param name="unit"></param>
        /// <returns></returns>
        public PlanePolar RotateAzimuth(double val, AngleUnit unit = AngleUnit.Degree)
        {
            if (this.Unit != unit)
            {
                val = AngularConvert.Convert(val, unit, this.Unit);
            }
            double azimuth = Azimuth + val;

            return(new PlanePolar(Range, azimuth));
        }
Пример #3
0
        /// <summary>
        /// 计算日固坐标系下的经纬度
        /// </summary>
        /// <param name="dateTimeUtc"></param>
        /// <returns></returns>
        public LonLat GetSeLonLat(DateTime dateTimeUtc)
        {
            double lon   = AngularConvert.ToRad(Lon, this.Unit);
            double utRad = Geo.Times.Time.DateTimeToRad(dateTimeUtc);

            lon = lon + utRad - Math.PI;
            lon = AngularConvert.RadTo(lon, this.Unit);

            return(new LonLat(lon, Lat, this.Unit));
        }
Пример #4
0
        /// <summary>
        /// Sphere to XYZ Coordinate
        /// </summary>
        /// <param name="lon"></param>
        /// <param name="lat"></param>
        /// <param name="r"></param>
        /// <returns></returns>
        public static XYZ SphereToXyz(double lon, double lat, double r, AngleUnit unit = AngleUnit.Degree)
        {
            lon = AngularConvert.ToRad(lon, unit);
            lat = AngularConvert.ToRad(lat, unit);

            double x = r * Cos(lat) * Cos(lon);
            double y = r * Cos(lat) * Sin(lon);
            double z = r * Sin(lat);

            return(new XYZ(x, y, z));
        }
Пример #5
0
        /// <summary>
        /// 由空间直角坐标转换为椭球坐标。默认角度单位为度。
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="z"></param>
        /// <param name="a"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        public static GeoCoord XyzToGeoCoord(double x, double y, double z, double a, double e, AngleUnit angeUnit = AngleUnit.Degree)
        {
            double ee  = e * e;
            double lon = Math.Atan2(y, x);
            double lat;
            double height;

            //iteration
            double deltaZ  = 0;
            double sqrtXy  = Math.Sqrt(x * x + y * y);
            double tempLat = Math.Atan2(z, sqrtXy);//初始取值

            lat = tempLat;
            //if (Math.Abs(lat) > 80.0 * CoordConverter.DegToRadMultiplier)//lat=+-90,或height特大时,采用此算法更稳定(实际有待实验,保留both代码)
            //{
            int count = 0;//避免死循环

            do
            {
                var sinLat = Sin(lat);
                deltaZ  = a * ee * sinLat / Math.Sqrt(1 - Math.Pow(e * sinLat, 2));
                tempLat = lat;
                lat     = Math.Atan2(z + deltaZ, sqrtXy);
                count++;
            } while (Math.Abs(lat - tempLat) > 1E-12 || count < 20);
            //}
            //else//经典算法
            //{
            //    do
            //    {
            //        double tanB = Math.Tan(lat);
            //        tempLat = lat;
            //        lat = Math.Atan2(z + a * ee * tanB / Math.Sqrt(1 + tanB * tanB * (1 - ee)), sqrtXy);
            //    } while (Math.Abs(lat - tempLat) > 1E-12);
            //}

            double n = a / Math.Sqrt(1 - Math.Pow(e * Sin(tempLat), 2));

            //double   height = Math.Sqrt(x * x + y * y + Math.Pow((z + deltaZ), 2)) - n;

            height = sqrtXy / Cos(lat) - n;

            //地心纬度
            //double dixinLat = (1 - ee * n / (n + height)) * Math.Tan(lat);
            //double dixinLatDeg = dixinLat * CoordConverter.RadToDegdMultiplier;


            lon = AngularConvert.RadTo(lon, angeUnit);
            lat = AngularConvert.RadTo(lat, angeUnit);

            return(new GeoCoord(lon, lat, height));
        }
Пример #6
0
        /// <summary>
        /// XYZ to Sphere Coordinate
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="z"></param>
        /// <returns></returns>
        public static SphereCoord XyzToSphere(double x, double y, double z, AngleUnit unit = AngleUnit.Degree)
        {
            double radius = Math.Sqrt(x * x + y * y + z * z);
            double lon    = Math.Atan2(y, x);
            double lat    = Math.Atan2(z, Math.Sqrt(x * x + y * y));

            lon = AngularConvert.RadTo(lon, unit);
            lat = AngularConvert.RadTo(lat, unit);

            SphereCoord sphere = new SphereCoord(lon, lat, radius);

            return(sphere);
        }
Пример #7
0
        /// <summary>
        /// 极坐标系到同心空间直角坐标系。
        /// </summary>
        /// <param name="p">极坐标</param>
        /// <returns></returns>
        public static NEU PolarToNeu(Polar p)
        {
            double ele = AngularConvert.ToRad(p.Elevation, p.Unit);
            double azi = AngularConvert.ToRad(p.Azimuth, p.Unit);

            double n = p.Range * Cos(ele) * Cos(azi);
            double e = p.Range * Cos(ele) * Sin(azi);
            double u = p.Range * Sin(ele);

            return(new NEU()
            {
                E = e, N = n, U = u
            });
        }
Пример #8
0
        /// <summary>
        /// 空间极坐标系到空间直角坐标系
        /// </summary>
        /// <param name="polar"></param>
        /// <param name="unit">角度单位</param>
        /// <returns></returns>
        public static XYZ PolarToXyz(Polar polar, AngleUnit unit = AngleUnit.Degree)
        {
            double radius      = polar.Range;
            double elevatAngle = polar.Zenith;
            double azimuth     = polar.Azimuth;

            elevatAngle = AngularConvert.ToRad(elevatAngle, polar.Unit);
            azimuth     = AngularConvert.ToRad(azimuth, polar.Unit);

            double x = radius * (Cos(elevatAngle) + Cos(azimuth));
            double y = radius * (Cos(elevatAngle) + Sin(azimuth));
            double z = radius * Sin(elevatAngle);

            return(new XYZ(x, y, z));
        }
Пример #9
0
        /// <summary>
        /// 经纬度转换到高斯坐标XY
        /// </summary>
        /// <param name="lonlat"></param>
        /// <param name="beltWidth"></param>
        /// <param name="Ellipsoid"></param>
        /// <param name="unit"></param>
        /// <param name="aveGeoHeight">投影面平均大地高</param>
        /// <param name="YConst">横轴Y加常数</param>
        /// <param name="orinalLonDeg">中央子午线,度小数</param>
        /// <param name="isYWithBeltNum"></param>
        /// <returns></returns>
        public static XY LonLatToGaussXy(LonLat lonlat, double aveGeoHeight, int beltWidth, ref double orinalLonDeg, bool IsIndicateOriginLon, Ellipsoid Ellipsoid, double YConst = 500000, AngleUnit unit = AngleUnit.Degree, bool isYWithBeltNum = true)
        {
            double B = lonlat.Lat;
            double L = lonlat.Lon;
            double x;
            double y;

            //单位转换
            L = AngularConvert.Convert(L, unit, AngleUnit.Degree);
            B = AngularConvert.Convert(B, unit, AngleUnit.Degree);
            Geo.Coordinates.GeodeticUtils.LonLatToGaussXy(L, B, aveGeoHeight, out x, out y, ref orinalLonDeg, IsIndicateOriginLon, beltWidth, YConst, isYWithBeltNum,
                                                          Ellipsoid.SemiMajorAxis, Ellipsoid.InverseFlattening);

            return(new XY(x, y));
        }
Пример #10
0
        /// <summary>
        ///  计算卫星的站心极坐标,基于当前测站的大地坐标,即高度角基于椭球表面,当前经度为0时,请直接调用 lon lat
        /// </summary>
        /// <param name="satXyz">卫星的地心空间直角坐标</param>
        /// <param name="stationPosition">测站的地心空间直角坐标</param>
        /// <param name="unit">角度单位,表示输出的角度单位</param>
        /// <returns></returns>
        public static Polar XyzToGeoPolar(XYZ satXyz, XYZ stationPosition, AngleUnit unit = AngleUnit.Degree)
        {
            double lat, lon, h;

            //计算站点坐标的经纬度,此法为度为单位,by Zhao Dongqing
            GeodeticX.Geodetic.XYZ_BLH(stationPosition.X, stationPosition.Y, stationPosition.Z, out lat, out lon, out h,
                                       Geo.Referencing.Ellipsoid.WGS84.SemiMajorAxis, Geo.Referencing.Ellipsoid.WGS84.InverseFlattening);

            if (unit != AngleUnit.Degree)
            {
                lat = AngularConvert.Convert(lat, AngleUnit.Degree, unit);
                lon = AngularConvert.Convert(lon, AngleUnit.Degree, unit);
            }
            return(XyzToPolar(satXyz, stationPosition, lon, lat, unit));
        }
Пример #11
0
        /// <summary>
        ///  空间直角坐标系到,站心坐标系的转换。默认B L 单位 度,可以为球坐标和大地坐标
        ///  地心空间直角坐标系(XYZ)转换为地方左手笛卡尔直角坐标系(NEU,XYZ)
        /// </summary>
        /// <param name="vector1">测站到卫星的向径</param>
        /// <param name="lat">站点所在纬度</param>
        /// <param name="lon">站点所在经度</param>
        /// <param name="angleUnit">站点所在经度的单位</param>
        /// <returns></returns>
        public static NEU XyzToNeu(XYZ vector1, double lat, double lon, AngleUnit angleUnit = AngleUnit.Degree)
        {
            if (angleUnit != AngleUnit.Radian) //当前经度为 0 的时候,U 的转换会出现符号错误???!!!2017.10.12.
            {
                lat = AngularConvert.ToRad(lat, angleUnit);
                lon = AngularConvert.ToRad(lon, angleUnit);
            }

            XYZ v = vector1;

            double n = -v.X * Sin(lat) * Cos(lon) - v.Y * Sin(lat) * Sin(lon) + v.Z * Cos(lat);
            double e = -v.X * Sin(lon) + v.Y * Cos(lon);
            double u = v.X * Cos(lat) * Cos(lon) + v.Y * Cos(lat) * Sin(lon) + v.Z * Sin(lat);

            return(new NEU(n, e, u));// { N = n, E = e, U = u };
        }
Пример #12
0
        /// <summary>
        /// 平面坐标(自然坐标或假定坐标)到大地坐标的高斯反算
        /// </summary>
        /// <param name="xy">x为横轴</param>
        /// <param name="a"></param>
        /// <param name="YConst">横轴Y加常数</param>
        /// <param name="InverseFlat ">参考椭球扁率倒数</param>
        /// <param name="beltWidth">6、3</param>
        /// <param name="aveGeoHeight">投影面大地高</param>
        /// <param name="unit">输出角度的单位</param>
        /// <param name="originLon_deg">中央子午线,度</param>
        /// <returns></returns>
        public static LonLat GaussXyToLonLat(XY xy, double aveGeoHeight, int beltWidth, double originLon_deg, double YConst,
                                             double a = Ellipsoid.SemiMajorAxisOfCGCS2000, double InverseFlat = Ellipsoid.InverseFlatOfCGCS2000, AngleUnit unit = AngleUnit.Degree)
        {
            double B;
            double L;
            double x = xy.X;
            double y = xy.Y;

            var lonlat = GeodeticUtils.GaussXyToLonLat(xy, aveGeoHeight, originLon_deg, YConst, a, InverseFlat);

            //GeodeticX.Geodetic.xy_BL(x, y, out B, out L, beltWidth, beltNum, a, InverseFlat );
            //单位转换
            L = AngularConvert.Convert(lonlat.Lon, AngleUnit.Degree, unit);
            B = AngularConvert.Convert(lonlat.Lat, AngleUnit.Degree, unit);

            return(new LonLat(L, B));
        }
Пример #13
0
        /// <summary>
        /// 空间直角坐标到极坐标
        /// </summary>
        /// <param name="xyz"></param>
        /// <param name="unit">角度单位</param>
        /// <returns></returns>
        public static Polar XyzToPolar(XYZ xyz, AngleUnit unit = AngleUnit.Degree)
        {
            double x = xyz.X;
            double y = xyz.Y;
            double z = xyz.Z;

            double radius  = Math.Sqrt(x * x + y * y + z * z);
            double azimuth = Math.Atan2(y, x);

            if (azimuth < 0)
            {
                azimuth += 2.0 * CoordConsts.PI;
            }
            double elevatAngle = Math.Atan2(z, Math.Sqrt(x * x + y * y));

            azimuth     = AngularConvert.RadTo(azimuth, unit);
            elevatAngle = AngularConvert.RadTo(elevatAngle, unit);

            return(new Polar(radius, azimuth, elevatAngle, unit));
        }
Пример #14
0
        /// <summary>
        /// 椭球坐标转为空间直角坐标。默认单位为度。
        /// </summary>
        /// <param name="lon">经度(度)</param>
        /// <param name="lat">纬度(度)</param>
        /// <param name="height">大地高</param>
        /// <param name="a">椭球半径</param>
        /// <param name="flatOrInverse">扁率或其倒数</param>
        /// <param name="unit">单位</param>
        /// <returns></returns>
        public static XYZ GeoCoordToXyz(double lon, double lat, double height, double a, double flatOrInverse, AngleUnit unit = AngleUnit.Degree)
        {
            lon = AngularConvert.ToRad(lon, unit);
            lat = AngularConvert.ToRad(lat, unit);

            //扁率判断
            double e = flatOrInverse;

            if (flatOrInverse > 1)
            {
                e = 1.0 / e;
            }

            double n = a / Math.Sqrt(1 - Math.Pow(e * Sin(lat), 2));

            double x = (n + height) * Cos(lat) * Cos(lon);
            double y = (n + height) * Cos(lat) * Sin(lon);
            double z = (n * (1 - e * e) + height) * Sin(lat);

            return(new XYZ(x, y, z));
        }
Пример #15
0
        /// <summary>
        /// 站心坐标系到站心极坐标系。
        /// </summary>
        /// <param name="neu"></param>
        /// <param name="unit">默认单位为度</param>
        /// <returns></returns>
        public static Polar NeuToPolar(NEU neu, AngleUnit unit = AngleUnit.Degree)
        {
            double r = neu.Length;
            double a = Math.Atan2(neu.E, neu.N);

            if (a < 0)//以北向为基准,顺时针,无负号
            {
                a += 2.0 * CoordConsts.PI;
            }

            double o = Math.Asin(neu.U / r);

            if (unit != AngleUnit.Radian)
            {
                a = AngularConvert.RadTo(a, unit);
                o = AngularConvert.RadTo(o, unit);
            }
            return(new Polar(r, a, o)
            {
                Unit = unit
            });
        }
Пример #16
0
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="dval"></param>
        /// <param name="degreeFormat"></param>
        public DMS(double dval, AngleUnit degreeFormat)
        {
            switch (degreeFormat)
            {
            case AngleUnit.Radian:
                InitDegree(AngularConvert.RadToDeg(dval));
                break;

            case AngleUnit.Degree:
                InitDegree(dval);
                break;

            case AngleUnit.DMS_S:
            {
                this.IsPlus = dval > 0;
                double d         = Math.Abs(dval);
                var    str       = d.ToString("0.00000000000");
                var    indexOfPt = str.IndexOf(".");

                if (indexOfPt > 4)
                {
                    var degr = str.Substring(0, indexOfPt - 4);
                    this.Degree = int.Parse(degr);
                }
                if (indexOfPt > 2)
                {
                    var minStr = str.Substring(indexOfPt - 4, 2);
                    this.Minute = int.Parse(minStr);
                }
                var secStr = str.Substring(indexOfPt - 2);
                this.Second = Double.Parse(secStr);
            }
            break;

            case AngleUnit.D_MS:    //120.30300
            {
                this.IsPlus = dval > 0;
                double d         = Math.Abs(dval);
                var    str       = d.ToString("0.00000000000");
                var    indexOfPt = str.IndexOf(".");
                var    degr      = str.Substring(0, indexOfPt);
                this.Degree = int.Parse(degr);
                this.Minute = int.Parse(str.Substring(indexOfPt + 1, 2));
                var secStr = str.Substring(indexOfPt + 3, 2) + "." + str.Substring(indexOfPt + 5);
                this.Second = Double.Parse(secStr);
            }
            break;

            case AngleUnit.HMS_S:
            {
                this.IsPlus = dval > 0;
                double d         = Math.Abs(dval);
                var    str       = d.ToString("0.00000000000");
                var    indexOfPt = str.IndexOf(".");

                if (indexOfPt > 4)
                {
                    var degr = str.Substring(0, indexOfPt - 4);
                    this.Degree = int.Parse(degr) * 15;
                }
                if (indexOfPt > 2)
                {
                    var minStr = str.Substring(indexOfPt - 4, 2);
                    this.Minute = int.Parse(minStr);
                }
                var secStr = str.Substring(indexOfPt - 2);
                this.Second = Double.Parse(secStr);
            }
                //this.IsPlus = dval > 0;
                //double deg0 = Math.Abs(dval);
                //var hour = (int)(deg0 / 10000);
                //var minute = (int)((deg0) / 100.0) - Degree * 100;
                //var second = deg0 % 100;
                //var hours = hour + minute / 60.0 + second / 3600.0;

                //var degs = hours * 15.0;
                //InitDegree(degs);
                break;

            default:
                throw new ArgumentException("暂不支持这种类型 " + degreeFormat);
            }
        }