/// <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)); }
/// <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)); }
/// <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 }; }
/// <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)); }
/// <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 }); }
/// <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); } }