DrawDtoLineHelper.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. 
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Runtime.InteropServices;
  8. using System.Text;
  9. using XdCxRhDW.Entity;
  10. namespace XdCxRhDW.Api
  11. {
  12. public class DrawDtoLineHelper
  13. {
  14. private const string XdtsDll = @"AddIns\时差线\Positioning.dll";
  15. [DllImport(XdtsDll, EntryPoint = "CurveByTwoTDOA", CallingConvention = CallingConvention.Cdecl)]//高轨双星有参时差线
  16. public extern static void CurveByTwoTDOA(double[] main_sat_pos, double[] neigh_sat_pos, double[] rec1_pos, double[] rec2_pos, double[] ref_pos, double[] Zone,
  17. double target_dto, double ref_dto, out IntPtr LOP_Value, ref int LOP_Len);
  18. /*
  19. 双星时差线-无参
  20. LOP_Value 返回值 结构参考DTO_Plot
  21. LOP_Len*3为LOP_Value的长度
  22. */
  23. [DllImport(XdtsDll, EntryPoint = "CurveByTwoTDOAWithNoRef", CallingConvention = CallingConvention.Cdecl)]//高轨双星无参时差线
  24. public extern static void CurveByTwoTDOAWithNoRef(double[] main_sat_pos, double[] neigh_sat_pos, double[] rec1_pos, double[] rec2_pos,
  25. double[] Zone, double target_dto, out IntPtr LOP_Value, ref int LOP_Len);
  26. [DllImport(XdtsDll, CallingConvention = CallingConvention.Cdecl)]
  27. public static extern void Destory(IntPtr val);
  28. private const string exeName = "XingDiSCX.exe";//星地时差线
  29. // private static double[] zone = new double[] { -85, 85, -180, 180 }; //定位区域
  30. /// <summary>
  31. /// 星地有参时差线
  32. /// </summary>
  33. /// <param name="opt"></param>
  34. /// <returns></returns>
  35. /// <exception cref="Exception"></exception>
  36. public static IEnumerable<(double lon, double lat)> DtoLineXd(DtoLineXdOption opt)
  37. {
  38. List<DtoLinePoint> list = new List<DtoLinePoint>();
  39. string file = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AddIns\\时差线\\DtoLine.dat");
  40. string exePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AddIns\\时差线");
  41. if (string.IsNullOrWhiteSpace(exePath))
  42. throw new Exception($"请先调用SetExePath指定{exeName}进程所在路径,支持相对路径");
  43. if (!Directory.Exists(exePath))
  44. throw new Exception($"路径[{exePath}]不存在");
  45. var exeFile = Path.Combine(exePath, exeName);
  46. if (!File.Exists(exeFile))
  47. throw new Exception($"文件[{exeFile}]不存在");
  48. List<string> arguments = new List<string>
  49. {
  50. file,
  51. $"{opt.MsEph[0]}",
  52. $"{opt.MsEph[1]}",
  53. $"{opt.MsEph[2]}",
  54. $"{opt.MsAnt[0]}",
  55. $"{opt.MsAnt[1]}",
  56. $"{opt.CDBAnt[0]}",
  57. $"{opt.CDBAnt[1]}",
  58. $"{opt.RefGeod[0]}",
  59. $"{opt.RefGeod[1]}",
  60. $"{opt.xdDto}",
  61. $"{opt.RefDto}",
  62. $"{opt.PosLon}",
  63. $"{opt.PosLat}"
  64. };
  65. Process p = new Process();
  66. p.StartInfo.WorkingDirectory = exePath;
  67. p.StartInfo.FileName = exeFile;
  68. p.StartInfo.Arguments = string.Join(" ", arguments);
  69. p.StartInfo.CreateNoWindow = true;
  70. p.StartInfo.RedirectStandardError = true;
  71. p.StartInfo.RedirectStandardOutput = true;
  72. p.StartInfo.UseShellExecute = false;
  73. p.Start();
  74. var succeed = p.WaitForExit(10000);
  75. if (!succeed)
  76. {
  77. throw new Exception($"进程[{exeName}]超时未完成!");
  78. }
  79. string result = p.StandardOutput.ReadToEnd();
  80. if (string.IsNullOrWhiteSpace(result))
  81. {
  82. throw new Exception("计算时差线出现未知错误!");
  83. }
  84. var array = result.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
  85. if (array[0] == "1")
  86. {
  87. throw new Exception(array[1]);
  88. }
  89. if (File.Exists(file))
  90. {
  91. var dtostr = File.ReadAllText(file);
  92. list = Newtonsoft.Json.JsonConvert.DeserializeObject<List<DtoLinePoint>>(dtostr);
  93. }
  94. var Lines = list.Select(s => (s.Lon, s.Lat));
  95. return Lines;
  96. }
  97. /// <summary>
  98. /// 星地有参时差线
  99. /// </summary>
  100. /// <param name="opt"></param>
  101. /// <returns></returns>
  102. /// <exception cref="Exception"></exception>
  103. public static IEnumerable<(double lon, double lat)> DtoLineXdEx(DtoLineXdOption opt)
  104. {
  105. List<DtoLinePoint> list = new List<DtoLinePoint>();
  106. IntPtr LOP_ValuePtr;
  107. int LOP_Len = 0;
  108. GDOPApi.SCX_XD(opt.MsEph, opt.MsAnt, opt.MsAnt, opt.CDBAnt, opt.RefGeod, opt.xdDto * 1e-6, opt.RefDto * 1e-6, ref LOP_Len, out LOP_ValuePtr);
  109. double[] LOP_Value = new double[LOP_Len];
  110. if (LOP_Len > 0)
  111. {
  112. Marshal.Copy(LOP_ValuePtr, LOP_Value, 0, LOP_Value.Length);
  113. }
  114. GDOPApi.FreeGDOPBuf(LOP_ValuePtr);
  115. var points = ParseResult(LOP_Value);
  116. var mapDots = points.Select(p => p).Select(p => (p.Lon, p.Lat));
  117. return mapDots;
  118. }
  119. /// <summary>
  120. /// 星地有参时差线
  121. /// </summary>
  122. /// <param name="opt"></param>
  123. /// <returns></returns>
  124. /// <exception cref="Exception"></exception>
  125. public static IEnumerable<DtoLine> DtoLineXdNew(DtoLineXdOption opt)
  126. {
  127. List<DtoLine> list = new List<DtoLine>();
  128. IntPtr LOP_ValuePtr;
  129. IntPtr ResLen;
  130. int LineCount = 0;
  131. GDOPApi.SCX_XD_new(opt.MsEph, opt.MsAnt, opt.MsAnt, opt.CDBAnt, opt.RefGeod, opt.xdDto * 1e-6, opt.RefDto * 1e-6, ref LineCount, out ResLen, out LOP_ValuePtr);
  132. int[] res_Len = new int[LineCount];
  133. if (LineCount > 0)
  134. {
  135. Marshal.Copy(ResLen, res_Len, 0, res_Len.Length);
  136. int total = res_Len.Sum(r => r);
  137. double[] LOP_Value = new double[total * 2];
  138. Marshal.Copy(LOP_ValuePtr, LOP_Value, 0, LOP_Value.Length);
  139. var points = ParseResult(LOP_Value);
  140. int skipcount = 0;
  141. for (int i = 0; i < LineCount; i++)
  142. {
  143. int pointcount = res_Len[i];
  144. skipcount = i == 0 ? 0 : skipcount + res_Len[i-1];
  145. var mapDots= points.Skip(skipcount).Take(pointcount);
  146. DtoLine dtoLine = new DtoLine();
  147. dtoLine.dtoLinePoints = mapDots.Select(p => p).Select(p => (p.Lon, p.Lat));
  148. list.Add(dtoLine);
  149. }
  150. }
  151. GDOPApi.FreeGDOPBuf(ResLen);
  152. GDOPApi.FreeGDOPBuf(LOP_ValuePtr);
  153. return list;
  154. }
  155. private static List<MapDot> ParseResult(double[] ponits)
  156. {
  157. List<MapDot> mapDots = new List<MapDot>();
  158. int count = 2;
  159. for (int i = 0; i < ponits.Length / count; i++)
  160. {
  161. MapDot mapDot = new MapDot();
  162. mapDot.Lon = ponits[count * i];
  163. mapDot.Lat = ponits[count * i + 1];//0 1 2 3 4 5 6 7
  164. mapDots.Add(mapDot);
  165. }
  166. return mapDots;
  167. }
  168. /// <summary>
  169. /// 星地无参时差线
  170. /// </summary>
  171. /// <param name="opt"></param>
  172. /// <returns></returns>
  173. /// <exception cref="Exception"></exception>
  174. public static IEnumerable<(double lon, double lat)> DtoLineXdNoRefEx(DtoLineXdOption opt)
  175. {
  176. List<DtoLinePoint> list = new List<DtoLinePoint>();
  177. IntPtr LOP_ValuePtr;
  178. int LOP_Len = 0;
  179. GDOPApi.SCX_XD_NoRef(opt.MsEph, opt.MsAnt, opt.CDBAnt, opt.xdDto * 1e-6, ref LOP_Len, out LOP_ValuePtr);
  180. double[] LOP_Value = new double[LOP_Len];
  181. if (LOP_Len > 0)
  182. {
  183. Marshal.Copy(LOP_ValuePtr, LOP_Value, 0, LOP_Value.Length);
  184. }
  185. GDOPApi.FreeGDOPBuf(LOP_ValuePtr);
  186. var points = ParseResult(LOP_Value);
  187. var mapDots = points.Select(p => p).Select(p => (p.Lon, p.Lat));
  188. return mapDots;
  189. }
  190. /// <summary>
  191. /// 星地无参时差线
  192. /// </summary>
  193. /// <param name="opt"></param>
  194. /// <returns></returns>
  195. /// <exception cref="Exception"></exception>
  196. public static IEnumerable<DtoLine> DtoLineXdNoRefNew(DtoLineXdOption opt)
  197. {
  198. List<DtoLine> list = new List<DtoLine>();
  199. IntPtr LOP_ValuePtr;
  200. IntPtr ResLen;
  201. int LineCount = 0;
  202. GDOPApi.SCX_XD_NoRef_new(opt.MsEph, opt.MsAnt, opt.CDBAnt, opt.xdDto * 1e-6, ref LineCount, out ResLen, out LOP_ValuePtr);
  203. int[] res_Len = new int[LineCount];
  204. if (LineCount > 0)
  205. {
  206. Marshal.Copy(ResLen, res_Len, 0, res_Len.Length);
  207. int total = res_Len.Sum(r => r);
  208. double[] LOP_Value = new double[total * 2];
  209. Marshal.Copy(LOP_ValuePtr, LOP_Value, 0, LOP_Value.Length);
  210. var points = ParseResult(LOP_Value);
  211. int skipcount = 0;
  212. for (int i = 0; i < LineCount; i++)
  213. {
  214. int pointcount = res_Len[i];
  215. skipcount = i == 0 ? 0 : skipcount + res_Len[i - 1];
  216. var mapDots = points.Skip(skipcount).Take(pointcount);
  217. DtoLine dtoLine = new DtoLine();
  218. dtoLine.dtoLinePoints = mapDots.Select(p => p).Select(p => (p.Lon, p.Lat));
  219. list.Add(dtoLine);
  220. }
  221. }
  222. GDOPApi.FreeGDOPBuf(ResLen);
  223. GDOPApi.FreeGDOPBuf(LOP_ValuePtr);
  224. return list;
  225. }
  226. public static IEnumerable<(double lon, double lat)> DtoLineXdNoRefZl(DtoLineXdOption opt)
  227. {
  228. double startLon = (int)opt.CDBAnt[0] - 30;
  229. double endLon = (int)opt.CDBAnt[0] + 30;
  230. double startLat = (int)opt.CDBAnt[1] - 30;
  231. double endLat = (int)opt.CDBAnt[1] + 30;
  232. List<(double, double, double)> list2 = new List<(double, double, double)>();
  233. var recXYZ = PhysicsHelper.GeoToEcef((opt.MsAnt[0], opt.MsAnt[1], opt.MsAnt[2]));
  234. var cdbXYZ = PhysicsHelper.GeoToEcef((opt.CDBAnt[0], opt.CDBAnt[1], opt.CDBAnt[2]));
  235. for (double lon = startLon; lon < endLon; lon += 0.01)
  236. {
  237. List<(double, double, double)> list = new List<(double, double, double)>();
  238. int flag = 0;
  239. for (double lat = startLat; lat < endLat; lat += 0.01)
  240. {
  241. var posXYZ = PhysicsHelper.GeoToEcef((lon, lat, 0));
  242. //目标-主星-接收站的时间(us)
  243. var dt1 = PhysicsHelper.Dto(posXYZ, (opt.MsEph[0], opt.MsEph[1], opt.MsEph[2]), recXYZ) * 1e6;
  244. //目标-超短站的时间(us)
  245. var dt2 = PhysicsHelper.Dto(posXYZ, cdbXYZ) * 1e6;
  246. var dto = Math.Abs(dt1 - dt2 - opt.xdDto);
  247. if (dto > 100)
  248. {
  249. lat += 1;
  250. if (flag < 1)
  251. flag = 1;
  252. continue;
  253. }
  254. else if (dto > 50)
  255. {
  256. lat += 0.5;
  257. if (flag < 2)
  258. flag = 2;
  259. continue;
  260. }
  261. else if (dto > 20)
  262. {
  263. lat += 0.2;
  264. if (flag < 3)
  265. flag = 3;
  266. continue;
  267. }
  268. else if (dto > 5)
  269. {
  270. lat += 0.1;
  271. if (flag < 4)
  272. flag = 4;
  273. continue;
  274. }
  275. else if (dto > 2)
  276. {
  277. lat += 0.05;
  278. if (flag < 5)
  279. flag = 5;
  280. continue;
  281. }
  282. flag = 10;
  283. list.Add((lon, lat, dto));
  284. }
  285. if (list.Any())
  286. {
  287. var p1 = list.OrderBy(p => p.Item3).FirstOrDefault();
  288. list2.Add(p1);
  289. var p2 = list.Where(p => p.Item3 < 0.01 && PhysicsHelper.DistanceGeo((p.Item1, p.Item2, 0), p1) > 5000).OrderBy(p => p.Item3).FirstOrDefault();
  290. if (p2 != default)
  291. list2.Add(p2);
  292. }
  293. else
  294. {
  295. if (flag == 1)
  296. lon += 1;
  297. else if (flag == 2)
  298. lon += 0.5;
  299. else if (flag == 3)
  300. lon += 0.2;
  301. else if (flag == 4)
  302. lon += 0.1;
  303. else if (flag == 5)
  304. lon += 0.05;
  305. }
  306. list.Clear();
  307. }
  308. return list2.Select(p => (p.Item1, p.Item2)).OrderBy(p => p.Item1).OrderBy(p => p.Item2);
  309. }
  310. /// <summary>
  311. /// 高轨双星时差线
  312. /// </summary>
  313. /// <param name="opt"></param>
  314. /// <returns></returns>
  315. public static IEnumerable<(double lon, double lat)> DtoLine2XStart(DtoLineTwoStartOption opt)
  316. {
  317. List<DtoLinePoint> list = new List<DtoLinePoint>();
  318. IntPtr LOP_ValuePtr;
  319. int LOP_Len = 0;
  320. CurveByTwoTDOA(
  321. opt.MsEph,
  322. opt.NsEph,
  323. opt.MsAnt,
  324. opt.NsAnt,
  325. opt.RefGeod,
  326. new double[] { -85, 85, -180, 180 },
  327. opt.TargetDto * 1e-6,
  328. opt.RefDto * 1e-6, out LOP_ValuePtr, ref LOP_Len);
  329. double[] LOP_Value = new double[LOP_Len * 3];
  330. if (LOP_Len > 0)
  331. {
  332. Marshal.Copy(LOP_ValuePtr, LOP_Value, 0, LOP_Value.Length);
  333. list = OutputHelper.WriteDtoLine(LOP_Value, LOP_Len);
  334. }
  335. Destory(LOP_ValuePtr);
  336. var Lines = list.Select(p => (p.Lon, p.Lat));
  337. return Lines;
  338. }
  339. public static IEnumerable<(double lon, double lat)> DtoLine2XNoRefStart(DtoLineTwoStartOption opt)
  340. {
  341. List<DtoLinePoint> list = new List<DtoLinePoint>();
  342. IntPtr LOP_ValuePtr;
  343. int LOP_Len = 0;
  344. CurveByTwoTDOAWithNoRef(
  345. opt.MsEph,
  346. opt.NsEph,
  347. opt.MsAnt,
  348. opt.NsAnt,
  349. new double[] { -85, 85, -180, 180 },
  350. opt.TargetDto * 1e-6, out LOP_ValuePtr, ref LOP_Len);
  351. double[] LOP_Value = new double[LOP_Len * 3];
  352. if (LOP_Len > 0)
  353. {
  354. Marshal.Copy(LOP_ValuePtr, LOP_Value, 0, LOP_Value.Length);
  355. list = OutputHelper.WriteDtoLine(LOP_Value, LOP_Len);
  356. }
  357. Destory(LOP_ValuePtr);
  358. var Lines = list.Select(p => (p.Lon, p.Lat));
  359. return Lines;
  360. }
  361. public static IEnumerable<(double lon, double lat)> DtoLine2XNoRefStartZl(DtoLineTwoStartOption opt)
  362. {
  363. double startLon = -180;
  364. double endLon = 180;
  365. double startLat = -80;
  366. double endLat = 80;
  367. List<(double, double, double)> list2 = new List<(double, double, double)>();
  368. var recXYZ = PhysicsHelper.GeoToEcef((opt.MsAnt[0], opt.MsAnt[1], opt.MsAnt[2]));
  369. for (double lon = startLon; lon < endLon; lon += 0.01)
  370. {
  371. List<(double, double, double)> list = new List<(double, double, double)>();
  372. int flag = 0;
  373. for (double lat = startLat; lat < endLat; lat += 0.01)
  374. {
  375. var posXYZ = PhysicsHelper.GeoToEcef((lon, lat, 0));
  376. //目标-主星-接收站的时间(us)
  377. var dt1 = PhysicsHelper.Dto(posXYZ, (opt.MsEph[0], opt.MsEph[1], opt.MsEph[2]), recXYZ) * 1e6;
  378. //目标-邻星-接收站的时间(us)
  379. var dt2 = PhysicsHelper.Dto(posXYZ, (opt.NsEph[0], opt.NsEph[1], opt.NsEph[2]), recXYZ) * 1e6;
  380. var dto = Math.Abs(dt1 - dt2 - opt.TargetDto);
  381. if (dto > 100)
  382. {
  383. lat += 1;
  384. if (flag < 1)
  385. flag = 1;
  386. continue;
  387. }
  388. else if (dto > 50)
  389. {
  390. lat += 0.5;
  391. if (flag < 2)
  392. flag = 2;
  393. continue;
  394. }
  395. else if (dto > 20)
  396. {
  397. lat += 0.2;
  398. if (flag < 3)
  399. flag = 3;
  400. continue;
  401. }
  402. else if (dto > 5)
  403. {
  404. lat += 0.1;
  405. if (flag < 4)
  406. flag = 4;
  407. continue;
  408. }
  409. else if (dto > 2)
  410. {
  411. lat += 0.05;
  412. if (flag < 5)
  413. flag = 5;
  414. continue;
  415. }
  416. flag = 10;
  417. list.Add((lon, lat, dto));
  418. }
  419. if (list.Any())
  420. {
  421. var p1 = list.OrderBy(p => p.Item3).FirstOrDefault();
  422. list2.Add(p1);
  423. //var p2 = list.Where(p => p.Item3 < 0.01 && PhysicsHelper.DistanceGeo((p.Item1, p.Item2, 0), p1) > 5000).OrderBy(p => p.Item3).FirstOrDefault();
  424. //if (p2 != default)
  425. // list2.Add(p2);
  426. }
  427. else
  428. {
  429. if (flag == 1)
  430. lon += 1;
  431. else if (flag == 2)
  432. lon += 0.5;
  433. else if (flag == 3)
  434. lon += 0.2;
  435. else if (flag == 4)
  436. lon += 0.1;
  437. else if (flag == 5)
  438. lon += 0.05;
  439. }
  440. list.Clear();
  441. }
  442. return list2.Select(p => (p.Item1, p.Item2)).OrderBy(p => PhysicsHelper.DistanceGeo((1, 1, 0), (1, 1, 9)));
  443. }
  444. }
  445. }