using Unity.Mathematics; using System.Drawing; using System.Text; using BHJD.DEMdll.Public; using Newtonsoft.Json; namespace QuYuSaoMiao { public class LimitedConcurrencyLevelTaskScheduler : TaskScheduler { /// Whether the current thread is processing work items. [ThreadStatic] private static bool _currentThreadIsProcessingItems; /// The list of tasks to be executed. private readonly LinkedList _tasks = new LinkedList(); // protected by lock(_tasks) /// The maximum concurrency level allowed by this scheduler. private readonly int _maxDegreeOfParallelism; /// Whether the scheduler is currently processing work items. private int _delegatesQueuedOrRunning = 0; // protected by lock(_tasks) /// /// Initializes an instance of the LimitedConcurrencyLevelTaskScheduler class with the /// specified degree of parallelism. /// /// The maximum degree of parallelism provided by this scheduler. public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism) { if (maxDegreeOfParallelism < 1) throw new ArgumentOutOfRangeException("maxDegreeOfParallelism"); _maxDegreeOfParallelism = maxDegreeOfParallelism; } /// /// current executing number; /// public int CurrentCount { get; set; } /// Queues a task to the scheduler. /// The task to be queued. protected sealed override void QueueTask(Task task) { // Add the task to the list of tasks to be processed. If there aren't enough // delegates currently queued or running to process tasks, schedule another. lock (_tasks) { //Console.WriteLine("Task Count : {0} ", _tasks.Count); _tasks.AddLast(task); if (_delegatesQueuedOrRunning < _maxDegreeOfParallelism) { ++_delegatesQueuedOrRunning; NotifyThreadPoolOfPendingWork(); } } } int executingCount = 0; private static object executeLock = new object(); /// /// Informs the ThreadPool that there's work to be executed for this scheduler. /// private void NotifyThreadPoolOfPendingWork() { ThreadPool.UnsafeQueueUserWorkItem(_ => { // Note that the current thread is now processing work items. // This is necessary to enable inlining of tasks into this thread. _currentThreadIsProcessingItems = true; try { // Process all available items in the queue. while (true) { Task item; lock (_tasks) { // When there are no more items to be processed, // note that we're done processing, and get out. if (_tasks.Count == 0) { --_delegatesQueuedOrRunning; break; } // Get the next item from the queue item = _tasks.First.Value; _tasks.RemoveFirst(); } // Execute the task we pulled out of the queue base.TryExecuteTask(item); } } // We're done processing items on the current thread finally { _currentThreadIsProcessingItems = false; } }, null); } /// Attempts to execute the specified task on the current thread. /// The task to be executed. /// /// Whether the task could be executed on the current thread. protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) { // If this thread isn't already processing a task, we don't support inlining if (!_currentThreadIsProcessingItems) return false; // If the task was previously queued, remove it from the queue if (taskWasPreviouslyQueued) TryDequeue(task); // Try to run the task. return base.TryExecuteTask(task); } /// Attempts to remove a previously scheduled task from the scheduler. /// The task to be removed. /// Whether the task could be found and removed. protected sealed override bool TryDequeue(Task task) { lock (_tasks) return _tasks.Remove(task); } /// Gets the maximum concurrency level supported by this scheduler. public sealed override int MaximumConcurrencyLevel { get { return _maxDegreeOfParallelism; } } /// Gets an enumerable of the tasks currently scheduled on this scheduler. /// An enumerable of the tasks currently scheduled. protected sealed override IEnumerable GetScheduledTasks() { bool lockTaken = false; try { Monitor.TryEnter(_tasks, ref lockTaken); if (lockTaken) return _tasks.ToArray(); else throw new NotSupportedException(); } finally { if (lockTaken) Monitor.Exit(_tasks); } } } public class Height { public string msg { get; set; } public int code { get; set; } public double data { get; set; } } public class TXResult { public double FirstOneReadyTime { get; set; } public double FirstOneArriveTime { get; set; } public double FirstOneMaxCover { get; set; } public int SingleMaxConnect { get; set; }//仅最大一架,单架输出另立列表 public double AverageTotalCover { get; set; } public double FullCoverTime { get; set; } public int MaxTotalConnect { get; set; } public double ConnectTimeRatio { get; set; } public double UnitFulfilledRatio { get; set; } public string Stability { get; set; } public string Robustness { get; set; } public string Security { get; set; } } public class YJTX { //public static DemHelper DemHelper()//00 // { // IDbHelper db = Factory.Load("10.130.100.5", "5432", "postgres", "postgres", "rescue_patrol_platform"); // DemHelper ddemHelper = new DemHelper(db); // return ddemHelper; // } public static double[,] MaxMinPoly(List poly)//01多边形矩形边界 { List PolyLon = new List(); List PolyLat = new List(); foreach (double[] element in poly) { PolyLon.Add(element[0]); PolyLat.Add(element[1]); } double[,] MM1 = new double[2, 2]; MM1[0, 0] = PolyLon.Min();//经度最小(西界) MM1[0, 1] = PolyLon.Max();//经度最大(东界) MM1[1, 0] = PolyLat.Min();//纬度最小(南界) MM1[1, 1] = PolyLat.Max();//纬度最大(北界) return MM1; } public static bool isinpoly(double[] zuobiao, List poly, DemHelper demHelper)//02已经替换成在边界内算法 { double[,] polyOut = MaxMinPoly(poly); if (zuobiao[0] <= polyOut[0, 0] || zuobiao[0] >= polyOut[0, 1] || zuobiao[1] <= polyOut[1, 0] || zuobiao[1] >= polyOut[1, 1]) { return false; } else { string polystring = "MULTIPOLYGON((("; foreach (double[] element in poly) { double e0 = element[0]; double e1 = element[1]; polystring = polystring + element[0] + " " + element[1] + ","; } polystring = polystring + poly[0][0] + " " + poly[0][1] + ")))"; string pointstring = "POINT (" + zuobiao[0] + " " + zuobiao[1] + ")"; // Console.WriteLine("isinpoly?"); //Console.WriteLine(pointstring+polystring); string r1 = demHelper.doDetermine(pointstring, polystring); // Console.WriteLine(r1); //double[,] polyOut = MaxMinPoly(poly); //if (zuobiao[0] <= polyOut[0, 0] || zuobiao[0] >= polyOut[0, 1] || zuobiao[1] <= polyOut[1, 0] || zuobiao[1] >= polyOut[1, 1]) // { return false; } // else //{ return (r1 == "True" ? true : false); // } } } //03格点生成方法[已删除]:输入前四个为经纬度上下限,数组为多边形,后两个是经纬度分辨率。输出0经,1纬,2高,3是否被侦察的【01】变量。 //04格点初始化[已删除] //05格点显示【已删除】,可以不用 //06两点间距计算,输出米 public static double distance(double[] P1, double[] P2, DemHelper demHelper) { //double DL = 6371.004 * Math.Acos(Math.Sin(Math.PI / 180 * P1[1]) * Math.Sin(Math.PI / 180 * P2[1]) + Math.Cos(Math.PI / 180 * P1[1]) * Math.Cos(Math.PI / 180 * P2[1]) * Math.Cos(Math.PI / 180 * (P1[0] - P2[0]))) * 1000; //double D = Math.Pow(Math.Pow(DL, 2) + Math.Pow(P1[2] - P2[2], 2), 0.5); //return D; double3 p1 = new double3(); double3 p2 = new double3(); p1.x = P1[0]; p1.y = P1[1]; p1.z = P1[2]; p2.x = P2[0]; p2.y = P2[1]; p2.z = P2[2]; double D1 = demHelper.getDistance(p1, p2); //double DD1 = D1; //Console.WriteLine("距离:" + D1); return D1; } //07两点间距计算,(本地版),输出米 public static double distance1(double[] P1, double[] P2) { double DL = 6371.004 * Math.Acos(Math.Sin(Math.PI / 180 * P1[1]) * Math.Sin(Math.PI / 180 * P2[1]) + Math.Cos(Math.PI / 180 * P1[1]) * Math.Cos(Math.PI / 180 * P2[1]) * Math.Cos(Math.PI / 180 * (P1[0] - P2[0]))) * 1000; double D = Math.Pow(Math.Pow(DL, 2) + Math.Pow(P1[2] - P2[2], 2), 0.5); return D; } //08两点间高度角计算,从P1到P2,角度制 public static double angleH(double[] P1, double[] P2) { if (P1[2] == P2[2]) { return 0; } else if (P1[0] == P2[0] && P1[1] == P2[1]) { if (P1[2] < P2[2]) { return 90; } else { return -90; } } else { //if (P1[2] < P2[2]) //{ double angleH = Math.Asin((P2[2] - P1[2]) / distance1(P1, P2)) * (180 / Math.PI); return angleH; //} //else //{ // double angleH = Math.Asin((P2[2] - P1[2]) / distance(P1, P2)) * (180 / Math.PI); // return angleH; //} } } //09MoveTo,输入单位坐标、目标坐标,输出时步结束时的单位坐标【暂不用】 public static double[] MoveTo(double[] aircraft, double[] target, double V, double TimeStep, DemHelper demHelper) { double[] direction = { (target[0] - aircraft[0]) / distance(aircraft, target, demHelper), (target[1] - aircraft[1]) / distance(aircraft, target, demHelper), (target[2] - aircraft[2]) / distance(aircraft, target, demHelper) }; double[] delta = { direction[0] * V * TimeStep, direction[1] * V * TimeStep, direction[2] * V * TimeStep }; double[] next = { aircraft[0] + delta[0], aircraft[1] + delta[1], aircraft[2] + delta[2] }; return next; } public static bool isBlocked(double[] P1, double[] P2, DemHelper demHelper)//10是否被地形遮挡 { double3 p1 = new double3(); double3 p2 = new double3(); p1.x = P1[0]; p1.y = P1[1]; p1.z = P1[2]; p2.x = P2[0]; p2.y = P2[1]; p2.z = P2[2]; string r2 = demHelper.doIntervisibility(p1, p2);//这三行代码用于运行判定 // Console.WriteLine("r2="+r2); return (r2 == "true" ? false : true); //return false; } //11是否符合观察条件【已删除】 //12航线转object【暂不用】 public static List RouteInput(string TurningPointName, List TurningPointLocation, string TurningPointType, double TurningPointVelocity, double SegmentFlightFuelConsumption, double SegmentFlightTime, double TurningRadius) { List SCIP = new List(); int i = 0; foreach (double[] element in TurningPointLocation) { object[] SCIPtemt = { $"{TurningPointName}{i}", element, $"{TurningPointType}", TurningPointVelocity, SegmentFlightFuelConsumption, SegmentFlightTime, TurningRadius }; SCIP.Add(SCIPtemt); i++; } return SCIP; } //13航线显示,不用管【暂不用】 public static void ListscanRoute(List SCtoRead) { Console.WriteLine("【showSC】"); foreach (double[] element in SCtoRead) { string lontax = element[0].ToString("F5"); string lattax = element[1].ToString("F5"); Console.WriteLine("【E" + lontax + " | N" + lattax + " | h" + element[2] + "】\t"); } } public static double HeightLL(double lon, double lat)//14经纬度提取高程 { string req = "http://10.130.100.5:7785//rescue-platform-service/api/v1/dem/getInfos?lon="; req += lon; req += "&lat="; req += lat; var client = new HttpClient(); //var request = new HttpRequestMessage(HttpMethod.Get, "http://10.130.100.5:7785//rescue-platform-service/api/v1/dem/getInfos?lon=115.32&lat=38.26"); var request = new HttpRequestMessage(HttpMethod.Get, req); var response = client.Send(request); response.EnsureSuccessStatusCode(); string BBB = ""; if (response.IsSuccessStatusCode) { string content = response.Content.ReadAsStringAsync().Result; // 同步阻塞调用 BBB = content; //Console.WriteLine(content); } Height data = JsonConvert.DeserializeObject(BBB); //Console.WriteLine("AAA"); //string BBB =await response.Content.ReadAsStringAsync(); Console.WriteLine("lo" + lon + "la" + lat + "h" + data.data); return data.data; } //15.字符串提取数字段 public static List intList(string intString)//示例:"1,3-5" { intString += ","; List intList = new List(); int Length = intString.Length; string reading = ""; string ii = ""; int head = new int(); int tail = new int(); bool isSingle = new bool(); for (int i = 0; i < Length; i++) { reading += intString[i]; ii += intString[i]; if (int.TryParse(reading, out int result) == true) { } else if (ii == "," && isSingle == true) { string readingNum = reading.Remove(reading.Length - 1); int adding = int.Parse(readingNum); intList.Add(adding); reading = ""; } else if (ii == "-") { string readingNum = reading.Remove(reading.Length - 1); head = int.Parse(readingNum); isSingle = false; reading = ""; } else if (ii == "," && isSingle == false) { string readingNum = reading.Remove(reading.Length - 1); tail = int.Parse(readingNum); for (int j = head; j <= tail; j++) { intList.Add(j); } isSingle = true; reading = ""; } else { Console.WriteLine("int列表转换的字符串有非法字符,仅支持整数、“,”、“-”,无空格"); } ii = ""; } //foreach(int i in intList) { Console.WriteLine("int:"+i); } return intList; } //16.环形航线坐标更新 public static double[] CirculeCoo(double Time, List Route3D, double Speed) { double TotalTime = 0; List TimeP = new List(); TimeP.Add(TotalTime); for (int i = 1; i < Route3D.Count; i++) { TotalTime += (distance1(Route3D[i], Route3D[i - 1]) / Speed); TimeP.Add(TotalTime); } TotalTime += (distance1(Route3D[0], Route3D[Route3D.Count - 1]) / Speed); TimeP.Add(TotalTime); double RestTime = Time % TotalTime; //Console.WriteLine(TotalTime+"TT||RT"+RestTime); double[] Head = new double[3]; double[] Tail = new double[3]; double[] Coo = new double[3]; Route3D.Add(Route3D[0]); double ratioRoute = new double(); for (int i = 0; i < TimeP.Count - 1; i++)//TimeP.Count比点数大1 { if (RestTime >= TimeP[i] && RestTime <= TimeP[i + 1]) { Head = Route3D[i]; Tail = Route3D[i + 1]; ratioRoute = (RestTime - TimeP[i]) / (TimeP[i + 1] - TimeP[i]); break; } } Coo[0] = Head[0] * (1 - ratioRoute) + Tail[0] * ratioRoute; Coo[1] = Head[1] * (1 - ratioRoute) + Tail[1] * ratioRoute; Coo[2] = Head[2] * (1 - ratioRoute) + Tail[2] * ratioRoute; double[] Coo1 = Coo; //Console.WriteLine("EEEEEEEEE" + Coo1[0] + "NNNNNNNNNN" + Coo1[1] + "HHHHHHHH" + Coo1[2]); Route3D.RemoveAt(Route3D.Count - 1); return Coo; } //17.坐标更新 public static void statusMove(List status, double Time, List Route3D, double Speed, int movingUnit)//速度单位是米每秒 { object[] statusMove = status[movingUnit]; double[] CooTemp = (double[])statusMove[1]; double[] CooNow = CirculeCoo(Time, Route3D, Speed); statusMove[1] = CooNow;//************需要更新为读取经纬高!!! //double Direction0 = Direction(CooTemp, CooNow); //statusMove[6] = Direction0;// double SailDirection =(Math.PI/2- Direction(CooTemp, CooNow)+ 2 * Math.PI) %(2* Math.PI);//*************需要更新为读取航向!!!!SailDirection是系统定义的航向 double direction0 = (Math.PI / 2 - SailDirection + 2 * Math.PI) % (2 * Math.PI); if(direction0> Math.PI) { direction0 -= 2 * Math.PI; } statusMove[6] = direction0*180/Math.PI;//将正北顺时针0-360航向角转化为正东逆时针+-180航向角.记录这个。 Console.WriteLine("航向角:"+ statusMove[6]); bool isMoved = true; statusMove[10] = isMoved; //status.RemoveAt(movingUnit); //status.Insert(movingUnit, statusMove); status[movingUnit] = statusMove; //return statusMove; } //通信设备定义,后期作为输入项 //0.int编号 //1.srting名称 //2.通信中心频率,MHz //3.发射功率,dBm //4.发射天线增益,dB //5.接收机灵敏度,dBm //6.接收天线增益.dB //7.bool是否有转发功能 //8.double发送流量限制Mbps //9.bool是否能接入外界网络 //10.double[]通信角度{angleH0,angleH1,angleD0,angleD1} public static List DeviceRead( List DeviceDTBS) { List Device = new List(); int i = 0; foreach(object[] element in DeviceDTBS) { int Number = i; string DeviceName = (string)element[0]; double F = (double)element[1]; double Pt = (double)element[2]; double Gt = (double)element[3]; double Pr = (double)element[4]; double Gr = (double)element[5]; bool canRelay = (bool)element[6]; double RelayLimit = (double)element[7]; bool isConnected = (bool)element[8]; double[] AngleLimit = { (double)element[9], (double)element[10], (double)element[11], (double)element[12] }; object[] DeviceToAdd = { Number, DeviceName, F, Pt, Gt, Pr, Gr, canRelay, RelayLimit, isConnected, AngleLimit }; Device.Add(DeviceToAdd); i++; } return Device; } //通信单位定义,后期作为输入项 //0.编号 //1.名称 //2.通信载荷种类int //3.double[]经纬高[初始位置] //4.本地遮挡衰减dB //5.本地数据流量需求Mbps //6.bool是否高优先级用户 //7.bool是否通信基点 //8.double初始朝向 //9.bool是否网格 public static void AddUnit(List Unit, string Name, string DeviceName, double[] Location,double LossLocal, double RequiredData, bool isVIP, bool isBase, double direction0, List Device) { int DeviceNumber = new int(); for (int i = 0; i < Device.Count; i++) { if ((string)Device[i][1] == DeviceName) { DeviceNumber = i; break; } } int Number = Unit.Count; double H; double[] LocationH = { Location[0], Location[1], Location[2] }; object[] UnitToAdd = { Number, Name, DeviceNumber, LocationH, LossLocal, RequiredData, isVIP, isBase, direction0, false }; Unit.Add(UnitToAdd); } //方向角算法,从P1指向P2,弧度制,正东为0,逆时针,正负Pi public static double Direction(double[] P1, double[] P2) { double EW = 6371.004 * 2 * math.PI * math.cos(math.PI * P1[1] / 180) * (P2[0] - P1[0]) / 360; double SN = 6371.004 * 2 * math.PI * (P2[1] - P1[1]) / 360; double Direction = Math.Atan2(SN, EW); return Direction; } //通信载荷状态定义 //0.编号 //1.double[]经纬高 //2.bool是否被联通 //3.int当前通信层级 //4.bool是否开启【默认开】 //5.所连基点ID //6.double朝向 //7.double上行数据量 //8.int上级ID //9.List连通性,0无判定,1连通,-1不通,三角。 //10.是否被移动 public static List status(List Unit) { List status = new List(); foreach (object[] element in Unit) { int num = (int)element[0]; double[] location = (double[])element[3]; bool isConnected; int level; bool isOpen = true; double direction = (double)element[8]; int BaseID; double UploadSpeed = 0; int upID; if ((bool)element[7] == true) { isConnected = true; level = 0; BaseID = num; upID = num; } else { isConnected = false; level = -1; BaseID = -1; upID = -1; } List canSee = new List(); for (int i = 0; i < Unit.Count; i++) { canSee.Add(0); } bool isMoved = false; object[] StatusToAdd = { num, location, isConnected, level, isOpen, BaseID, direction, UploadSpeed, upID, canSee, isMoved }; status.Add(StatusToAdd); } return status; } public static TXResult TXR(double FRT,string Stablility,string Robustness,string Security) { TXResult TXR = new TXResult(); TXR.FirstOneReadyTime = FRT; TXR.FirstOneArriveTime = -1; TXR.FirstOneMaxCover = -1; TXR.SingleMaxConnect = -1; TXR.AverageTotalCover = -1; TXR.FullCoverTime = -1; TXR.MaxTotalConnect = -1; TXR.ConnectTimeRatio = -1; TXR.UnitFulfilledRatio = -1; TXR.Stability = Stablility; TXR.Robustness = Robustness; TXR.Security = Security; return TXR; } //通信余量计算算法 //AL为航向角 public static double Margin(int Unit1, int Unit2, List Device, List Unit, List status, double MarginLimit, string TXEnvironment, DemHelper demHelper) //MarginLimit为通信余量下限,默认0 { //Console.WriteLine("正在判断" + (string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "的连通性"); int Device1 = (int)Unit[Unit1][2];//设备属性 int Device2 = (int)Unit[Unit2][2]; double F1 = (double)Device[Device1][2];//频率 double F2 = (double)Device[Device2][2]; if (F1 - F2 > 1) { // Console.WriteLine( (string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "不连通:频率不对"); return -1; }//不对频就结束 else { double Pt1 = (double)Device[Device1][3];//发射功率 double Gt1 = (double)Device[Device1][4];//发射增益 double Pr1 = (double)Device[Device1][5];//接收功率 double Gr1 = (double)Device[Device1][6];//接收增益 double[] AngleLimit1 = (double[])Device[Device1][10];//角度限制 double LossLocal1 = (double)Unit[Unit1][4];//本地损失 double[] Location1 = (double[])status[Unit1][1];//位置 //Console.WriteLine((string)Unit[Unit1][1] + "<--11-->" + (string)Unit[Unit2][1]); List canSee1 = (List)status[Unit1][9]; List canSee2 = (List)status[Unit2][9]; bool isMoved2 = (bool)status[Unit2][10]; bool isMoved1 = (bool)status[Unit1][10]; double Pt2 = (double)Device[Device2][3]; double Gt2 = (double)Device[Device2][4]; double Pr2 = (double)Device[Device2][5]; double Gr2 = (double)Device[Device2][6]; double[] AngleLimit2 = (double[])Device[Device2][10]; double LossLocal2 = (double)Unit[Unit2][4]; double[] Location2 = (double[])status[Unit2][1]; double D = distance1(Location1, Location2) / 1000;//距离,千米 double PL12 = 20 * Math.Log10(F1) + 20 * Math.Log10(D) + 32.44;//自由空间 //Console.WriteLine((string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "的自由空间损耗"+PL12); if (TXEnvironment=="郊区"|| TXEnvironment == "城市" || TXEnvironment == "密集城市" || TXEnvironment == "高层建筑城市" ) { string envi = TXEnvironment; double r = distance1(new double[] { Location1[0], Location1[1], 0 }, new double[] { Location2[0], Location2[1], 0 });//水平距离,m double f = F1 * 1000000;//频率,Hz double h = Math.Abs(Location1[2] - Location2[2]);//高度差,m double a = 0, b = 0, n_los = 0, n_nlos = 0; switch (envi) { case "郊区": a = 4.88; b = 0.43; n_los = 0.1; n_nlos = 21; break; case "城市": a = 9.61; b = 0.16; n_los = 1; n_nlos = 20; break; case "密集城市": a = 12.08; b = 0.11; n_los = 1.6; n_nlos = 23; break; case "高层建筑城市": a = 27.23; b = 0.08; n_los = 2.3; n_nlos = 34; break; } //double pi = 3.1415926; double c = 299552816; double A = n_los - n_nlos; double B = 20 * Math.Log10(f) + 20 * Math.Log10(4 * Math.PI / c) + n_nlos; double fm = 1 + a * Math.Exp(-b * (Math.Atan(h / r)*180/Math.PI - a)); double pl = A / fm + 10 * Math.Log10(h * h + r * r) + B; // double pl = A / fm + 20 * Math.Log10(D*1000)+ B; // Console.WriteLine((string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "的自由空间损耗" + PL12+"环境损耗" + pl + " r=" + r + " h=" + h);//+ " A/fm=" + (A / fm)); PL12 = pl; //+ " A/fm=" + (A/fm) + " B+30-20 * Math.Log10(F1)=" + (B+30- 20 * Math.Log10(F1))); } double Loss12 = PL12 + LossLocal1 + LossLocal2;//***损耗计算,暂时仅自由空间+本地损失*** double SafeL1to2 = Pt1 + Gt1 - Pr2 + Gr2 - MarginLimit;//安全损耗 double SafeL2to1 = Pt2 + Gt2 - Pr1 + Gr1 - MarginLimit; double A1 = Direction(Location1, Location2)*180/Math.PI;//连线方向角 double A2 = Direction(Location2, Location1) * 180 / Math.PI; double AL1 = (double)status[Unit1][6];//单位航向角 double AL2 = (double)status[Unit2][6]; double AA1 = (A1 - AL1) % 360; double AA2 = (A2 - AL2) % 360;//天线与目标夹角 if (AA1 >180) { AA1 = AA1 - 360; } if (AA1 <-180) { AA1 = AA1 + 360; } if (AA2 > 180) { AA2 = AA2 - 360; } if (AA2 < -180) { AA2 = AA2 +360; } //Console.WriteLine("AL1="+AL1+ "AL2=" + AL2+"AA1=" + AA1 + "AA2=" + AA2); double AV1 = angleH(Location1, Location2);//垂直高度角 double AV2 = angleH(Location2, Location1); bool isInDirection = false; if (AA1 >= AngleLimit1[2] && AA1 <= AngleLimit1[3] && AA2 >= AngleLimit2[2] && AA2 <= AngleLimit2[3] && AV1 >= AngleLimit1[0] && AV1 <= AngleLimit1[1] && AV2 >= AngleLimit2[0] && AV2 <= AngleLimit2[1]) { isInDirection = true; }//判断是否在角度限制内 //Console.WriteLine(SafeL2to1 - Loss12); //Console.WriteLine(SafeL1to2 - Loss12); //Console.WriteLine(isInDirection); if (SafeL1to2 >= Loss12 && SafeL2to1 >= Loss12 && isInDirection == true) //if (SafeL1to2 >= Loss12 && SafeL2to1 >= Loss12 && isInDirection == true) { bool isBlock = new bool(); if (isMoved1 == false && isMoved2 == false && Unit2 < Unit1 && canSee1[Unit2] != 0) { if (canSee1[Unit2] < 0) { isBlock = true; } else { isBlock = false; } } else if (isMoved1 == false && isMoved2 == false && Unit2 > Unit1 && canSee2[Unit1] != 0) { if (canSee2[Unit1] < 0) { isBlock = true; } else { isBlock = false; } } else { //Stopwatch stopwatch = Stopwatch.StartNew(); isBlock = isBlocked(Location1, Location2, demHelper);//是否被遮挡 //stopwatch.Stop(); //Console.WriteLine($"{(string)Unit[Unit1][1]}与{(string)Unit[Unit2][1]}地形判断耗时{stopwatch.ElapsedMilliseconds} 毫秒"); if (isMoved1 == false && isMoved2 == false) { if (isBlock == true) { //Console.WriteLine(Unit2 + "---->" + canSee1.Count); //canSee1.RemoveAt(Unit2); //canSee1.Insert(Unit2, -1); canSee1[Unit2] = -1; // Console.WriteLine(Unit1 + "---->" + canSee1.Count); //canSee2.RemoveAt(Unit1); //canSee2.Insert(Unit1, -1); canSee2[Unit1] = -1; } else { // Console.WriteLine(Unit2 + "---->" + canSee1.Count); //canSee1.RemoveAt(Unit2); //canSee1.Insert(Unit2, 1); canSee1[Unit2] = 1; // Console.WriteLine(Unit1 + "---->" + canSee1.Count); //canSee2.RemoveAt(Unit1); //canSee2.Insert(Unit1, 1); canSee2[Unit1] = 1; } object[] status1 = status[Unit1]; object[] status2 = status[Unit2]; status1[9] = canSee1; status2[9] = canSee2; //status.RemoveAt(Unit1); //status.Insert( Unit1,status1); status[Unit1] = status1; //status.RemoveAt(Unit2); //status.Insert( Unit2,status2); status[Unit2] = status2; } } //Console.WriteLine((string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "bolck:" + isBlock); if (isBlock != true) { if (SafeL1to2 >= SafeL2to1) { //Console.WriteLine((string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "连通"); return SafeL2to1 - Loss12; }//输出双向通信余量的小者 else { // Console.WriteLine((string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "连通"); return SafeL1to2 - Loss12; } } else { //Console.WriteLine((string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "不连通:地形遮挡"); return -1;//通不上就返-1 } } else { //Console.WriteLine((string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "不连通:在距离外"); return -1;//通不上就返-1 } } } public static List ASAStatusLevel(List Device, List Unit, List Status, double MarginLimit, int RelayLimit, string TXEnvironment, DemHelper demHelper) //RelayLimit是中继次数限制 { bool[] isOpen = new bool[Unit.Count];//本轮通信是否被激活 bool[] isConnected = new bool[Unit.Count];//是否被联通 int[] Level = new int[Unit.Count];//记录本轮通信层级 double[] margin = new double[Unit.Count];//记录余量 int[] UpID = new int[Unit.Count];//记录上一级ID int[] BaseID = new int[Unit.Count];//记录指向的base double[] UploadSpeed = new double[Unit.Count];//记录上行数据速度 for (int i = 0; i < Unit.Count; i++)//初始化 { isOpen[i] = false; margin[i] = -1; UploadSpeed[i] = 0; if ((bool)Unit[i][7] == true) { isConnected[i] = true; BaseID[i] = (int)Unit[i][0]; Level[i] = 0; UpID[i] = i; } else { isConnected[i] = false; BaseID[i] = -1; Level[i] = -1; UpID[i] = -1; } } for (int relay = 1; relay <= RelayLimit; relay++)//relay是将要更新的层级 { //单层初始化 for (int i = 0; i < Unit.Count; i++) { if (Level[i] == relay - 1 && (bool)Device[(int)Unit[i][2]][7] == true) { isOpen[i] = true;//仅开启上一级能中继的设备 //Console.WriteLine(i + "open"); } else { isOpen[i] = false; } } //找一个指向上一级的目标 //TaskFactory fac1 = new TaskFactory(new LimitedConcurrencyLevelTaskScheduler(128)); Task[] LevelTasks = new Task[Unit.Count];// Unit.Count]; for (int i = 0; i < Unit.Count; i++) { int ii = i; LevelTasks[ii] = Task.Run(() => { if (ii < Unit.Count && isOpen[ii] == true) { //Console.WriteLine("UNC" + Unit.Count); Task[] UnitTasks = new Task[Unit.Count]; for (int j = 0; j < Unit.Count; j++) { int jj = j; UnitTasks[jj] = //fac1.StartNew(s => Task.Run(() => { //int Levelj = ; double mar = -1; if (jj < Unit.Count && ii != jj && (Level[jj] == -1 || Level[jj] == relay)) { mar = Margin(ii, jj, Device, Unit, Status, MarginLimit,TXEnvironment ,demHelper); // Console.WriteLine("完成,mar:" + mar + "jj:" + jj); if (jj < Unit.Count && mar > 0 && (margin[jj] < 0 || mar > margin[jj])) { margin[jj] = mar; UpID[jj] = ii; BaseID[jj] = BaseID[ii]; Level[jj] = relay; isConnected[jj] = true; //Console.WriteLine("单位" + ii + "与" + "单位" + jj + "连通"); } } //Console.WriteLine("完成单位" + ii + "与" + "单位" + jj + "连通判定"); } );//,ii*Unit.Count+jj); } Task.WaitAll(UnitTasks); } }); } Task.WaitAll(LevelTasks); } for (int rerelay = Level.Max(); rerelay >= 0; rerelay--)//倒查并记录数据流量 { for (int i = 0; i < Unit.Count; i++) { if (Level[i] == rerelay) { //Console.WriteLine(i + "号设备上行速率需求" + (double)Unit[i][5] + "Mbps"); UploadSpeed[i] += (double)Unit[i][5]; if (i != UpID[i]) { UploadSpeed[UpID[i]] += UploadSpeed[i]; } //Console.WriteLine(i + "号设备上行速率" + UploadSpeed[i] + "Mbps"); } } } List newStatus = new List(); for (int i = 0; i < Unit.Count; i++) { object[] StatusToAdd = { Status[i][0], Status[i][1], isConnected[i], Level[i], Status[i][4], BaseID[i], Status[i][6], UploadSpeed[i], UpID[i], Status[i][9], Status[i][10] }; newStatus.Add(StatusToAdd); }//将2,3,5写入新Status return newStatus; } public static void ASASLevelCalculate(List Device, List Unit, List Status, double MarginLimit, int RelayLimit, string TXEnvironment, DemHelper demHelper) //RelayLimit是中继次数限制 { List newStatus = YJTX.ASAStatusLevel(Device, Unit, Status, MarginLimit, RelayLimit, TXEnvironment, demHelper); Status.Clear(); for (int i = 0; i < Unit.Count; i++) { Status.Add(newStatus[i]); }//刷新status } public static void ShowStatus(List Device, List Unit, List Status) { for (int i = 0; i < Unit.Count; i++) { double[] Location = (double[])Status[i][1]; string ConMark; if ((bool)Status[i][2] == true) { ConMark = "是"; } else { ConMark = "否"; } string OnMark; if ((bool)Status[i][4] == true) { OnMark = "开启"; } else { OnMark = "关闭"; } Console.WriteLine("编号:" + (int)Status[i][0] + "|单位名称:" + (string)Unit[i][1] + "|设备名称:" + (string)Device[(int)Unit[i][2]][1] + "|位置:E" + Location[0] + "°N" + Location[1] + "°H" + Location[2] + "m|方向角:" + (double)Status[i][6] + "°|连通状态:" + ConMark + "|当前通信层级:" + (int)Status[i][3] + "|当前载荷状态:" + OnMark + "|所连基点ID:" + (int)Status[i][5] + "上行数据速率:" + (double)Status[i][7] + "Mbps"); Console.WriteLine("___________________________________________"); } } //区域网格生成 public static List TXNPGenerate(List juxing, double netscalelon, double netscalelat, double DeviceHeight, string DeviceName, string NetName, double LocalLost, List Device, DemHelper demHelper) //DeviceHeight设备高度,单位m //LocalLost网格本地遮挡,单位dB { Console.WriteLine("格点生成"); List netpoints = new List(); int DeviceNumber = new int(); for (int i = 0; i < Device.Count; i++) { if ((string)Device[i][1] == DeviceName) { DeviceNumber = i; break; } } double lonmin = -1000; double lonmax = -1000; double latmin = -1000; double latmax = -1000; foreach (double[] element in juxing) { if (lonmin == -1000 || element[0] < lonmin) { lonmin = element[0]; } if (lonmax == -1000 || element[0] > lonmax) { lonmax = element[0]; } if (latmin == -1000 || element[1] < latmin) { latmin = element[1]; } if (latmax == -1000 || element[1] > latmax) { latmax = element[1]; } } for (double[] netpointprev = new double[3] { lonmin, latmax, 0 }; netpointprev[1] >= latmin; netpointprev[1] = netpointprev[1] - netscalelat) { int i = 0; for (netpointprev[0] = lonmin; netpointprev[0] <= lonmax; netpointprev[0] = netpointprev[0] + netscalelon) { if (isinpoly(netpointprev, juxing, demHelper) == true) { double HH = HeightLL(netpointprev[0], netpointprev[1]);//需要替换为该点【netpointprev[0], netpointprev[1]】高程 double[] netpointtemp = new double[3] { netpointprev[0], netpointprev[1], HH + DeviceHeight }; //netpointtemp = netpointprev; string GridName = NetName + i; object[] GridToAdd = { i, GridName, DeviceNumber, netpointtemp, LocalLost, 0.0, false, false, 0.0, true }; netpoints.Add(GridToAdd); i++; } } } return netpoints; } //区域网格计算 public static int[] AreaConnectCheck(List TXNP, List Device, List Unit, List Status, int[] UnitInvolved,//计算涉及的通信网络,至少含一基站类目标 double MarginLimit,//有效计算的通信余量 string TXEnvironment, DemHelper demHelper ) { int TXNPCount = TXNP.Count; int[] AreaCheck = new int[TXNPCount]; //if (TXNPCount == 0) //{ // Console.WriteLine("无网格"); // return AreaCheck; //} //else //{ List NPStatus = status(TXNP); for (int i = 0; i < UnitInvolved.Length; i++) { TXNP.Add(Unit[UnitInvolved[i]]); } for (int i = 0; i < UnitInvolved.Length; i++) { object[] StatusToAdd = Status[UnitInvolved[i]]; bool isMoved = true; StatusToAdd[10] = isMoved; NPStatus.Add(StatusToAdd); //Console.WriteLine("involve" + Status[UnitInvolved[i]].Length); } List NPstatusLevel = ASAStatusLevel(Device, TXNP, NPStatus, MarginLimit, 1, TXEnvironment, demHelper); for (int i = 0; i < TXNPCount; i++) { if ((int)NPstatusLevel[i][3] > 0) { AreaCheck[i] = (int)NPstatusLevel[i][5]; } else { AreaCheck[i] = -1; } } for (int i = 0; i < UnitInvolved.Length; i++) { TXNP.RemoveAt(TXNP.Count - 1); } return AreaCheck; //} } public static void AreaCheckPostProcess(double Time, List poly, int[] BaseList, int[] AreaConnectCheck, List TXNP, string CalculateName, double netscalelon, double netscalelat, List GridResult) //区域网格后处理 { double[,] MM1 = MaxMinPoly(poly); double W = MM1[0, 0];//经度最小(西界) double E = MM1[0, 1];//经度最大(东界) double S = MM1[1, 0]; //纬度最小(南界) double N = MM1[1, 1];//纬度最大(北界); double kmPerlat = 111.1; double kmPerlon = kmPerlat * Math.Cos((Math.PI / 180) * ((N + S) / 2)); double SPerGrid = (netscalelon * kmPerlon) * (netscalelat * kmPerlat); int NPNumber = AreaConnectCheck.Length; int ConnectedNP = 0; int[] ConnectedSingle = new int[BaseList.Length]; for (int j = 0; j < BaseList.Length; j++) { ConnectedSingle[j] = 0; } for (int i = 0; i < NPNumber; i++) { if (AreaConnectCheck[i] >= 0) { ConnectedNP++; for (int j = 0; j < BaseList.Length; j++) { if (BaseList[j] == AreaConnectCheck[i]) { ConnectedSingle[j]++; } } } } double[] AreaSingle = new double[ConnectedSingle.Length];//各单机连接区域面积 for (int j = 0; j < ConnectedSingle.Length; j++) { AreaSingle[j] = SPerGrid * ConnectedSingle[j]; } double Ratio = (double)ConnectedNP / NPNumber; double AreaTotal = SPerGrid * ConnectedNP; Console.WriteLine("计算名称:" + CalculateName + "||网格总数:" + NPNumber + "||连接网格数:" + ConnectedNP + "||比例:" + Ratio * 100 + "%"); //string csvFilePath = CalculateName + "output.csv";//需csv输出则取消注释1/5 //using (var writer = new StreamWriter(csvFilePath))//需csv输出则取消注释2/5 //{//需csv输出则取消注释3/5 // for (int k = 0; k < NPNumber; k++) // { // double[] item = (double[])TXNP[k][3]; // if (AreaConnectCheck[k] >= 0) // { // string Fmt = "{0} , {1}"; // for (int i = 0; i <= AreaConnectCheck[k]; i++) // { Fmt += " ,"; } // Fmt += "{1}"; // writer.WriteLine(String.Format(Fmt, item[0], item[1])); // } // else // { writer.WriteLine(String.Format("{0} ,{1} ", item[0], item[1])); } // } //} object[] StepResult = { Time, BaseList, AreaSingle, Ratio, AreaTotal }; GridResult.Add(StepResult); } //区域内随机数生成 public static List TXRandomGenerate(List juxing, int pointnumber, //生成的随机格点数量 double DeviceHeight,//DeviceHeight设备高度,单位m string DeviceName, string NetName, double LocalLost, double DataSpeedPerPiont, int firstNum,//首点ID //List Device, ListDevice,DemHelper demHelper) //LocalLost网格本地遮挡,单位dB { Console.WriteLine("随机点生成"); List netpoints = new List(); double lonmin = -1000; double lonmax = -1000; double latmin = -1000; double latmax = -1000; foreach (double[] element in juxing) { if (lonmin == -1000 || element[0] < lonmin) { lonmin = element[0]; } if (lonmax == -1000 || element[0] > lonmax) { lonmax = element[0]; } if (latmin == -1000 || element[1] < latmin) { latmin = element[1]; } if (latmax == -1000 || element[1] > latmax) { latmax = element[1]; } } //四界 int DeviceNumber = new int(); for (int i = 0; i < Device.Count; i++) { if ((string)Device[i][1] == DeviceName) { DeviceNumber = i; break; } } System.Random lonRam = new System.Random(); System.Random latRam = new System.Random(); TaskFactory fac = new TaskFactory(new LimitedConcurrencyLevelTaskScheduler(64)); Task[] PointTasks = new Task[pointnumber]; for (int i = 0; i < pointnumber;) { double lon = lonmin + lonRam.NextDouble() * (lonmax - lonmin); double lat = latmin + latRam.NextDouble() * (latmax - latmin); double[] netpointprev = { lon, lat }; if (isinpoly(netpointprev, juxing, demHelper) == true) { int ii = i; //PointTasks[ii] = Task.Run(() => //{ PointTasks[ii] = fac.StartNew(s => { if (ii < pointnumber) { double HH = HeightLL(netpointprev[0], netpointprev[1]); double[] netpointtemp = new double[3] { netpointprev[0], netpointprev[1], HH + DeviceHeight }; string GridName = NetName + ii; object[] GridToAdd = { ii + firstNum, GridName, DeviceNumber, netpointtemp, LocalLost, DataSpeedPerPiont, false, false, 0.0, false }; netpoints.Add(GridToAdd); } }, ii); //}); i++; } } //Task.WaitAll(fac.); //TaskFactory.Continue(fac); Task.WaitAll(PointTasks); return netpoints; } public static void TXRandomAdd(List juxing, int pointnumber, //生成的随机格点数量 double DeviceHeight,//DeviceHeight设备高度,单位m string DeviceType, string NetName, double LocalLost, double DataSpeedPerPiont, //int firstNum,//首点ID List Unit, ListDevice, DemHelper demHelper) { List TXNP = TXRandomGenerate(juxing, pointnumber, DeviceHeight, DeviceType, NetName, LocalLost, DataSpeedPerPiont, Unit.Count,Device,demHelper); foreach (object[] element in TXNP) { Unit.Add(element); } } public static void ConnectNetPostProcess(double Time, List Device, List Unit, List Status, string CalculateName, string involvedUnit, List NetResult) //通信网络后处理 { List involvedUnitNum = intList(involvedUnit); bool[] isInvolved = new bool[Status.Count]; List BaseList = new List(); List ConnectedSingle = new List(); List BaseFull = new List(); for (int i = 0; i < Status.Count; i++) { isInvolved[i] = false; } int involvedNP = 0; int Fulfilled = 0; foreach (int i in involvedUnitNum) { if (i < Status.Count) { isInvolved[i] = true; involvedNP++; if ((int)Status[i][3] == 0) { BaseList.Add(i); ConnectedSingle.Add(0); double UpLimit = (double)Device[(int)Unit[i][2]][8]; double UpRatio = (double)Status[i][7] / UpLimit; BaseFull.Add(UpRatio); } } } int NPNumber = Status.Count; int ConnectedNP = 0; for (int i = 0; i < NPNumber; i++) { if ((int)Status[i][3] >= 0 && isInvolved[i] == true) { ConnectedNP++; } if ((int)Status[i][3] > 0 && isInvolved[i] == true) { for (int j = 0; j < BaseList.Count; j++) { if (BaseList[j] == (int)Status[i][5]) { ConnectedSingle[j]++; if (BaseFull[j]<1) { Fulfilled++; } } } } } int TotalConnected = ConnectedNP - BaseList.Count; int nonBasePoint = involvedNP - BaseList.Count; double Ratio = (double)TotalConnected / nonBasePoint; double FulRatio=(double)Fulfilled/ nonBasePoint; object[] StepResult = { Time, BaseList, ConnectedSingle, TotalConnected, BaseFull, FulRatio }; NetResult.Add(StepResult); Console.WriteLine("计算名称:" + CalculateName + "||基站数:" + BaseList.Count + "||非基站节点数:" + nonBasePoint + "||连接节点数:" + TotalConnected + "||比例:" + Ratio * 100 + "%"); //string csvFilePath = CalculateName + "output.csv"; //using (var writer = new StreamWriter(csvFilePath)) //{ // for (int k = 0; k < NPNumber; k++) // { // if (isInvolved[k] == true) // { // double[] item = (double[])Status[k][1]; // int level = (int)Status[k][3]; // if ((int)Status[k][3] >= 0) // { // string Fmt = "{0} , {1},{2}"; // for (int i = 0; i <= (int)Status[k][5]; i++) // { Fmt += " ,"; } // Fmt += "{2}"; // writer.WriteLine(String.Format(Fmt, level, item[0], item[1])); // } // else // { writer.WriteLine(String.Format("{0} ,{1},{2} ", level, item[0], item[1])); } // } // } //} } public static void Draw(List poly, List point, List ColorP, List> points, List color, int PxPerKm, string name)//可视化,下一步改成自动颜色! { // 创建一个位图 double[,] MM1 = MaxMinPoly(poly); double W = MM1[0, 0];//经度最小(西界) double E = MM1[0, 1];//经度最大(东界) double S = MM1[1, 0]; //纬度最小(南界) double N = MM1[1, 1];//纬度最大(北界); double kmPerlat = 111.1; double kmPerlon = kmPerlat * Math.Cos((Math.PI / 180) * ((N + S) / 2)); //Console.WriteLine(E+"+"+W); static int LonToPx(double lon, double W, double kmPerlon, int PxPerKm) { double LonKm = (lon - W) * kmPerlon; int LonPx = (int)(LonKm * PxPerKm); return LonPx; } static int LatToPx(double lat, double N, double kmPerlat, int PxPerKm)//从北向南!! { double LatKm = (N - lat) * kmPerlat; int LatPx = (int)(LatKm * PxPerKm); return LatPx; } int EW = LonToPx(E, W, kmPerlon, PxPerKm); int NS = LatToPx(S, N, kmPerlat, PxPerKm); //Console.WriteLine(EW + "EW|NS" + NS); using Bitmap bitmap = new Bitmap(EW, NS);//位图大小东西南北界 using (Graphics g = Graphics.FromImage(bitmap)) { g.Clear(Color.White); // 使用Clear方法填充背景色 } using Graphics graphics = Graphics.FromImage(bitmap); for (int i = 1; i < poly.Count; i++) { int penWidth = math.max(EW, NS) / 500; using Pen Pen = new Pen(Color.Black, penWidth); Point Point1 = new Point(LonToPx(poly[i - 1][0], W, kmPerlon, PxPerKm), LatToPx(poly[i - 1][1], N, kmPerlat, PxPerKm)); Point Point2 = new Point(LonToPx(poly[i][0], W, kmPerlon, PxPerKm), LatToPx(poly[i][1], N, kmPerlat, PxPerKm)); graphics.DrawLine(Pen, Point1, Point2); } for (int i = 0; i < point.Count; i++) { int penWidth = math.max(EW, NS) / 500; using Pen Pen = new Pen(ColorP[i], penWidth); //Rectangle rg = new Rectangle(0, 0, math.max(EW, NS) / 300, math.max(EW, NS) / 300); float RGsize = math.max(EW, NS) / 300; graphics.DrawRectangle(Pen, LonToPx(point[i][0], W, kmPerlon, PxPerKm) - (int)(0.5 * RGsize), LatToPx(point[i][1], N, kmPerlat, PxPerKm) - (int)(0.5 * RGsize), RGsize, RGsize); } for (int i = 0; i < points.Count; i++) { int penWidth = math.max(EW, NS) / 1000; using Pen Pen = new Pen(color[i % color.Count], penWidth); for (int j = 0; j < points[i].Count; j++) { Point Point1 = new Point(LonToPx(points[i][j][0], W, kmPerlon, PxPerKm), LatToPx(points[i][j][1], N, kmPerlat, PxPerKm)); Point Point2 = new Point(LonToPx(points[i][j][2], W, kmPerlon, PxPerKm), LatToPx(points[i][j][3], N, kmPerlat, PxPerKm)); graphics.DrawLine(Pen, Point1, Point2); } } // 定义两个坐标点 // Point point1 = new Point(50, 50); // Point point2 = new Point(150, 150); // Point point3= new Point(100, 150); // 使用Pen来定义直线的颜色和宽度 // using Pen pen = new Pen(Color.Black, 2); // 画直线 // graphics.DrawLine(pen, point1, point2); // graphics.DrawLine(pen, point1, point3); // 保存图像到文件 //bitmap.Save("line.png"); // 或者显示图像 bitmap.Save(name + ".jpeg"); Console.WriteLine("已画制并保存到" + name + ".jpeg文件中。||" + EW + "EW|NS" + NS); } public static void Drawnet(List Status, string involvedUnit, List poly, int PxPerKm, string name) { List color = new List(); //color.Add(Color.Black); color.Add(Color.Red); color.Add(Color.Orange); color.Add(Color.Yellow); color.Add(Color.Green); color.Add(Color.Cyan); color.Add(Color.Blue); color.Add(Color.Purple); List colorP = new List();//不同基站的上色方案:红橙黄绿青蓝紫,循环 List involvedUnitNum = intList(involvedUnit);//读取需要画进去的单位ID List> points = new List>();//把每个基站连接的不同单位存储在不同的List里,方便上色 List UnitsP = new List(); int[] BaseCatalogue = new int[Status.Count];//基站单位着色索引 int BaseTemp = 0; bool[] isInvolved = new bool[Status.Count]; for (int i = 0; i < Status.Count; i++)//找出基站并针对基站情况初始化列表 { isInvolved[i] = false;//true为画入的单位 if ((int)Status[i][3] == 0)//是基站 { BaseCatalogue[i] = BaseTemp;//加入基站单位着色索引,表示该单位为目录中第 BaseTemp+1个基站 BaseTemp++; points.Add(new List());//为每个基站新建一个列表 } else { BaseCatalogue[i] = -1; } } foreach (int i in involvedUnitNum) { if (i < isInvolved.Length) { isInvolved[i] = true; } }//将需要画入的单位画入开关打开 foreach (object[] element in Status) { if (isInvolved[(int)element[0]] == true)//若画入开关打开 { UnitsP.Add((double[])element[1]);//记录该点坐标用于散点绘制 if ((int)element[3] >= 1) { int BaseID = (int)element[5]; int upID = (int)element[8]; double[] point12 = new double[4]; point12[0] = ((double[])element[1])[0]; point12[1] = ((double[])element[1])[1]; double[] pointUp = (double[])Status[upID][1]; point12[2] = pointUp[0]; point12[3] = pointUp[1]; points[BaseCatalogue[BaseID]].Add(point12); colorP.Add(color[BaseCatalogue[BaseID] % color.Count]); } else if ((int)element[3] == 0) { colorP.Add(Color.Magenta); } else { colorP.Add(Color.Black); } } } Draw(poly, UnitsP, colorP, points, color, PxPerKm, name); } public static void Drawgrid(List poly, List Grids, int[] ACC, int PxPerKm, string name, double netscalelon, double netscalelat) { List UnitsP = new List(); foreach (object[] element in Grids) { UnitsP.Add((double[])element[3]); } List color = new List(); //color.Add(Color.Black); //color.Add(Color.White); color.Add(Color.Red); color.Add(Color.Orange); color.Add(Color.Yellow); color.Add(Color.Green); color.Add(Color.Cyan); color.Add(Color.Blue); color.Add(Color.Purple); // 创建一个位图 double[,] MM1 = MaxMinPoly(poly); double W = MM1[0, 0];//经度最小(西界) double E = MM1[0, 1];//经度最大(东界) double S = MM1[1, 0]; //纬度最小(南界) double N = MM1[1, 1];//纬度最大(北界); double kmPerlat = 111.1; double kmPerlon = kmPerlat * Math.Cos((Math.PI / 180) * ((N + S) / 2)); //Console.WriteLine(E + "+" + W); static int LonToPx(double lon, double W, double kmPerlon, int PxPerKm) { double LonKm = (lon - W) * kmPerlon; int LonPx = (int)(LonKm * PxPerKm); return LonPx; } static int LatToPx(double lat, double N, double kmPerlat, int PxPerKm)//从北向南!! { double LatKm = (N - lat) * kmPerlat; int LatPx = (int)(LatKm * PxPerKm); return LatPx; } int EW = LonToPx(E, W, kmPerlon, PxPerKm); int NS = LatToPx(S, N, kmPerlat, PxPerKm); int RGEW = LonToPx(W + netscalelon, W, kmPerlon, PxPerKm); int RGNS = LatToPx(N - netscalelat, N, kmPerlat, PxPerKm); //Console.WriteLine(EW + "EW|NS" + NS); //Console.WriteLine(RGEW + "RGEW|RGNS" + RGNS); using Bitmap bitmap = new Bitmap(EW, NS);//位图大小东西南北界 using (Graphics g = Graphics.FromImage(bitmap)) { g.Clear(Color.White); // 使用Clear方法填充背景色 } using Graphics graphics = Graphics.FromImage(bitmap); for (int i = 0; i < ACC.Length; i++) { int penWidth = math.max(EW, NS) / 500; Color colorThis = Color.White; if (ACC[i] >= 0) { colorThis = color[ACC[i] % (color.Count)]; } using Pen Pen = new Pen(Color.Black, penWidth); //Rectangle rg = new Rectangle(0, 0, math.max(EW, NS) / 300, math.max(EW, NS) / 300); //float RGsize = math.max(EW, NS) / 300; graphics.DrawRectangle(Pen, LonToPx(UnitsP[i][0], W, kmPerlon, PxPerKm) - (int)(0.5 * RGEW), LatToPx(UnitsP[i][1], N, kmPerlat, PxPerKm) - (int)(0.5 * RGNS), RGEW, RGNS); using Brush BrushT = new SolidBrush(colorThis); graphics.FillRectangle(BrushT, LonToPx(UnitsP[i][0], W, kmPerlon, PxPerKm) - (int)(0.5 * RGEW), LatToPx(UnitsP[i][1], N, kmPerlat, PxPerKm) - (int)(0.5 * RGNS), RGEW, RGNS); } for (int i = 1; i < poly.Count; i++) { int penWidth = math.max(EW, NS) / 250; using Pen Pen = new Pen(Color.Black, penWidth); Point Point1 = new Point(LonToPx(poly[i - 1][0], W, kmPerlon, PxPerKm), LatToPx(poly[i - 1][1], N, kmPerlat, PxPerKm)); Point Point2 = new Point(LonToPx(poly[i][0], W, kmPerlon, PxPerKm), LatToPx(poly[i][1], N, kmPerlat, PxPerKm)); graphics.DrawLine(Pen, Point1, Point2); } bitmap.Save(name + ".jpeg"); Console.WriteLine(ACC.Length + "个网格已画制并保存到" + name + ".jpeg文件中||" + EW + "EW|NS" + NS); } public static List CirclePoint(double[] Center, double r, int pointnumber, double startPoint, double H,bool isClockWise) //经纬度,半径(km),点数量,起始点(角度,正北为0,顺时针),海拔高度 { List CirclePoint = new List(); double kmPerlat = 111.1; double kmPerlon = kmPerlat * Math.Cos((Math.PI / 180) * Center[1]); double Rlat = r / kmPerlat; double Rlon = r / kmPerlon; double DevideAngleRad = 2 * Math.PI / pointnumber; double startPointRad = startPoint * (Math.PI / 180); int k = 1; if(isClockWise==false) { k = -1; } for (int i = 0; i < pointnumber; i++) { double AngleRad = (startPointRad + k*i * DevideAngleRad) % (2 * Math.PI); double pointLon = Center[0] + Math.Sin(AngleRad) * Rlon; double pointLat = Center[1] + Math.Cos(AngleRad) * Rlat; double[] point = { pointLon, pointLat, H }; CirclePoint.Add(point); } return CirclePoint; } public static void PostProcessTotal(double ResultStartTime,double ResultEndTime, TXResult TXR, ListUnit, List GridResult, List NetResult,int FirstOne,double Timestep,string CalculateName) //结果统计开始时间、结束时间 { List netBaseList = (List)NetResult[0][1]; int[] maxSingle = new int[netBaseList.Count]; if (NetResult.Count > 0) { //List netBaseList = (List)NetResult[0][1]; int maxTotal = 0; double TimeConnected = 0; for(int k = 0;k< netBaseList.Count;k++) { maxSingle[k] = 0; } double[] FulRatio = new double[NetResult.Count]; for (int i = 0; i < NetResult.Count; i++)//读取每时步结果 { List ConnectedSingle = (List)NetResult[i][2]; if (ConnectedSingle[FirstOne] > 0) { TXR.FirstOneArriveTime = (double)NetResult[i][0];//记录最早连接的时间 break; } } int iStart = (int)((ResultStartTime+0.5*Timestep) / Timestep); int iEnd = (int)((ResultEndTime+0.5 * Timestep) / Timestep); for (int i = 0; i < NetResult.Count; i++)//读取每时步结果 { FulRatio[i] = (double)NetResult[i][5]; List ConnectedSingle = (List)NetResult[i][2]; //List < double>BaseFull= (List)NetResult[i][4]; for (int j=0;j< ConnectedSingle.Count;j++) { if (ConnectedSingle[j]> maxSingle[j]) { maxSingle[j] = ConnectedSingle[j]; } } if(maxTotal < (int)NetResult[i][3]) { maxTotal = (int)NetResult[i][3]; } if (i>=iStart && i<=iEnd &&(int)NetResult[i][3]>0) { if(NetResult.Count >1 && i==iStart) { TimeConnected += (iStart*Timestep-ResultStartTime)+0.5 * Timestep; } else if(NetResult.Count > 1 && i == iEnd) { TimeConnected +=(ResultEndTime-iEnd*Timestep) + 0.5 * Timestep; } else { { TimeConnected += Timestep; } } } } int maxmaxSingle = maxSingle.Max(); double FulRatioAve = FulRatio.Average(); TXR.SingleMaxConnect = maxmaxSingle; TXR.MaxTotalConnect = maxTotal; TXR.ConnectTimeRatio = TimeConnected/(ResultEndTime-ResultStartTime); TXR.UnitFulfilledRatio = FulRatioAve; } if (GridResult.Count > 0) { double FirstMaxCover = 0; for (int i = 0; i < GridResult.Count; i++)//读取每时步结果 { if ((double)GridResult[i][3] >= 1) { TXR.FullCoverTime = (double)GridResult[i][0];//记录最早100%连接的时间 break; } } double[] TotalCover = new double[GridResult.Count]; for (int i = 0; i < GridResult.Count; i++)//读取每时步结果 { double FirstCover = ((double[])GridResult[i][2])[FirstOne]; if (FirstMaxCover < FirstCover) { FirstMaxCover =FirstCover; } TotalCover[i] = (double)GridResult[i][4]; } double AveTotalCover = TotalCover.Average(); TXR.FirstOneMaxCover = FirstMaxCover; TXR.AverageTotalCover = AveTotalCover; } Console.WriteLine("准备时间:" + TXR.FirstOneReadyTime+"s||到达任务区域时间:"+TXR.FirstOneArriveTime+ "s||首架次覆盖范围最大值:"+ TXR.FirstOneMaxCover +"km²||最大单架接入用户数:"+ TXR.SingleMaxConnect+"个||第一次完全覆盖时间:"+ TXR.FullCoverTime+"s||平均总覆盖面积:" + TXR.AverageTotalCover + "km²||同时连接最大用户数量:"+ TXR.MaxTotalConnect+ "个||保持至少一个单位有通信情况下的时间比例:"+ (TXR.ConnectTimeRatio*100)+ "%||能满足流量需求的单位比例:"+ (TXR.UnitFulfilledRatio*100)+"%"); string csvFilePath = CalculateName + "/应急通信计算报告.csv"; using (var writer = new StreamWriter(csvFilePath, Encoding.UTF8, new FileStreamOptions{Access = FileAccess.Write, Mode = FileMode.Create, Share = FileShare.None, Options = FileOptions.None})) { writer.WriteLine(String.Format("{0} ,{1}", "指标名", "数值")); writer.WriteLine(String.Format("{0} ,{1}", "首架次出动准备时间(秒)", TXR.FirstOneReadyTime)); writer.WriteLine(String.Format("{0} ,{1}", "首架次飞抵时间(秒)", TXR.FirstOneArriveTime)); writer.WriteLine(String.Format("{0} ,{1}", "首架次最大单次覆盖范围(平方千米)", TXR.FirstOneMaxCover)); writer.WriteLine(String.Format("{0} ,{1}", "任务区域全覆盖实现时间(秒)", TXR.FullCoverTime)); writer.WriteLine(String.Format("{0} ,{1}", "平均覆盖地面总面积(平方千米)", TXR.AverageTotalCover)); writer.WriteLine(String.Format("{0} ,{1}", "最大单次总接入数量", TXR.MaxTotalConnect)); writer.WriteLine(String.Format("{0} ,{1}", "给定时间内持续保障率(%)", TXR.ConnectTimeRatio * 100)); writer.WriteLine(String.Format("{0} ,{1}", "满足通信速率要求的用户比例(%)", TXR.UnitFulfilledRatio * 100)); writer.WriteLine(String.Format("{0} ,{1}", "通信稳定性", TXR.Stability)); writer.WriteLine(String.Format("{0} ,{1}", "鲁棒性", TXR.Robustness)); writer.WriteLine(String.Format("{0} ,{1}", "安全性", TXR.Security)); writer.WriteLine(String.Format("{0}", " ")); writer.WriteLine(String.Format("{0} ,{1}", "基站名称", "单基站最大接入数量")); for (int i = 0; i < netBaseList.Count; i++) { writer.WriteLine(String.Format("{0} ,{1}", (string)(Unit[netBaseList[i]][1]), maxSingle[i])); } } } public static List Hover(double[]Location,double Direction,double H,bool isRealHeight,double EnterDistance) { double kmPerlat = 111.1; double kmPerlon = kmPerlat * Math.Cos((Math.PI / 180) * Location[1]); double Dlat = EnterDistance / kmPerlat; double Dlon = EnterDistance / kmPerlon; double DirectionRad = Direction * (Math.PI / 180); double EnterLon = Location[0] - Math.Sin(DirectionRad) * Dlon; double EnterLat = Location[1] - Math.Cos(DirectionRad) * Dlat; double H1 = H; if (isRealHeight) { H1 += HeightLL(Location[0], Location[1]); } double[] Point1 = { Location[0], Location[1], H1 }; double[]Point0= { EnterLon, EnterLat, H1 }; List Hover = new List(); Hover.Add(Point0); Hover.Add(Point1); return Hover; } } }