EphHelper.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel.DataAnnotations;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. namespace XdCxRhDW.Core.Api
  10. {
  11. /// <summary>
  12. /// 星历推算帮助类.该类调用了Tle2XYZ.exe进程
  13. /// </summary>
  14. public static class EphHelper
  15. {
  16. private static readonly DateTime dtZero = new DateTime(1970, 1, 1, 0, 0, 0, 0);
  17. private static string exePath= "星历推算";
  18. private const string exeName = "Tle2XYZ.exe";
  19. /// <summary>
  20. /// 设置【Tle2XYZ.exe】文件所在路径,支持相对路径
  21. /// </summary>
  22. public static void SetExePath(string path)
  23. {
  24. if (string.IsNullOrWhiteSpace(path)) return;
  25. if (path.StartsWith("\\"))//相对路径要么开头不带\,要么是 .\
  26. path = path.Remove(0, 1);
  27. exePath = path;
  28. }
  29. /// <summary>
  30. /// 推算双行星历
  31. /// </summary>
  32. /// <param name="tleStr">双行根数</param>
  33. /// <param name="dt">指定时刻(北京时间)</param>
  34. /// <returns></returns>
  35. public static SatEphDto Calc(string tleStr, DateTime dt)
  36. {
  37. if (string.IsNullOrWhiteSpace(exePath))
  38. throw new Exception($"请先调用SetExePath指定{exeName}进程所在路径,支持相对路径");
  39. if (!Directory.Exists(exePath))
  40. throw new Exception($"路径[{exePath}]不存在");
  41. var exeFile = Path.Combine(exePath, exeName);
  42. if (!File.Exists(exeFile))
  43. throw new Exception($"文件[{exeFile}]不存在");
  44. tleStr = tleStr.Replace(";", ";");
  45. if (tleStr.EndsWith(";"))
  46. tleStr = tleStr.Substring(0, tleStr.Length - 1);
  47. tleStr = tleStr.Replace(";", ";");
  48. var line1 = tleStr.Split(';')[0];
  49. var line2 = tleStr.Split(';')[1];
  50. var dtUtc = dt.AddHours(-8);
  51. var timeSpan = (long)(dtUtc - dtZero).TotalSeconds;
  52. Process p = new Process();
  53. p.StartInfo.WorkingDirectory = exePath;
  54. p.StartInfo.FileName = exeFile;
  55. p.StartInfo.Arguments = $"-a \"{line1}\" -b \"{line2}\" -t {timeSpan} -p 1 -c 1";
  56. p.StartInfo.CreateNoWindow = true;
  57. p.StartInfo.RedirectStandardError = true;
  58. p.StartInfo.RedirectStandardOutput = true;
  59. p.StartInfo.UseShellExecute = false;
  60. p.Start();
  61. var succeed = p.WaitForExit(10000);
  62. if (!succeed)
  63. {
  64. throw new Exception($"进程[{exeName}]超时未完成!");
  65. }
  66. return ParseOneResult(p.StandardOutput.ReadToEnd());
  67. }
  68. /// <summary>
  69. /// 批量推算双行星历
  70. /// </summary>
  71. /// <param name="tleStr">双行根数</param>
  72. /// <param name="start">起始时刻(北京)</param>
  73. /// <param name="end">结束(北京)</param>
  74. /// <param name="spanSeconds">推算间隔(秒)</param>
  75. /// <returns></returns>
  76. public static List<SatEphDto> CalcMult(string tleStr, DateTime start, DateTime end, int spanSeconds)
  77. {
  78. if (string.IsNullOrWhiteSpace(exePath))
  79. throw new Exception($"请先调用SetExePath指定{exeName}进程所在路径,支持相对路径");
  80. if (!Directory.Exists(exePath))
  81. throw new Exception($"路径[{exePath}]不存在");
  82. var exeFile = Path.Combine(exePath, exeName);
  83. if (!File.Exists(exeFile))
  84. throw new Exception($"文件[{exeFile}]不存在");
  85. tleStr = tleStr.Replace(";", ";");
  86. if (tleStr.EndsWith(";"))
  87. tleStr = tleStr.Substring(0, tleStr.Length - 1);
  88. tleStr = tleStr.Replace(";", ";");
  89. var line1 = tleStr.Split(';')[0];
  90. var line2 = tleStr.Split(';')[1];
  91. var dtUtc = start.AddHours(-8);
  92. var timeSpan = (long)(dtUtc - dtZero).TotalSeconds;
  93. var c = (end - start).TotalSeconds / spanSeconds;
  94. Process p = new Process();
  95. var binPath = AppDomain.CurrentDomain.BaseDirectory;
  96. p.StartInfo.WorkingDirectory = exePath;
  97. p.StartInfo.FileName = exeFile;
  98. p.StartInfo.Arguments = $"-a \"{line1}\" -b \"{line2}\" -t {timeSpan} -p {spanSeconds} -c {c + 1}";
  99. p.StartInfo.CreateNoWindow = true;
  100. p.StartInfo.RedirectStandardError = true;
  101. p.StartInfo.RedirectStandardOutput = true;
  102. p.StartInfo.UseShellExecute = false;
  103. StringBuilder sb = new StringBuilder();
  104. p.OutputDataReceived += (sender, e) => sb.Append(e.Data);
  105. p.Start();
  106. p.BeginOutputReadLine();
  107. p.WaitForExit();//WaitForExit加了超时时间的话进程退出后不能保证异步流已经读取完成,这是.NET框架的BUG
  108. return ParseResult(sb.ToString());
  109. }
  110. static List<SatEphDto> ParseResult(string result)
  111. {
  112. if (string.IsNullOrWhiteSpace(result))
  113. {
  114. throw new Exception("星历推算出现未知错误!");
  115. }
  116. var array = result.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
  117. List<SatEphDto> list = new List<SatEphDto>();
  118. foreach (var item in array)
  119. {
  120. var arrayItem = item.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
  121. for (int i = 0; i < arrayItem.Length; i++)
  122. {
  123. var dto = new SatEphDto
  124. {
  125. SatId = Convert.ToInt32(arrayItem[i++]),
  126. TleTime = dtZero.AddSeconds(Convert.ToInt64(arrayItem[i++])).AddHours(16),//内部有BUG需要多加8h
  127. SatTime = dtZero.AddSeconds(Convert.ToInt64(arrayItem[i++])).AddHours(8),//utc to beijing
  128. X = Math.Round(Convert.ToDouble(arrayItem[i++]), 3),
  129. Y = Math.Round(Convert.ToDouble(arrayItem[i++]), 3),
  130. Z = Math.Round(Convert.ToDouble(arrayItem[i++]), 3),
  131. VX = Math.Round(Convert.ToDouble(arrayItem[i++]), 3),
  132. VY = Math.Round(Convert.ToDouble(arrayItem[i++]), 3),
  133. VZ = Math.Round(Convert.ToDouble(arrayItem[i]), 3)
  134. };
  135. list.Add(dto);
  136. }
  137. }
  138. return list;
  139. }
  140. static SatEphDto ParseOneResult(string result)
  141. {
  142. if (string.IsNullOrWhiteSpace(result))
  143. {
  144. throw new Exception("星历推算出现未知错误!");
  145. }
  146. result = result.Replace(";", "");
  147. var array = result.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
  148. int i = 0;
  149. var dto = new SatEphDto
  150. {
  151. SatId = Convert.ToInt32(array[i++]),
  152. TleTime = dtZero.AddSeconds(Convert.ToInt64(array[i++])).AddHours(16),//内部有BUG需要多加8h
  153. SatTime = dtZero.AddSeconds(Convert.ToInt64(array[i++])).AddHours(8),//utc to beijing
  154. X = Math.Round(Convert.ToDouble(array[i++]), 3),
  155. Y = Math.Round(Convert.ToDouble(array[i++]), 3),
  156. Z = Math.Round(Convert.ToDouble(array[i++]), 3),
  157. VX = Math.Round(Convert.ToDouble(array[i++]), 3),
  158. VY = Math.Round(Convert.ToDouble(array[i++]), 3),
  159. VZ = Math.Round(Convert.ToDouble(array[i++]), 3)
  160. };
  161. return dto;
  162. }
  163. }
  164. public class SatEphDto
  165. {
  166. /// <summary>
  167. /// 卫星编号
  168. /// </summary>
  169. [Display(Name = "卫星编号")]
  170. public int SatId { get; set; }
  171. /// <summary>
  172. /// 卫星时刻(北京时间)
  173. /// </summary>
  174. [Display(Name = "卫星时刻")]
  175. public DateTime SatTime { get; set; }
  176. /// <summary>
  177. /// 星历时刻(北京时间)
  178. /// </summary>
  179. [Display(Name = "星历时刻")]
  180. public DateTime TleTime { get; set; }
  181. /// <summary>
  182. /// X坐标
  183. /// </summary>
  184. [Display(Name = "X")]
  185. public double X { get; set; }
  186. /// <summary>
  187. /// Y坐标
  188. /// </summary>
  189. [Display(Name = "Y")]
  190. public double Y { get; set; }
  191. /// <summary>
  192. /// Z坐标
  193. /// </summary>
  194. [Display(Name = "Z")]
  195. public double Z { get; set; }
  196. /// <summary>
  197. /// X方向速率
  198. /// </summary>
  199. [Display(Name = "VX")]
  200. public double VX { get; set; }
  201. /// <summary>
  202. /// Y方向速率
  203. /// </summary>
  204. [Display(Name = "VY")]
  205. public double VY { get; set; }
  206. /// <summary>
  207. /// Z方向速率
  208. /// </summary>
  209. [Display(Name = "VZ")]
  210. public double VZ { get; set; }
  211. public override string ToString()
  212. {
  213. return $"{X},{Y},{Z},{VX},{VY},{VZ}";
  214. }
  215. }
  216. }