using DevExpress.Charts.Native; using DevExpress.XtraPrinting; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PosResAnalysis { /// /// 星历推算帮助类.该类调用了Tle2XYZ.exe进程 /// public static class EphHelper { private static readonly DateTime dtZero = new DateTime(1970, 1, 1, 0, 0, 0, 0); private static string exePath= "星历推算"; private const string exeName = "Tle2XYZ.exe"; /// /// 设置【Tle2XYZ.exe】文件所在路径,支持相对路径 /// public static void SetExePath(string path) { if (string.IsNullOrWhiteSpace(path)) return; if (path.StartsWith("\\"))//相对路径要么开头不带\,要么是 .\ path = path.Remove(0, 1); exePath = path; } /// /// 推算双行星历 /// /// 双行根数 /// 指定时刻(北京时间) /// public static SatEphDto Calc(string tleStr, DateTime dt) { if (string.IsNullOrWhiteSpace(exePath)) throw new Exception($"请先调用SetExePath指定{exeName}进程所在路径,支持相对路径"); if (!Directory.Exists(exePath)) throw new Exception($"路径[{exePath}]不存在"); var exeFile = Path.Combine(exePath, exeName); if (!File.Exists(exeFile)) throw new Exception($"文件[{exeFile}]不存在"); tleStr = tleStr.Replace(";", ";"); if (tleStr.EndsWith(";")) tleStr = tleStr.Substring(0, tleStr.Length - 1); tleStr = tleStr.Replace(";", ";"); var line1 = tleStr.Split(';')[0]; var line2 = tleStr.Split(';')[1]; var dtUtc = dt.AddHours(-8); var timeSpan = (long)(dtUtc - dtZero).TotalSeconds; Process p = new Process(); p.StartInfo.WorkingDirectory = exePath; p.StartInfo.FileName = exeFile; p.StartInfo.Arguments = $"-a \"{line1}\" -b \"{line2}\" -t {timeSpan} -p 1 -c 1"; p.StartInfo.CreateNoWindow = true; p.StartInfo.RedirectStandardError = true; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.UseShellExecute = false; p.Start(); var succeed = p.WaitForExit(10000); if (!succeed) { throw new Exception($"进程[{exeName}]超时未完成!"); } return ParseOneResult(p.StandardOutput.ReadToEnd()); } /// /// 批量推算双行星历 /// /// 双行根数 /// 起始时刻(北京) /// 结束(北京) /// 推算间隔(秒) /// public static List CalcMult(string tleStr, DateTime start, DateTime end, int spanSeconds) { if (string.IsNullOrWhiteSpace(exePath)) throw new Exception($"请先调用SetExePath指定{exeName}进程所在路径,支持相对路径"); if (!Directory.Exists(exePath)) throw new Exception($"路径[{exePath}]不存在"); var exeFile = Path.Combine(exePath, exeName); if (!File.Exists(exeFile)) throw new Exception($"文件[{exeFile}]不存在"); tleStr = tleStr.Replace(";", ";"); if (tleStr.EndsWith(";")) tleStr = tleStr.Substring(0, tleStr.Length - 1); tleStr = tleStr.Replace(";", ";"); var line1 = tleStr.Split(';')[0]; var line2 = tleStr.Split(';')[1]; var dtUtc = start.AddHours(-8); var timeSpan = (long)(dtUtc - dtZero).TotalSeconds; var c = (end - start).TotalSeconds / spanSeconds; Process p = new Process(); var binPath = AppDomain.CurrentDomain.BaseDirectory; p.StartInfo.WorkingDirectory = exePath; p.StartInfo.FileName = exeFile; p.StartInfo.Arguments = $"-a \"{line1}\" -b \"{line2}\" -t {timeSpan} -p {spanSeconds} -c {c + 1}"; p.StartInfo.CreateNoWindow = true; p.StartInfo.RedirectStandardError = true; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.UseShellExecute = false; StringBuilder sb = new StringBuilder(); p.OutputDataReceived += (sender, e) => sb.Append(e.Data); p.Start(); p.BeginOutputReadLine(); p.WaitForExit();//WaitForExit加了超时时间的话进程退出后不能保证异步流已经读取完成,这是.NET框架的BUG return ParseResult(sb.ToString()); } static List ParseResult(string result) { if (string.IsNullOrWhiteSpace(result)) { throw new Exception("星历推算出现未知错误!"); } var array = result.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); List list = new List(); foreach (var item in array) { var arrayItem = item.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < arrayItem.Length; i++) { var dto = new SatEphDto { SatId = Convert.ToInt32(arrayItem[i++]), TleTime = dtZero.AddSeconds(Convert.ToInt64(arrayItem[i++])).AddHours(16),//内部有BUG需要多加8h SatTime = dtZero.AddSeconds(Convert.ToInt64(arrayItem[i++])).AddHours(8),//utc to beijing X = Math.Round(Convert.ToDouble(arrayItem[i++]), 3), Y = Math.Round(Convert.ToDouble(arrayItem[i++]), 3), Z = Math.Round(Convert.ToDouble(arrayItem[i++]), 3), VX = Math.Round(Convert.ToDouble(arrayItem[i++]), 3), VY = Math.Round(Convert.ToDouble(arrayItem[i++]), 3), VZ = Math.Round(Convert.ToDouble(arrayItem[i]), 3) }; list.Add(dto); } } return list; } static SatEphDto ParseOneResult(string result) { if (string.IsNullOrWhiteSpace(result)) { throw new Exception("星历推算出现未知错误!"); } result = result.Replace(";", ""); var array = result.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); int i = 0; var dto = new SatEphDto { SatId = Convert.ToInt32(array[i++]), TleTime = dtZero.AddSeconds(Convert.ToInt64(array[i++])).AddHours(16),//内部有BUG需要多加8h SatTime = dtZero.AddSeconds(Convert.ToInt64(array[i++])).AddHours(8),//utc to beijing X = Math.Round(Convert.ToDouble(array[i++]), 3), Y = Math.Round(Convert.ToDouble(array[i++]), 3), Z = Math.Round(Convert.ToDouble(array[i++]), 3), VX = Math.Round(Convert.ToDouble(array[i++]), 3), VY = Math.Round(Convert.ToDouble(array[i++]), 3), VZ = Math.Round(Convert.ToDouble(array[i++]), 3) }; return dto; } } public class SatEphDto { /// /// 卫星编号 /// [Display(Name = "卫星编号")] public int SatId { get; set; } /// /// 卫星时刻(北京时间) /// [Display(Name = "卫星时刻")] public DateTime SatTime { get; set; } /// /// 星历时刻(北京时间) /// [Display(Name = "星历时刻")] public DateTime TleTime { get; set; } /// /// X坐标 /// [Display(Name = "X")] public double X { get; set; } /// /// Y坐标 /// [Display(Name = "Y")] public double Y { get; set; } /// /// Z坐标 /// [Display(Name = "Z")] public double Z { get; set; } /// /// X方向速率 /// [Display(Name = "VX")] public double VX { get; set; } /// /// Y方向速率 /// [Display(Name = "VY")] public double VY { get; set; } /// /// Z方向速率 /// [Display(Name = "VZ")] public double VZ { get; set; } public override string ToString() { return $"{X},{Y},{Z},{VX},{VY},{VZ}"; } } }