| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 | using System;using System.Collections.Generic;using System.Diagnostics;using System.IO;using System.Linq;using System.Runtime.InteropServices;using System.Text;using DW5S.Entity;namespace DW5S.KxcApi{    public class DrawDtoLineHelper    {        private const string XdtsDll = @"AddIns\时差线\Positioning.dll";        [DllImport(XdtsDll, EntryPoint = "CurveByTwoTDOA", CallingConvention = CallingConvention.Cdecl)]//高轨双星有参时差线        public extern static void CurveByTwoTDOA(double[] main_sat_pos, double[] neigh_sat_pos, double[] rec1_pos, double[] rec2_pos, double[] ref_pos, double[] Zone,      double target_dto, double ref_dto, out IntPtr LOP_Value, ref int LOP_Len);        /*	双星时差线-无参	LOP_Value 返回值 结构参考DTO_Plot	LOP_Len*3为LOP_Value的长度	*/        [DllImport(XdtsDll, EntryPoint = "CurveByTwoTDOAWithNoRef", CallingConvention = CallingConvention.Cdecl)]//高轨双星无参时差线        public extern static void CurveByTwoTDOAWithNoRef(double[] main_sat_pos, double[] neigh_sat_pos, double[] rec1_pos, double[] rec2_pos,            double[] Zone, double target_dto, out IntPtr LOP_Value, ref int LOP_Len);        [DllImport(XdtsDll, CallingConvention = CallingConvention.Cdecl)]        public static extern void Destory(IntPtr val);        private const string exeName = "XingDiSCX.exe";//星地时差线                                                       // private static double[] zone = new double[] { -85, 85, -180, 180 }; //定位区域        /// <summary>        /// 星地有参时差线        /// </summary>        /// <param name="opt"></param>        /// <returns></returns>        /// <exception cref="Exception"></exception>        public static IEnumerable<(double lon, double lat)> DtoLineXd(DtoLineXdOption opt)        {            List<DtoLinePoint> list = new List<DtoLinePoint>();            string file = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AddIns\\时差线\\DtoLine.dat");            string exePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AddIns\\时差线");            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}]不存在");            List<string> arguments = new List<string>            {                file,                $"{opt.MsEph[0]}",                $"{opt.MsEph[1]}",                $"{opt.MsEph[2]}",                $"{opt.MsAnt[0]}",                $"{opt.MsAnt[1]}",                $"{opt.CDBAnt[0]}",                $"{opt.CDBAnt[1]}",                $"{opt.RefGeod[0]}",                $"{opt.RefGeod[1]}",                $"{opt.xdDto}",                $"{opt.RefDto}",                $"{opt.PosLon}",                $"{opt.PosLat}"            };            Process p = new Process();            p.StartInfo.WorkingDirectory = exePath;            p.StartInfo.FileName = exeFile;            p.StartInfo.Arguments = string.Join(" ", arguments);            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}]超时未完成!");            }            string result = p.StandardOutput.ReadToEnd();            if (string.IsNullOrWhiteSpace(result))            {                throw new Exception("计算时差线出现未知错误!");            }            var array = result.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);            if (array[0] == "1")            {                throw new Exception(array[1]);            }            if (File.Exists(file))            {                var dtostr = File.ReadAllText(file);                list = Newtonsoft.Json.JsonConvert.DeserializeObject<List<DtoLinePoint>>(dtostr);            }            var Lines = list.Select(s => (s.Lon, s.Lat));            return Lines;        }        ///// <summary>        ///// 星地有参时差线        ///// </summary>        ///// <param name="opt"></param>        ///// <returns></returns>        ///// <exception cref="Exception"></exception>        //public static IEnumerable<(double lon, double lat)> DtoLineXdEx(DtoLineXdOption opt)        //{        //    List<DtoLinePoint> list = new List<DtoLinePoint>();        //    IntPtr LOP_ValuePtr;        //    int LOP_Len = 0;        //    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);        //    double[] LOP_Value = new double[LOP_Len];        //    if (LOP_Len > 0)        //    {        //        Marshal.Copy(LOP_ValuePtr, LOP_Value, 0, LOP_Value.Length);        //    }        //    GDOPApi.FreeGDOPBuf(LOP_ValuePtr);        //    var points = ParseResult(LOP_Value);        //    var mapDots = points.Select(p => p).Select(p => (p.Lon, p.Lat));        //    return mapDots;        //}        /// <summary>        /// 星地有参时差线        /// </summary>        /// <param name="opt"></param>        /// <returns></returns>        /// <exception cref="Exception"></exception>        public static IEnumerable<DtoLine> DtoLineXdNew(DtoLineXdOption opt)        {            List<DtoLine> list = new List<DtoLine>();            IntPtr LOP_ValuePtr;            IntPtr ResLen;            int LineCount = 0;            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);            int[] res_Len = new int[LineCount];            if (LineCount > 0)            {                Marshal.Copy(ResLen, res_Len, 0, res_Len.Length);                int total = res_Len.Sum(r => r);                double[] LOP_Value = new double[total * 2];                Marshal.Copy(LOP_ValuePtr, LOP_Value, 0, LOP_Value.Length);                var points = ParseResult(LOP_Value);                int skipcount = 0;                for (int i = 0; i < LineCount; i++)                {                    int pointcount = res_Len[i];                    skipcount = i == 0 ? 0 : skipcount + res_Len[i-1];                    var mapDots=  points.Skip(skipcount).Take(pointcount);                    DtoLine dtoLine = new DtoLine();                    dtoLine.dtoLinePoints = mapDots.Select(p => p).Select(p => (p.Lon, p.Lat));                    list.Add(dtoLine);                }            }            GDOPApi.FreeGDOPBuf(ResLen);            GDOPApi.FreeGDOPBuf(LOP_ValuePtr);            return list;        }        private static List<MapDot> ParseResult(double[] ponits)        {            List<MapDot> mapDots = new List<MapDot>();            int count = 2;            for (int i = 0; i < ponits.Length / count; i++)            {                MapDot mapDot = new MapDot();                mapDot.Lon = ponits[count * i];                mapDot.Lat = ponits[count * i + 1];//0 1  2  3  4 5 6 7                mapDots.Add(mapDot);            }            return mapDots;        }        /// <summary>        /// 星地无参时差线        /// </summary>        /// <param name="opt"></param>        /// <returns></returns>        /// <exception cref="Exception"></exception>        public static IEnumerable<(double lon, double lat)> DtoLineXdNoRefEx(DtoLineXdOption opt)        {            List<DtoLinePoint> list = new List<DtoLinePoint>();            IntPtr LOP_ValuePtr;            int LOP_Len = 0;            GDOPApi.SCX_XD_NoRef(opt.MsEph, opt.MsAnt, opt.CDBAnt, opt.xdDto * 1e-6, ref LOP_Len, out LOP_ValuePtr);            double[] LOP_Value = new double[LOP_Len];            if (LOP_Len > 0)            {                Marshal.Copy(LOP_ValuePtr, LOP_Value, 0, LOP_Value.Length);            }            GDOPApi.FreeGDOPBuf(LOP_ValuePtr);            var points = ParseResult(LOP_Value);            var mapDots = points.Select(p => p).Select(p => (p.Lon, p.Lat));            return mapDots;        }        /// <summary>        /// 星地无参时差线        /// </summary>        /// <param name="opt"></param>        /// <returns></returns>        /// <exception cref="Exception"></exception>        public static IEnumerable<DtoLine> DtoLineXdNoRefNew(DtoLineXdOption opt)        {            List<DtoLine> list = new List<DtoLine>();            IntPtr LOP_ValuePtr;            IntPtr ResLen;            int LineCount = 0;            GDOPApi.SCX_XD_NoRef_new(opt.MsEph, opt.MsAnt, opt.CDBAnt, opt.xdDto * 1e-6, ref LineCount, out ResLen, out LOP_ValuePtr);            int[] res_Len = new int[LineCount];            if (LineCount > 0)            {                Marshal.Copy(ResLen, res_Len, 0, res_Len.Length);                int total = res_Len.Sum(r => r);                double[] LOP_Value = new double[total * 2];                Marshal.Copy(LOP_ValuePtr, LOP_Value, 0, LOP_Value.Length);                var points = ParseResult(LOP_Value);                int skipcount = 0;                for (int i = 0; i < LineCount; i++)                {                    int pointcount = res_Len[i];                    skipcount = i == 0 ? 0 : skipcount + res_Len[i - 1];                    var mapDots = points.Skip(skipcount).Take(pointcount);                    DtoLine dtoLine = new DtoLine();                    dtoLine.dtoLinePoints = mapDots.Select(p => p).Select(p => (p.Lon, p.Lat));                    list.Add(dtoLine);                }            }            GDOPApi.FreeGDOPBuf(ResLen);            GDOPApi.FreeGDOPBuf(LOP_ValuePtr);            return list;        }        public static IEnumerable<(double lon, double lat)> DtoLineXdNoRefZl(DtoLineXdOption opt)        {            double startLon = (int)opt.CDBAnt[0] - 30;            double endLon = (int)opt.CDBAnt[0] + 30;            double startLat = (int)opt.CDBAnt[1] - 30;            double endLat = (int)opt.CDBAnt[1] + 30;            List<(double, double, double)> list2 = new List<(double, double, double)>();            var recXYZ = PhysicsHelper.GeoToEcef((opt.MsAnt[0], opt.MsAnt[1], opt.MsAnt[2]));            var cdbXYZ = PhysicsHelper.GeoToEcef((opt.CDBAnt[0], opt.CDBAnt[1], opt.CDBAnt[2]));            for (double lon = startLon; lon < endLon; lon += 0.01)            {                List<(double, double, double)> list = new List<(double, double, double)>();                int flag = 0;                for (double lat = startLat; lat < endLat; lat += 0.01)                {                    var posXYZ = PhysicsHelper.GeoToEcef((lon, lat, 0));                    //目标-主星-接收站的时间(us)                    var dt1 = PhysicsHelper.Dto(posXYZ, (opt.MsEph[0], opt.MsEph[1], opt.MsEph[2]), recXYZ) * 1e6;                    //目标-超短站的时间(us)                    var dt2 = PhysicsHelper.Dto(posXYZ, cdbXYZ) * 1e6;                    var dto = Math.Abs(dt1 - dt2 - opt.xdDto);                    if (dto > 100)                    {                        lat += 1;                        if (flag < 1)                            flag = 1;                        continue;                    }                    else if (dto > 50)                    {                        lat += 0.5;                        if (flag < 2)                            flag = 2;                        continue;                    }                    else if (dto > 20)                    {                        lat += 0.2;                        if (flag < 3)                            flag = 3;                        continue;                    }                    else if (dto > 5)                    {                        lat += 0.1;                        if (flag < 4)                            flag = 4;                        continue;                    }                    else if (dto > 2)                    {                        lat += 0.05;                        if (flag < 5)                            flag = 5;                        continue;                    }                    flag = 10;                    list.Add((lon, lat, dto));                }                if (list.Any())                {                    var p1 = list.OrderBy(p => p.Item3).FirstOrDefault();                    list2.Add(p1);                    var p2 = list.Where(p => p.Item3 < 0.01 && PhysicsHelper.DistanceGeo((p.Item1, p.Item2, 0), p1) > 5000).OrderBy(p => p.Item3).FirstOrDefault();                    if (p2 != default)                        list2.Add(p2);                }                else                {                    if (flag == 1)                        lon += 1;                    else if (flag == 2)                        lon += 0.5;                    else if (flag == 3)                        lon += 0.2;                    else if (flag == 4)                        lon += 0.1;                    else if (flag == 5)                        lon += 0.05;                }                list.Clear();            }            return list2.Select(p => (p.Item1, p.Item2)).OrderBy(p => p.Item1).OrderBy(p => p.Item2);        }        /// <summary>        /// 高轨双星时差线        /// </summary>        /// <param name="opt"></param>        /// <returns></returns>        public static IEnumerable<(double lon, double lat)> DtoLine2XStart(DtoLineTwoStartOption opt)        {            List<DtoLinePoint> list = new List<DtoLinePoint>();            IntPtr LOP_ValuePtr;            int LOP_Len = 0;            CurveByTwoTDOA(                opt.MsEph,                 opt.NsEph,                 opt.MsAnt,                 opt.NsAnt,                opt.RefGeod,                 new double[] { -85, 85, -180, 180 },                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);            }            Destory(LOP_ValuePtr);            var Lines = list.Select(p => (p.Lon, p.Lat));            return Lines;        }        public static IEnumerable<(double lon, double lat)> DtoLine2XNoRefStart(DtoLineTwoStartOption opt)        {            List<DtoLinePoint> list = new List<DtoLinePoint>();            IntPtr LOP_ValuePtr;            int LOP_Len = 0;            CurveByTwoTDOAWithNoRef(                opt.MsEph,                 opt.NsEph,                 opt.MsAnt,                 opt.NsAnt,                 new double[] { -85, 85, -180, 180 },                opt.TargetDto * 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);            }            Destory(LOP_ValuePtr);            var Lines = list.Select(p => (p.Lon, p.Lat));            return Lines;        }        public static IEnumerable<(double lon, double lat)> DtoLine2XNoRefStartZl(DtoLineTwoStartOption opt)        {            double startLon = -180;            double endLon = 180;            double startLat = -80;            double endLat = 80;            List<(double, double, double)> list2 = new List<(double, double, double)>();            var recXYZ = PhysicsHelper.GeoToEcef((opt.MsAnt[0], opt.MsAnt[1], opt.MsAnt[2]));            for (double lon = startLon; lon < endLon; lon += 0.01)            {                List<(double, double, double)> list = new List<(double, double, double)>();                int flag = 0;                for (double lat = startLat; lat < endLat; lat += 0.01)                {                    var posXYZ = PhysicsHelper.GeoToEcef((lon, lat, 0));                    //目标-主星-接收站的时间(us)                    var dt1 = PhysicsHelper.Dto(posXYZ, (opt.MsEph[0], opt.MsEph[1], opt.MsEph[2]), recXYZ) * 1e6;                    //目标-邻星-接收站的时间(us)                    var dt2 = PhysicsHelper.Dto(posXYZ, (opt.NsEph[0], opt.NsEph[1], opt.NsEph[2]), recXYZ) * 1e6;                    var dto = Math.Abs(dt1 - dt2 - opt.TargetDto);                    if (dto > 100)                    {                        lat += 1;                        if (flag < 1)                            flag = 1;                        continue;                    }                    else if (dto > 50)                    {                        lat += 0.5;                        if (flag < 2)                            flag = 2;                        continue;                    }                    else if (dto > 20)                    {                        lat += 0.2;                        if (flag < 3)                            flag = 3;                        continue;                    }                    else if (dto > 5)                    {                        lat += 0.1;                        if (flag < 4)                            flag = 4;                        continue;                    }                    else if (dto > 2)                    {                        lat += 0.05;                        if (flag < 5)                            flag = 5;                        continue;                    }                    flag = 10;                    list.Add((lon, lat, dto));                }                if (list.Any())                {                    var p1 = list.OrderBy(p => p.Item3).FirstOrDefault();                    list2.Add(p1);                    //var p2 = list.Where(p => p.Item3 < 0.01 && PhysicsHelper.DistanceGeo((p.Item1, p.Item2, 0), p1) > 5000).OrderBy(p => p.Item3).FirstOrDefault();                    //if (p2 != default)                    //    list2.Add(p2);                }                else                {                    if (flag == 1)                        lon += 1;                    else if (flag == 2)                        lon += 0.5;                    else if (flag == 3)                        lon += 0.2;                    else if (flag == 4)                        lon += 0.1;                    else if (flag == 5)                        lon += 0.05;                }                list.Clear();            }            return list2.Select(p => (p.Item1, p.Item2)).OrderBy(p => PhysicsHelper.DistanceGeo((1, 1, 0), (1, 1, 9)));        }    }}
 |