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}";
}
}
}