using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Runtime.InteropServices; using System.Security.Policy; using System.Text; using System.Threading.Tasks; using XdCxRhDW.Entity; namespace XdCxRhDW.Api { public static class LeoPosApi { //低轨道单星和双星定位 private const string leoPos = @"AddIns\低轨\DLL_XDXZ.dll"; private static double[] zone = new double[] { -85, 85, -180, 180 }; //定位区域 /// /// 地轨双星dw /// /// /// /// /// /// /// /// /// /// /// /// [DllImport(leoPos, EntryPoint = "TwoStar_DTFO_DW", CallingConvention = CallingConvention.Cdecl)] public extern static void TwoStar_DTFO_DW(double[] main_sat, double[] neigh_sat, double[] Ref_Station_LLH , double[] Zone, double target_dto, double target_dfo, double ref_dto, double ref_dfo, double fu1, double fu2, double[] target_llh); /// /// 单星dw /// /// 第一时刻星历 长度6 /// 第二时刻星历 长度6 /// 第三时刻星历 长度6 /// /// 频差1(Hz) /// 频差2(Hz) /// 上行频点(Hz) /// [DllImport(leoPos, EntryPoint = "SingleStar_DFO_DW", CallingConvention = CallingConvention.Cdecl)] public extern static void SingleStar_DFO_DW(double[] main_sat, double[] neigh_sat1, double[] neigh_sat2 , double[] Zone, double target_dfo1, double target_dfo2, double fu, double[] target_llh); /// /// 低轨双星时差线 /// /// 主星星历 长度6 /// 邻星星历 长度6 /// 参考站位置 /// -85, 85, -180, 180 /// 目标时差(s) /// 参考时差(s) /// /// [DllImport(leoPos, EntryPoint = "TwoStar_SCX", CallingConvention = CallingConvention.Cdecl)] public extern static void TwoStar_SCX(double[] main_sat_pos, double[] neigh_sat_pos, double[] ref_pos, double[] Zone, double target_dto, double ref_dto, out IntPtr LOP_Value, ref int LOP_Len); /// /// 低轨双星频差线 /// /// /// /// /// /// 目标频差(Hz) /// 参考频差(Hz) /// 上行频点1(Hz) /// 上行频点2(Hz) /// /// [DllImport(leoPos, EntryPoint = "TwoStar_PCX", CallingConvention = CallingConvention.Cdecl)] public extern static void TwoStar_PCX(double[] main_sat, double[] neigh_sat, double[] ref_pos, double[] Zone, double target_dfo, double ref_dfo, double fu1, double fu2, out IntPtr LOP_Value, ref int LOP_Len); /// /// 单星频差线 /// /// /// /// /// /// /// /// [DllImport(leoPos, EntryPoint = "SingleStar_PCX", CallingConvention = CallingConvention.Cdecl)] public extern static void SingleStar_PCX(double[] main_sat, double[] neigh_sat , double[] Zone, double target_dfo, double fu, out IntPtr LOP_Value, ref int LOP_Len); public static double[] X1_POS(CgRes cg, double upfreqHz) { double[] mainSat = new double[6] { cg.MainX.Value, cg.MainY.Value, cg.MainZ.Value, cg.MainVx.Value, cg.MainVy.Value, cg.MainVz.Value }; double[] adjaSat1 = new double[6] { cg.Adja1X.Value, cg.Adja1Y.Value, cg.Adja1Z.Value, cg.Adja1Vx.Value, cg.Adja1Vy.Value, cg.Adja1Vz.Value }; double[] adjaSat2 = new double[6] { cg.Adja2X.Value, cg.Adja2Y.Value, cg.Adja2Z.Value, cg.Adja2Vx.Value, cg.Adja2Vy.Value, cg.Adja2Vz.Value }; double[] zone = new double[] { -85, 85, -180, 180 }; //定位区域 double[] res = new double[6]; SingleStar_DFO_DW(mainSat, adjaSat1, adjaSat2, zone, cg.Dfo1.Value, cg.Dfo2.Value, upfreqHz, res); var posRes = ConvertToGeoPoint(res); if (posRes[1] < 5 && posRes[4] > 10 && posRes[4] < 30) { var p0 = posRes[0]; var p1 = posRes[1]; var p2 = posRes[2]; posRes[0] = posRes[3]; posRes[1] = posRes[4]; posRes[2] = posRes[5]; posRes[3] = p0; posRes[4] = p1; posRes[5] = p2; } return posRes; } /// /// /// /// /// /// 目标上行频点 /// 参考上行频点 /// public static double[] X2_POS(CgRes cg, StationRes sRes, double upfreqHz1, double upfreqHz2) { double[] refStation = new double[3] { sRes.RefLon.Value, sRes.RefLat.Value, 0 }; double[] mainSat = new double[6] { cg.MainX.Value, cg.MainY.Value, cg.MainZ.Value, cg.MainVx.Value, cg.MainVy.Value, cg.MainVz.Value }; double[] adjaSat1 = new double[6] { cg.Adja1X.Value, cg.Adja1Y.Value, cg.Adja1Z.Value, cg.Adja1Vx.Value, cg.Adja1Vy.Value, cg.Adja1Vz.Value }; double[] zone = new double[] { -85, 85, -180, 180 }; //定位区域 double[] res = new double[6]; var refDto = (cg.YbMainDto.Value - cg.YbAdja1Dto.Value) / 1e6; var refDfo = cg.YbMainDfo.Value - cg.YbAdja1Dfo.Value; TwoStar_DTFO_DW(mainSat, adjaSat1, refStation, zone, cg.Dto1.Value / 1e6, cg.Dfo1.Value, refDto, refDfo, upfreqHz1, upfreqHz2, res); var posRes = ConvertToGeoPoint(res); if (posRes[1] < 5 && posRes[4] > 10 && posRes[4] < 30) { var p0 = posRes[0]; var p1 = posRes[1]; var p2 = posRes[2]; posRes[0] = posRes[3]; posRes[1] = posRes[4]; posRes[2] = posRes[5]; posRes[3] = p0; posRes[4] = p1; posRes[5] = p2; } return posRes; } private static double[] ConvertToGeoPoint(double[] res) { if (res == null || res.Length == 0) { return new double[7] { 999, 999, 0, 999, 999, 0, -1 }; } else if (res.Length != 3 && res.Length != 6) { throw new Exception("定位结果解析异常,长度不是3或6"); } var list = res.Select(p => Math.Round(p, 4)).ToArray(); if (list.Length == 3) { list = list.Concat(new double[4] { 999, 999, 0, -1 }).ToArray(); } list[2] = list[5] = 0;//高度 if (double.IsNaN(list[0]) || double.IsNaN(list[1])) { list[0] = list[1] = 999; } if (double.IsNaN(list[3]) || double.IsNaN(list[4])) { list[3] = list[4] = 999; } if (list[0] < -180 || list[0] > 180) { list[0] = list[1] = 999; } else if (list[1] < -90 || list[1] > 90) { list[0] = list[1] = 999; } if (list[3] < -180 || list[3] > 180) { list[3] = list[4] = 999; } else if (list[4] < -90 || list[4] > 90) { list[3] = list[4] = 999; } if (list.Length == 6) { var listNew = list.ToList(); listNew.Add(-1); list = listNew.ToArray(); } return list; } public static IEnumerable<(double lon, double lat)> DtoLineLeoX2(DtoLineTwoStartOption opt) { List list = new List(); IntPtr LOP_ValuePtr; int LOP_Len = 0; TwoStar_SCX( opt.MsEph, opt.NsEph, opt.RefGeod, zone, opt.TargetDto * 1e-6, opt.RefDto * 1e-6, out LOP_ValuePtr, ref LOP_Len); double[] LOP_Value = new double[LOP_Len * 3]; if (LOP_Len > 0) { Marshal.Copy(LOP_ValuePtr, LOP_Value, 0, LOP_Value.Length); list = OutputHelper.WriteDtoLine(LOP_Value, LOP_Len); } var Lines = list.Select(p => (p.Lon, p.Lat)); return Lines; } public static IEnumerable<(double lon, double lat)> DfoLineLeo2(LeoDfoLineTwo opt) { IntPtr LOP_ValuePtr; int LOP_Len = 0; TwoStar_PCX( opt.MsEph, opt.NsEph, opt.RefGeod, zone, opt.TargetDfo, opt.RefDfo, opt.fu1, opt.fu2, out LOP_ValuePtr, ref LOP_Len); return ParseResult(LOP_ValuePtr, LOP_Len); } public static IEnumerable<(double lon, double lat)> DfoLineLeoX1(double[] main_sat, double[] neigh_sat, double target_dfo, double fu) { IntPtr LOP_ValuePtr; int LOP_Len = 0; SingleStar_PCX(main_sat, neigh_sat , zone, target_dfo, fu, out LOP_ValuePtr, ref LOP_Len); return ParseResult(LOP_ValuePtr, LOP_Len); } private static IEnumerable<(double lon, double lat)> ParseResult(IntPtr LOP_ValuePtr, int LOP_Len) { List list = new List(); double[] LOP_Value = new double[LOP_Len * 3]; if (LOP_Len > 0) { Marshal.Copy(LOP_ValuePtr, LOP_Value, 0, LOP_Value.Length); for (int idx = 0; idx < LOP_Len; ++idx) { if (LOP_Value[3 * idx + 1] != -1) { list.Add(new DtoLinePoint() { Lon = LOP_Value[3 * idx + 1], Lat = LOP_Value[3 * idx] }); } } for (int idx = 0; idx < LOP_Len; ++idx) { if (LOP_Value[3 * idx + 2] != -1) { list.Add(new DtoLinePoint() { Lon = LOP_Value[3 * idx + 2], Lat = LOP_Value[3 * idx] }); } } } var Lines = list.Select(p => (p.Lon, p.Lat)); return Lines; } } }