using DevExpress.Charts.Native; using DevExpress.Internal.WinApi.Windows.UI.Notifications; using DevExpress.XtraPrinting; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using XdCxRhDW.App.DTO; using static System.Windows.Forms.VisualStyles.VisualStyleElement.TaskbarClock; namespace XzXdDw.App.Api.低轨GDOP误差椭圆 { /// /// 误差椭圆计算帮助类.该类调用了GdopCore.exe进程 /// 每种误差椭圆算法提供了两个接口,这两种接口是完全等价的,一种传入双行根,一种直接传入卫星状态x、y、z等 /// public static class ErrEllipseHelper { private static string exePath = "Api\\低轨GDOP误差椭圆\\GDOP"; private const string exeName = "GdopCore.exe"; /// /// 三星双时差误差椭圆带参 /// /// 主星双行根数 /// 邻1星双行根数 /// 邻2星双行根数 /// 采集时刻 /// 定位点经纬度,数组长度=2 /// 参考站经纬度,数组长度=2 /// 输出参数:椭圆长轴(km) /// 输出参数:椭圆短轴(km) /// 时差误差(单位us) /// 星历位置误差(单位米) /// 误差概率百分比(0-100,默认50) /// public static (List, List) ErrEllipse3Sat2DtoRef(string mainSatTle, string adja1SatTle, string adja2SatTle, DateTime time, double[] posLonLat, double[] refLonLat, out double R1, out double R2, double dtousErr = 1, double satLocErr = 10000, double errProb = 50) { 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}]不存在"); Process p = new Process(); p.StartInfo.WorkingDirectory = exePath; p.StartInfo.FileName = exeFile; p.StartInfo.Arguments = $"50 \"{mainSatTle}\" \"{adja1SatTle}\" \"{adja2SatTle}\" \"{time:yyyy-MM-dd HH:mm:ss.000000}\" {string.Join(" ", posLonLat)} {string.Join(" ", refLonLat)} {dtousErr} {satLocErr} {errProb}"; 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(3, sb.ToString(), out R1, out R2); } /// /// 三星双时差误差椭圆带参 /// /// 主星xyz星历,数组长度=3 /// 邻1星xyz星历,数组长度=3 /// 邻2星xyz星历,数组长度=3 /// 定位点经纬度,数组长度=2 /// 参考站经纬度,数组长度=2 /// 输出参数:椭圆长轴(km) /// 输出参数:椭圆短轴(km) /// 时差误差(单位us) /// 星历位置误差(单位米) /// 误差概率百分比(0-100,默认50) /// public static (List, List) ErrEllipse3Sat2DtoRef(double[] mainSatEph, double[] adja1SatEph, double[] adja2SatEph, double[] posLonLat, double[] refLonLat, out double R1, out double R2, double dtousErr = 1, double satLocErr = 10000, double errProb = 50) { 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}]不存在"); Process p = new Process(); p.StartInfo.WorkingDirectory = exePath; p.StartInfo.FileName = exeFile; p.StartInfo.Arguments = $"51 {string.Join(" ", mainSatEph)} {string.Join(" ", adja1SatEph)} {string.Join(" ", adja2SatEph)} {string.Join(" ", posLonLat)} {string.Join(" ", refLonLat)} {dtousErr} {satLocErr} {errProb}"; 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(3, sb.ToString(), out R1, out R2); } /// /// 三星双时差误差椭圆无参 /// /// 主星双行根数 /// 邻1星双行根数 /// 邻2星双行根数 /// 采集时刻 /// 定位点经纬度,数组长度=2 /// 接收站经纬度,数组长度=2 /// 输出参数:椭圆长轴(km) /// 输出参数:椭圆短轴(km) /// 时差误差(单位us) /// 星历位置误差(单位米) /// 误差概率百分比(0-100,默认50) /// public static (List, List) ErrEllipse3Sat2Dto(string mainSatTle, string adja1SatTle, string adja2SatTle, DateTime time, double[] posLonLat, double[] recLonLat, out double R1, out double R2, double dtousErr = 1, double satLocErr = 10000, double errProb = 50) { 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}]不存在"); Process p = new Process(); p.StartInfo.WorkingDirectory = exePath; p.StartInfo.FileName = exeFile; p.StartInfo.Arguments = $"52 \"{mainSatTle}\" \"{adja1SatTle}\" \"{adja2SatTle}\" \"{time:yyyy-MM-dd HH:mm:ss.000000}\" {string.Join(" ", posLonLat)} {string.Join(" ", recLonLat)} {dtousErr} {satLocErr} {errProb}"; 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(3, sb.ToString(), out R1, out R2); } /// /// 三星双时差误差椭圆无参 /// /// 主星xyz星历,数组长度=3 /// 邻1星xyz星历,数组长度=3 /// 邻2星xyz星历,数组长度=3 /// 定位点经纬度,数组长度=2 /// 接收站经纬度,数组长度=2 /// 输出参数:椭圆长轴(km) /// 输出参数:椭圆短轴(km) /// 时差误差(单位us) /// 星历位置误差(单位米) /// 误差概率百分比(0-100,默认50) /// public static (List, List) ErrEllipse3Sat2Dto(double[] mainSatEph, double[] adja1SatEph, double[] adja2SatEph, double[] posLonLat, double[] recLonLat, out double R1, out double R2, double dtousErr = 1, double satLocErr = 10000, double errProb = 50) { 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}]不存在"); Process p = new Process(); p.StartInfo.WorkingDirectory = exePath; p.StartInfo.FileName = exeFile; p.StartInfo.Arguments = $"51 {string.Join(" ", mainSatEph)} {string.Join(" ", adja1SatEph)} {string.Join(" ", adja2SatEph)} {string.Join(" ", posLonLat)} {string.Join(" ", recLonLat)} {dtousErr} {satLocErr} {errProb}"; 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(3, sb.ToString(), out R1, out R2); } /// /// 双星时频差误差椭圆带参 /// /// 主星双行根数 /// 邻星双行根数 /// 采集时刻 /// 目标上行频点MHz /// 参考上行频点MHz /// 主星转发器本振MHz /// 邻星转发器本振MHz /// 定位点经纬度,数组长度=2 /// 参考站经纬度,数组长度=2 /// 输出参数:椭圆长轴(km) /// 输出参数:椭圆短轴(km) /// public static (List, List) ErrEllipse2SatDtoDfoRef(string mainTle, string adjaTle, DateTime time, double tarFreqUpMHz, double refFreqUpMHz, double mainSatTransMHz, double adjaSatTransMHz, double[] posLonLat, double[] refLonLat, out double R1, out double R2) { 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}]不存在"); Process p = new Process(); p.StartInfo.WorkingDirectory = exePath; p.StartInfo.FileName = exeFile; p.StartInfo.Arguments = $"54 \"{mainTle}\" \"{adjaTle}\" \"{time:yyyy-MM-dd HH:mm:ss.000000}\" {tarFreqUpMHz} {refFreqUpMHz} {mainSatTransMHz} {adjaSatTransMHz} {string.Join(" ", posLonLat)} {string.Join(" ", refLonLat)} "; 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(2, sb.ToString(), out R1, out R2); } /// /// 双星时频差误差椭圆带参 /// /// 主星星历xyz vx vy vz,数组长度=6 /// 邻星星历xyz vx vy vz,数组长度=6 /// 目标上行频点MHz /// 参考上行频点MHz /// 主星转发器本振MHz /// 邻星转发器本振MHz /// 定位点经纬度,数组长度=2 /// 参考站经纬度,数组长度=2 /// 输出参数:椭圆长轴(km) /// 输出参数:椭圆短轴(km) /// public static (List, List) ErrEllipse2SatDtoDfoRef(double[] mainSatEph, double[] adjaSatEph, double tarFreqUpMHz, double refFreqUpMHz, double mainSatTransMHz, double adjaSatTransMHz, double[] posLonLat, double[] refLonLat, out double R1, out double R2) { 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}]不存在"); Process p = new Process(); p.StartInfo.WorkingDirectory = exePath; p.StartInfo.FileName = exeFile; p.StartInfo.Arguments = $"55 {string.Join(" ", mainSatEph)} {string.Join(" ", adjaSatEph)} {tarFreqUpMHz} {refFreqUpMHz} {mainSatTransMHz} {adjaSatTransMHz} {string.Join(" ", posLonLat)} {string.Join(" ", refLonLat)}"; 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(2, sb.ToString(), out R1, out R2); } /// /// 双星时频差误差椭圆无参 /// /// 主星双行根数 /// 邻星双行根数 /// 采集时刻 /// 目标上行频点MHz /// 主星转发器本振MHz /// 邻星转发器本振MHz /// 定位点经纬度,数组长度=2 /// 接收站经纬度,数组长度=2 /// 输出参数:椭圆长轴(km) /// 输出参数:椭圆短轴(km) /// public static (List, List) ErrEllipse2SatDtoDfo(string mainTle, string adjaTle, DateTime time, double tarFreqUpMHz, double mainSatTransMHz, double adjaSatTransMHz, double[] posLonLat, double[] recLonLat, out double R1, out double R2) { 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}]不存在"); Process p = new Process(); p.StartInfo.WorkingDirectory = exePath; p.StartInfo.FileName = exeFile; p.StartInfo.Arguments = $"56 \"{mainTle}\" \"{adjaTle}\" \"{time:yyyy-MM-dd HH:mm:ss.000000}\" {tarFreqUpMHz} {mainSatTransMHz} {adjaSatTransMHz} {string.Join(" ", posLonLat)} {string.Join(" ", recLonLat)}"; 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(2, sb.ToString(), out R1, out R2); } /// /// 双星时频差误差椭圆无参 /// /// 主星星历xyz vx vy vz,数组长度=6 /// 邻星星历xyz vx vy vz,数组长度=6 /// 目标上行频点MHz /// 主星转发器本振MHz /// 邻星转发器本振MHz /// 定位点经纬度,数组长度=2 /// 接收站经纬度,数组长度=2 /// 输出参数:椭圆长轴(km) /// 输出参数:椭圆短轴(km) /// public static (List, List) ErrEllipse2SatDtoDfo(double[] mainSatEph, double[] adjaSatEph, double tarFreqUpMHz, double mainSatTransMHz, double adjaSatTransMHz, double[] posLonLat, double[] recLonLat, out double R1, out double R2) { 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}]不存在"); Process p = new Process(); p.StartInfo.WorkingDirectory = exePath; p.StartInfo.FileName = exeFile; p.StartInfo.Arguments = $"57 {string.Join(" ", mainSatEph)} {string.Join(" ", adjaSatEph)} {tarFreqUpMHz} {mainSatTransMHz} {adjaSatTransMHz} {string.Join(" ", posLonLat)} {string.Join(" ", recLonLat)}"; 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(2, sb.ToString(), out R1, out R2); } private static (List, List) ParseResult(int satCount, string txt, out double errR1, out double errR2) { if (string.IsNullOrWhiteSpace(txt)) { throw new Exception("误差椭圆计算出现未知错误!"); } if (txt.StartsWith("1 ")) { throw new Exception(txt.Remove(0, 2)); } var arr = txt.Split(' '); List list = new List(); for (int i = 0; i < satCount; i++) { SatInfo satInfo = new SatInfo(); var satCode = Convert.ToInt32(arr[3 * i + 1]); if (satCode > 0) satInfo.SatCode = satCode; satInfo.SatLon = Convert.ToDouble(arr[3 * i + 2]); satInfo.SatLat = Convert.ToDouble(arr[3 * i + 3]); list.Add(satInfo); } errR1 = Convert.ToDouble(arr[1 + satCount * 3]);//椭圆长轴 errR2 = Convert.ToDouble(arr[2 + satCount * 3]);//椭圆短轴 var jsonStr = arr[3 + satCount * 3]; var res = JsonConvert.DeserializeObject>(jsonStr); return (list, res); } } }