YJTX.cs 79 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785
  1. 
  2. using Unity.Mathematics;
  3. using System.Drawing;
  4. using System.Text;
  5. using BHJD.DEMdll.Public;
  6. using Newtonsoft.Json;
  7. namespace QuYuSaoMiao
  8. {
  9. public class LimitedConcurrencyLevelTaskScheduler : TaskScheduler
  10. {
  11. /// <summary>Whether the current thread is processing work items.</summary>
  12. [ThreadStatic]
  13. private static bool _currentThreadIsProcessingItems;
  14. /// <summary>The list of tasks to be executed.</summary>
  15. private readonly LinkedList<Task> _tasks = new LinkedList<Task>(); // protected by lock(_tasks)
  16. /// <summary>The maximum concurrency level allowed by this scheduler.</summary>
  17. private readonly int _maxDegreeOfParallelism;
  18. /// <summary>Whether the scheduler is currently processing work items.</summary>
  19. private int _delegatesQueuedOrRunning = 0; // protected by lock(_tasks)
  20. /// <summary>
  21. /// Initializes an instance of the LimitedConcurrencyLevelTaskScheduler class with the
  22. /// specified degree of parallelism.
  23. /// </summary>
  24. /// <param name="maxDegreeOfParallelism">The maximum degree of parallelism provided by this scheduler.</param>
  25. public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism)
  26. {
  27. if (maxDegreeOfParallelism < 1) throw new ArgumentOutOfRangeException("maxDegreeOfParallelism");
  28. _maxDegreeOfParallelism = maxDegreeOfParallelism;
  29. }
  30. /// <summary>
  31. /// current executing number;
  32. /// </summary>
  33. public int CurrentCount { get; set; }
  34. /// <summary>Queues a task to the scheduler.</summary>
  35. /// <param name="task">The task to be queued.</param>
  36. protected sealed override void QueueTask(Task task)
  37. {
  38. // Add the task to the list of tasks to be processed. If there aren't enough
  39. // delegates currently queued or running to process tasks, schedule another.
  40. lock (_tasks)
  41. {
  42. //Console.WriteLine("Task Count : {0} ", _tasks.Count);
  43. _tasks.AddLast(task);
  44. if (_delegatesQueuedOrRunning < _maxDegreeOfParallelism)
  45. {
  46. ++_delegatesQueuedOrRunning;
  47. NotifyThreadPoolOfPendingWork();
  48. }
  49. }
  50. }
  51. int executingCount = 0;
  52. private static object executeLock = new object();
  53. /// <summary>
  54. /// Informs the ThreadPool that there's work to be executed for this scheduler.
  55. /// </summary>
  56. private void NotifyThreadPoolOfPendingWork()
  57. {
  58. ThreadPool.UnsafeQueueUserWorkItem(_ =>
  59. {
  60. // Note that the current thread is now processing work items.
  61. // This is necessary to enable inlining of tasks into this thread.
  62. _currentThreadIsProcessingItems = true;
  63. try
  64. {
  65. // Process all available items in the queue.
  66. while (true)
  67. {
  68. Task item;
  69. lock (_tasks)
  70. {
  71. // When there are no more items to be processed,
  72. // note that we're done processing, and get out.
  73. if (_tasks.Count == 0)
  74. {
  75. --_delegatesQueuedOrRunning;
  76. break;
  77. }
  78. // Get the next item from the queue
  79. item = _tasks.First.Value;
  80. _tasks.RemoveFirst();
  81. }
  82. // Execute the task we pulled out of the queue
  83. base.TryExecuteTask(item);
  84. }
  85. }
  86. // We're done processing items on the current thread
  87. finally { _currentThreadIsProcessingItems = false; }
  88. }, null);
  89. }
  90. /// <summary>Attempts to execute the specified task on the current thread.</summary>
  91. /// <param name="task">The task to be executed.</param>
  92. /// <param name="taskWasPreviouslyQueued"></param>
  93. /// <returns>Whether the task could be executed on the current thread.</returns>
  94. protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
  95. {
  96. // If this thread isn't already processing a task, we don't support inlining
  97. if (!_currentThreadIsProcessingItems) return false;
  98. // If the task was previously queued, remove it from the queue
  99. if (taskWasPreviouslyQueued) TryDequeue(task);
  100. // Try to run the task.
  101. return base.TryExecuteTask(task);
  102. }
  103. /// <summary>Attempts to remove a previously scheduled task from the scheduler.</summary>
  104. /// <param name="task">The task to be removed.</param>
  105. /// <returns>Whether the task could be found and removed.</returns>
  106. protected sealed override bool TryDequeue(Task task)
  107. {
  108. lock (_tasks) return _tasks.Remove(task);
  109. }
  110. /// <summary>Gets the maximum concurrency level supported by this scheduler.</summary>
  111. public sealed override int MaximumConcurrencyLevel { get { return _maxDegreeOfParallelism; } }
  112. /// <summary>Gets an enumerable of the tasks currently scheduled on this scheduler.</summary>
  113. /// <returns>An enumerable of the tasks currently scheduled.</returns>
  114. protected sealed override IEnumerable<Task> GetScheduledTasks()
  115. {
  116. bool lockTaken = false;
  117. try
  118. {
  119. Monitor.TryEnter(_tasks, ref lockTaken);
  120. if (lockTaken) return _tasks.ToArray();
  121. else throw new NotSupportedException();
  122. }
  123. finally
  124. {
  125. if (lockTaken) Monitor.Exit(_tasks);
  126. }
  127. }
  128. }
  129. public class Height
  130. {
  131. public string msg { get; set; }
  132. public int code { get; set; }
  133. public double data { get; set; }
  134. }
  135. public class TXResult
  136. {
  137. public double FirstOneReadyTime { get; set; }
  138. public double FirstOneArriveTime { get; set; }
  139. public double FirstOneMaxCover { get; set; }
  140. public int SingleMaxConnect { get; set; }//仅最大一架,单架输出另立列表
  141. public double AverageTotalCover { get; set; }
  142. public double FullCoverTime { get; set; }
  143. public int MaxTotalConnect { get; set; }
  144. public double ConnectTimeRatio { get; set; }
  145. public double UnitFulfilledRatio { get; set; }
  146. public string Stability { get; set; }
  147. public string Robustness { get; set; }
  148. public string Security { get; set; }
  149. }
  150. public class YJTX
  151. {
  152. //public static DemHelper DemHelper()//00
  153. // {
  154. // IDbHelper db = Factory.Load("10.130.100.5", "5432", "postgres", "postgres", "rescue_patrol_platform");
  155. // DemHelper ddemHelper = new DemHelper(db);
  156. // return ddemHelper;
  157. // }
  158. public static double[,] MaxMinPoly(List<double[]> poly)//01多边形矩形边界
  159. {
  160. List<double> PolyLon = new List<double>();
  161. List<double> PolyLat = new List<double>();
  162. foreach (double[] element in poly)
  163. {
  164. PolyLon.Add(element[0]);
  165. PolyLat.Add(element[1]);
  166. }
  167. double[,] MM1 = new double[2, 2];
  168. MM1[0, 0] = PolyLon.Min();//经度最小(西界)
  169. MM1[0, 1] = PolyLon.Max();//经度最大(东界)
  170. MM1[1, 0] = PolyLat.Min();//纬度最小(南界)
  171. MM1[1, 1] = PolyLat.Max();//纬度最大(北界)
  172. return MM1;
  173. }
  174. public static bool isinpoly(double[] zuobiao, List<double[]> poly, DemHelper demHelper)//02已经替换成在边界内算法
  175. {
  176. double[,] polyOut = MaxMinPoly(poly);
  177. if (zuobiao[0] <= polyOut[0, 0] || zuobiao[0] >= polyOut[0, 1] || zuobiao[1] <= polyOut[1, 0] || zuobiao[1] >= polyOut[1, 1])
  178. { return false; }
  179. else
  180. {
  181. string polystring = "MULTIPOLYGON(((";
  182. foreach (double[] element in poly)
  183. {
  184. double e0 = element[0];
  185. double e1 = element[1];
  186. polystring = polystring + element[0] + " " + element[1] + ",";
  187. }
  188. polystring = polystring + poly[0][0] + " " + poly[0][1] + ")))";
  189. string pointstring = "POINT (" + zuobiao[0] + " " + zuobiao[1] + ")";
  190. // Console.WriteLine("isinpoly?");
  191. //Console.WriteLine(pointstring+polystring);
  192. string r1 = demHelper.doDetermine(pointstring, polystring);
  193. // Console.WriteLine(r1);
  194. //double[,] polyOut = MaxMinPoly(poly);
  195. //if (zuobiao[0] <= polyOut[0, 0] || zuobiao[0] >= polyOut[0, 1] || zuobiao[1] <= polyOut[1, 0] || zuobiao[1] >= polyOut[1, 1])
  196. // { return false; }
  197. // else
  198. //{
  199. return (r1 == "True" ? true : false);
  200. // }
  201. }
  202. }
  203. //03格点生成方法[已删除]:输入前四个为经纬度上下限,数组为多边形,后两个是经纬度分辨率。输出0经,1纬,2高,3是否被侦察的【01】变量。
  204. //04格点初始化[已删除]
  205. //05格点显示【已删除】,可以不用
  206. //06两点间距计算,输出米
  207. public static double distance(double[] P1, double[] P2, DemHelper demHelper)
  208. {
  209. //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;
  210. //double D = Math.Pow(Math.Pow(DL, 2) + Math.Pow(P1[2] - P2[2], 2), 0.5);
  211. //return D;
  212. double3 p1 = new double3();
  213. double3 p2 = new double3();
  214. p1.x = P1[0];
  215. p1.y = P1[1];
  216. p1.z = P1[2];
  217. p2.x = P2[0];
  218. p2.y = P2[1];
  219. p2.z = P2[2];
  220. double D1 = demHelper.getDistance(p1, p2);
  221. //double DD1 = D1;
  222. //Console.WriteLine("距离:" + D1);
  223. return D1;
  224. }
  225. //07两点间距计算,(本地版),输出米
  226. public static double distance1(double[] P1, double[] P2)
  227. {
  228. 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;
  229. double D = Math.Pow(Math.Pow(DL, 2) + Math.Pow(P1[2] - P2[2], 2), 0.5);
  230. return D;
  231. }
  232. //08两点间高度角计算,从P1到P2,角度制
  233. public static double angleH(double[] P1, double[] P2)
  234. {
  235. if (P1[2] == P2[2])
  236. { return 0; }
  237. else if (P1[0] == P2[0] && P1[1] == P2[1])
  238. {
  239. if (P1[2] < P2[2])
  240. { return 90; }
  241. else { return -90; }
  242. }
  243. else
  244. {
  245. //if (P1[2] < P2[2])
  246. //{
  247. double angleH = Math.Asin((P2[2] - P1[2]) / distance1(P1, P2)) * (180 / Math.PI);
  248. return angleH;
  249. //}
  250. //else
  251. //{
  252. // double angleH = Math.Asin((P2[2] - P1[2]) / distance(P1, P2)) * (180 / Math.PI);
  253. // return angleH;
  254. //}
  255. }
  256. }
  257. //09MoveTo,输入单位坐标、目标坐标,输出时步结束时的单位坐标【暂不用】
  258. public static double[] MoveTo(double[] aircraft, double[] target, double V, double TimeStep, DemHelper demHelper)
  259. {
  260. 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) };
  261. double[] delta = { direction[0] * V * TimeStep, direction[1] * V * TimeStep, direction[2] * V * TimeStep };
  262. double[] next = { aircraft[0] + delta[0], aircraft[1] + delta[1], aircraft[2] + delta[2] };
  263. return next;
  264. }
  265. public static bool isBlocked(double[] P1, double[] P2, DemHelper demHelper)//10是否被地形遮挡
  266. {
  267. double3 p1 = new double3();
  268. double3 p2 = new double3();
  269. p1.x = P1[0];
  270. p1.y = P1[1];
  271. p1.z = P1[2];
  272. p2.x = P2[0];
  273. p2.y = P2[1];
  274. p2.z = P2[2];
  275. string r2 = demHelper.doIntervisibility(p1, p2);//这三行代码用于运行判定
  276. // Console.WriteLine("r2="+r2);
  277. return (r2 == "true" ? false : true);
  278. //return false;
  279. }
  280. //11是否符合观察条件【已删除】
  281. //12航线转object【暂不用】
  282. public static List<object[]> RouteInput(string TurningPointName, List<double[]> TurningPointLocation, string TurningPointType, double TurningPointVelocity, double SegmentFlightFuelConsumption, double SegmentFlightTime, double TurningRadius)
  283. {
  284. List<object[]> SCIP = new List<object[]>();
  285. int i = 0;
  286. foreach (double[] element in TurningPointLocation)
  287. {
  288. object[] SCIPtemt = { $"{TurningPointName}{i}", element, $"{TurningPointType}", TurningPointVelocity, SegmentFlightFuelConsumption, SegmentFlightTime, TurningRadius };
  289. SCIP.Add(SCIPtemt);
  290. i++;
  291. }
  292. return SCIP;
  293. }
  294. //13航线显示,不用管【暂不用】
  295. public static void ListscanRoute(List<double[]> SCtoRead)
  296. {
  297. Console.WriteLine("【showSC】");
  298. foreach (double[] element in SCtoRead)
  299. {
  300. string lontax = element[0].ToString("F5");
  301. string lattax = element[1].ToString("F5");
  302. Console.WriteLine("【E" + lontax + " | N" + lattax + " | h" + element[2] + "】\t");
  303. }
  304. }
  305. public static double HeightLL(double lon, double lat)//14经纬度提取高程
  306. {
  307. string req = "http://10.130.100.5:7785//rescue-platform-service/api/v1/dem/getInfos?lon=";
  308. req += lon;
  309. req += "&lat=";
  310. req += lat;
  311. var client = new HttpClient();
  312. //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");
  313. var request = new HttpRequestMessage(HttpMethod.Get, req);
  314. var response = client.Send(request);
  315. response.EnsureSuccessStatusCode();
  316. string BBB = "";
  317. if (response.IsSuccessStatusCode)
  318. {
  319. string content = response.Content.ReadAsStringAsync().Result; // 同步阻塞调用
  320. BBB = content;
  321. //Console.WriteLine(content);
  322. }
  323. Height data = JsonConvert.DeserializeObject<Height>(BBB);
  324. //Console.WriteLine("AAA");
  325. //string BBB =await response.Content.ReadAsStringAsync();
  326. Console.WriteLine("lo" + lon + "la" + lat + "h" + data.data);
  327. return data.data;
  328. }
  329. //15.字符串提取数字段
  330. public static List<int> intList(string intString)//示例:"1,3-5"
  331. {
  332. intString += ",";
  333. List<int> intList = new List<int>();
  334. int Length = intString.Length;
  335. string reading = "";
  336. string ii = "";
  337. int head = new int();
  338. int tail = new int();
  339. bool isSingle = new bool();
  340. for (int i = 0; i < Length; i++)
  341. {
  342. reading += intString[i];
  343. ii += intString[i];
  344. if (int.TryParse(reading, out int result) == true)
  345. { }
  346. else if (ii == "," && isSingle == true)
  347. {
  348. string readingNum = reading.Remove(reading.Length - 1);
  349. int adding = int.Parse(readingNum);
  350. intList.Add(adding);
  351. reading = "";
  352. }
  353. else if (ii == "-")
  354. {
  355. string readingNum = reading.Remove(reading.Length - 1);
  356. head = int.Parse(readingNum);
  357. isSingle = false;
  358. reading = "";
  359. }
  360. else if (ii == "," && isSingle == false)
  361. {
  362. string readingNum = reading.Remove(reading.Length - 1);
  363. tail = int.Parse(readingNum);
  364. for (int j = head; j <= tail; j++)
  365. { intList.Add(j); }
  366. isSingle = true;
  367. reading = "";
  368. }
  369. else
  370. {
  371. Console.WriteLine("int列表转换的字符串有非法字符,仅支持整数、“,”、“-”,无空格");
  372. }
  373. ii = "";
  374. }
  375. //foreach(int i in intList) { Console.WriteLine("int:"+i); }
  376. return intList;
  377. }
  378. //16.环形航线坐标更新
  379. public static double[] CirculeCoo(double Time, List<double[]> Route3D, double Speed)
  380. {
  381. double TotalTime = 0;
  382. List<double> TimeP = new List<double>();
  383. TimeP.Add(TotalTime);
  384. for (int i = 1; i < Route3D.Count; i++)
  385. {
  386. TotalTime += (distance1(Route3D[i], Route3D[i - 1]) / Speed);
  387. TimeP.Add(TotalTime);
  388. }
  389. TotalTime += (distance1(Route3D[0], Route3D[Route3D.Count - 1]) / Speed);
  390. TimeP.Add(TotalTime);
  391. double RestTime = Time % TotalTime;
  392. //Console.WriteLine(TotalTime+"TT||RT"+RestTime);
  393. double[] Head = new double[3];
  394. double[] Tail = new double[3];
  395. double[] Coo = new double[3];
  396. Route3D.Add(Route3D[0]);
  397. double ratioRoute = new double();
  398. for (int i = 0; i < TimeP.Count - 1; i++)//TimeP.Count比点数大1
  399. {
  400. if (RestTime >= TimeP[i] && RestTime <= TimeP[i + 1])
  401. {
  402. Head = Route3D[i];
  403. Tail = Route3D[i + 1];
  404. ratioRoute = (RestTime - TimeP[i]) / (TimeP[i + 1] - TimeP[i]);
  405. break;
  406. }
  407. }
  408. Coo[0] = Head[0] * (1 - ratioRoute) + Tail[0] * ratioRoute;
  409. Coo[1] = Head[1] * (1 - ratioRoute) + Tail[1] * ratioRoute;
  410. Coo[2] = Head[2] * (1 - ratioRoute) + Tail[2] * ratioRoute;
  411. double[] Coo1 = Coo;
  412. //Console.WriteLine("EEEEEEEEE" + Coo1[0] + "NNNNNNNNNN" + Coo1[1] + "HHHHHHHH" + Coo1[2]);
  413. Route3D.RemoveAt(Route3D.Count - 1);
  414. return Coo;
  415. }
  416. //17.坐标更新
  417. public static void statusMove(List<object[]> status, double Time, List<double[]> Route3D, double Speed, int movingUnit)//速度单位是米每秒
  418. {
  419. object[] statusMove = status[movingUnit];
  420. double[] CooTemp = (double[])statusMove[1];
  421. double[] CooNow = CirculeCoo(Time, Route3D, Speed);
  422. statusMove[1] = CooNow;//************需要更新为读取经纬高!!!
  423. //double Direction0 = Direction(CooTemp, CooNow);
  424. //statusMove[6] = Direction0;//
  425. double SailDirection =(Math.PI/2- Direction(CooTemp, CooNow)+ 2 * Math.PI) %(2* Math.PI);//*************需要更新为读取航向!!!!SailDirection是系统定义的航向
  426. double direction0 = (Math.PI / 2 - SailDirection + 2 * Math.PI) % (2 * Math.PI);
  427. if(direction0> Math.PI) { direction0 -= 2 * Math.PI; }
  428. statusMove[6] = direction0*180/Math.PI;//将正北顺时针0-360航向角转化为正东逆时针+-180航向角.记录这个。
  429. Console.WriteLine("航向角:"+ statusMove[6]);
  430. bool isMoved = true;
  431. statusMove[10] = isMoved;
  432. //status.RemoveAt(movingUnit);
  433. //status.Insert(movingUnit, statusMove);
  434. status[movingUnit] = statusMove;
  435. //return statusMove;
  436. }
  437. //通信设备定义,后期作为输入项
  438. //0.int编号
  439. //1.srting名称
  440. //2.通信中心频率,MHz
  441. //3.发射功率,dBm
  442. //4.发射天线增益,dB
  443. //5.接收机灵敏度,dBm
  444. //6.接收天线增益.dB
  445. //7.bool是否有转发功能
  446. //8.double发送流量限制Mbps
  447. //9.bool是否能接入外界网络
  448. //10.double[]通信角度{angleH0,angleH1,angleD0,angleD1}
  449. public static List<object[]> DeviceRead( List<object[]> DeviceDTBS)
  450. {
  451. List<object[]> Device = new List<object[]>();
  452. int i = 0;
  453. foreach(object[] element in DeviceDTBS)
  454. {
  455. int Number = i;
  456. string DeviceName = (string)element[0];
  457. double F = (double)element[1];
  458. double Pt = (double)element[2];
  459. double Gt = (double)element[3];
  460. double Pr = (double)element[4];
  461. double Gr = (double)element[5];
  462. bool canRelay = (bool)element[6];
  463. double RelayLimit = (double)element[7];
  464. bool isConnected = (bool)element[8];
  465. double[] AngleLimit = { (double)element[9], (double)element[10], (double)element[11], (double)element[12] };
  466. object[] DeviceToAdd = { Number, DeviceName, F, Pt, Gt, Pr, Gr, canRelay, RelayLimit, isConnected, AngleLimit };
  467. Device.Add(DeviceToAdd);
  468. i++;
  469. }
  470. return Device;
  471. }
  472. //通信单位定义,后期作为输入项
  473. //0.编号
  474. //1.名称
  475. //2.通信载荷种类int
  476. //3.double[]经纬高[初始位置]
  477. //4.本地遮挡衰减dB
  478. //5.本地数据流量需求Mbps
  479. //6.bool是否高优先级用户
  480. //7.bool是否通信基点
  481. //8.double初始朝向
  482. //9.bool是否网格
  483. public static void AddUnit(List<object[]> Unit, string Name, string DeviceName, double[] Location,double LossLocal,
  484. double RequiredData, bool isVIP,
  485. bool isBase, double direction0, List<object[]> Device)
  486. {
  487. int DeviceNumber = new int();
  488. for (int i = 0; i < Device.Count; i++)
  489. {
  490. if ((string)Device[i][1] == DeviceName)
  491. { DeviceNumber = i; break; }
  492. }
  493. int Number = Unit.Count;
  494. double H;
  495. double[] LocationH = { Location[0], Location[1], Location[2] };
  496. object[] UnitToAdd = { Number, Name, DeviceNumber, LocationH, LossLocal, RequiredData, isVIP, isBase, direction0, false };
  497. Unit.Add(UnitToAdd);
  498. }
  499. //方向角算法,从P1指向P2,弧度制,正东为0,逆时针,正负Pi
  500. public static double Direction(double[] P1, double[] P2)
  501. {
  502. double EW = 6371.004 * 2 * math.PI * math.cos(math.PI * P1[1] / 180) * (P2[0] - P1[0]) / 360;
  503. double SN = 6371.004 * 2 * math.PI * (P2[1] - P1[1]) / 360;
  504. double Direction = Math.Atan2(SN, EW);
  505. return Direction;
  506. }
  507. //通信载荷状态定义
  508. //0.编号
  509. //1.double[]经纬高
  510. //2.bool是否被联通
  511. //3.int当前通信层级
  512. //4.bool是否开启【默认开】
  513. //5.所连基点ID
  514. //6.double朝向
  515. //7.double上行数据量
  516. //8.int上级ID
  517. //9.List<int>连通性,0无判定,1连通,-1不通,三角。
  518. //10.是否被移动
  519. public static List<object[]> status(List<object[]> Unit)
  520. {
  521. List<object[]> status = new List<object[]>();
  522. foreach (object[] element in Unit)
  523. {
  524. int num = (int)element[0];
  525. double[] location = (double[])element[3];
  526. bool isConnected;
  527. int level;
  528. bool isOpen = true;
  529. double direction = (double)element[8];
  530. int BaseID;
  531. double UploadSpeed = 0;
  532. int upID;
  533. if ((bool)element[7] == true)
  534. {
  535. isConnected = true;
  536. level = 0;
  537. BaseID = num;
  538. upID = num;
  539. }
  540. else
  541. {
  542. isConnected = false;
  543. level = -1;
  544. BaseID = -1;
  545. upID = -1;
  546. }
  547. List<int> canSee = new List<int>();
  548. for (int i = 0; i < Unit.Count; i++)
  549. {
  550. canSee.Add(0);
  551. }
  552. bool isMoved = false;
  553. object[] StatusToAdd = { num, location, isConnected, level, isOpen, BaseID, direction, UploadSpeed, upID, canSee, isMoved };
  554. status.Add(StatusToAdd);
  555. }
  556. return status;
  557. }
  558. public static TXResult TXR(double FRT,string Stablility,string Robustness,string Security)
  559. {
  560. TXResult TXR = new TXResult();
  561. TXR.FirstOneReadyTime = FRT;
  562. TXR.FirstOneArriveTime = -1;
  563. TXR.FirstOneMaxCover = -1;
  564. TXR.SingleMaxConnect = -1;
  565. TXR.AverageTotalCover = -1;
  566. TXR.FullCoverTime = -1;
  567. TXR.MaxTotalConnect = -1;
  568. TXR.ConnectTimeRatio = -1;
  569. TXR.UnitFulfilledRatio = -1;
  570. TXR.Stability = Stablility;
  571. TXR.Robustness = Robustness;
  572. TXR.Security = Security;
  573. return TXR;
  574. }
  575. //通信余量计算算法
  576. //AL为航向角
  577. public static double Margin(int Unit1, int Unit2, List<object[]> Device, List<object[]> Unit, List<object[]> status, double MarginLimit, string TXEnvironment, DemHelper demHelper)
  578. //MarginLimit为通信余量下限,默认0
  579. {
  580. //Console.WriteLine("正在判断" + (string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "的连通性");
  581. int Device1 = (int)Unit[Unit1][2];//设备属性
  582. int Device2 = (int)Unit[Unit2][2];
  583. double F1 = (double)Device[Device1][2];//频率
  584. double F2 = (double)Device[Device2][2];
  585. if (F1 - F2 > 1)
  586. {
  587. // Console.WriteLine( (string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "不连通:频率不对");
  588. return -1; }//不对频就结束
  589. else
  590. {
  591. double Pt1 = (double)Device[Device1][3];//发射功率
  592. double Gt1 = (double)Device[Device1][4];//发射增益
  593. double Pr1 = (double)Device[Device1][5];//接收功率
  594. double Gr1 = (double)Device[Device1][6];//接收增益
  595. double[] AngleLimit1 = (double[])Device[Device1][10];//角度限制
  596. double LossLocal1 = (double)Unit[Unit1][4];//本地损失
  597. double[] Location1 = (double[])status[Unit1][1];//位置
  598. //Console.WriteLine((string)Unit[Unit1][1] + "<--11-->" + (string)Unit[Unit2][1]);
  599. List<int> canSee1 = (List<int>)status[Unit1][9];
  600. List<int> canSee2 = (List<int>)status[Unit2][9];
  601. bool isMoved2 = (bool)status[Unit2][10];
  602. bool isMoved1 = (bool)status[Unit1][10];
  603. double Pt2 = (double)Device[Device2][3];
  604. double Gt2 = (double)Device[Device2][4];
  605. double Pr2 = (double)Device[Device2][5];
  606. double Gr2 = (double)Device[Device2][6];
  607. double[] AngleLimit2 = (double[])Device[Device2][10];
  608. double LossLocal2 = (double)Unit[Unit2][4];
  609. double[] Location2 = (double[])status[Unit2][1];
  610. double D = distance1(Location1, Location2) / 1000;//距离,千米
  611. double PL12 = 20 * Math.Log10(F1) + 20 * Math.Log10(D) + 32.44;//自由空间
  612. //Console.WriteLine((string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "的自由空间损耗"+PL12);
  613. if (TXEnvironment=="郊区"||
  614. TXEnvironment == "城市" ||
  615. TXEnvironment == "密集城市" ||
  616. TXEnvironment == "高层建筑城市" )
  617. {
  618. string envi = TXEnvironment;
  619. double r = distance1(new double[] { Location1[0], Location1[1], 0 }, new double[] { Location2[0], Location2[1], 0 });//水平距离,m
  620. double f = F1 * 1000000;//频率,Hz
  621. double h = Math.Abs(Location1[2] - Location2[2]);//高度差,m
  622. double a = 0, b = 0, n_los = 0, n_nlos = 0;
  623. switch (envi)
  624. {
  625. case "郊区":
  626. a = 4.88;
  627. b = 0.43;
  628. n_los = 0.1;
  629. n_nlos = 21;
  630. break;
  631. case "城市":
  632. a = 9.61;
  633. b = 0.16;
  634. n_los = 1;
  635. n_nlos = 20;
  636. break;
  637. case "密集城市":
  638. a = 12.08;
  639. b = 0.11;
  640. n_los = 1.6;
  641. n_nlos = 23;
  642. break;
  643. case "高层建筑城市":
  644. a = 27.23;
  645. b = 0.08;
  646. n_los = 2.3;
  647. n_nlos = 34;
  648. break;
  649. }
  650. //double pi = 3.1415926;
  651. double c = 299552816;
  652. double A = n_los - n_nlos;
  653. double B = 20 * Math.Log10(f) + 20 * Math.Log10(4 * Math.PI / c) + n_nlos;
  654. double fm = 1 + a * Math.Exp(-b * (Math.Atan(h / r)*180/Math.PI - a));
  655. double pl = A / fm + 10 * Math.Log10(h * h + r * r) + B;
  656. // double pl = A / fm + 20 * Math.Log10(D*1000)+ B;
  657. // Console.WriteLine((string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "的自由空间损耗" + PL12+"环境损耗" + pl + " r=" + r + " h=" + h);//+ " A/fm=" + (A / fm));
  658. PL12 = pl;
  659. //+ " A/fm=" + (A/fm) + " B+30-20 * Math.Log10(F1)=" + (B+30- 20 * Math.Log10(F1)));
  660. }
  661. double Loss12 = PL12
  662. + LossLocal1
  663. + LossLocal2;//***损耗计算,暂时仅自由空间+本地损失***
  664. double SafeL1to2 = Pt1 + Gt1 - Pr2 + Gr2 - MarginLimit;//安全损耗
  665. double SafeL2to1 = Pt2 + Gt2 - Pr1 + Gr1 - MarginLimit;
  666. double A1 = Direction(Location1, Location2)*180/Math.PI;//连线方向角
  667. double A2 = Direction(Location2, Location1) * 180 / Math.PI;
  668. double AL1 = (double)status[Unit1][6];//单位航向角
  669. double AL2 = (double)status[Unit2][6];
  670. double AA1 = (A1 - AL1) % 360;
  671. double AA2 = (A2 - AL2) % 360;//天线与目标夹角
  672. if (AA1 >180) { AA1 = AA1 - 360; }
  673. if (AA1 <-180) { AA1 = AA1 + 360; }
  674. if (AA2 > 180) { AA2 = AA2 - 360; }
  675. if (AA2 < -180) { AA2 = AA2 +360; }
  676. //Console.WriteLine("AL1="+AL1+ "AL2=" + AL2+"AA1=" + AA1 + "AA2=" + AA2);
  677. double AV1 = angleH(Location1, Location2);//垂直高度角
  678. double AV2 = angleH(Location2, Location1);
  679. bool isInDirection = false;
  680. if (AA1 >= AngleLimit1[2] && AA1 <= AngleLimit1[3]
  681. && AA2 >= AngleLimit2[2] && AA2 <= AngleLimit2[3]
  682. && AV1 >= AngleLimit1[0] && AV1 <= AngleLimit1[1]
  683. && AV2 >= AngleLimit2[0] && AV2 <= AngleLimit2[1])
  684. { isInDirection = true; }//判断是否在角度限制内
  685. //Console.WriteLine(SafeL2to1 - Loss12);
  686. //Console.WriteLine(SafeL1to2 - Loss12);
  687. //Console.WriteLine(isInDirection);
  688. if (SafeL1to2 >= Loss12 && SafeL2to1 >= Loss12 && isInDirection == true)
  689. //if (SafeL1to2 >= Loss12 && SafeL2to1 >= Loss12 && isInDirection == true)
  690. {
  691. bool isBlock = new bool();
  692. if (isMoved1 == false && isMoved2 == false && Unit2 < Unit1 && canSee1[Unit2] != 0)
  693. {
  694. if (canSee1[Unit2] < 0)
  695. {
  696. isBlock = true;
  697. }
  698. else
  699. {
  700. isBlock = false;
  701. }
  702. }
  703. else if (isMoved1 == false && isMoved2 == false && Unit2 > Unit1 && canSee2[Unit1] != 0)
  704. {
  705. if (canSee2[Unit1] < 0)
  706. {
  707. isBlock = true;
  708. }
  709. else
  710. {
  711. isBlock = false;
  712. }
  713. }
  714. else
  715. {
  716. //Stopwatch stopwatch = Stopwatch.StartNew();
  717. isBlock = isBlocked(Location1, Location2, demHelper);//是否被遮挡
  718. //stopwatch.Stop();
  719. //Console.WriteLine($"{(string)Unit[Unit1][1]}与{(string)Unit[Unit2][1]}地形判断耗时{stopwatch.ElapsedMilliseconds} 毫秒");
  720. if (isMoved1 == false && isMoved2 == false)
  721. {
  722. if (isBlock == true)
  723. {
  724. //Console.WriteLine(Unit2 + "---->" + canSee1.Count);
  725. //canSee1.RemoveAt(Unit2);
  726. //canSee1.Insert(Unit2, -1);
  727. canSee1[Unit2] = -1;
  728. // Console.WriteLine(Unit1 + "---->" + canSee1.Count);
  729. //canSee2.RemoveAt(Unit1);
  730. //canSee2.Insert(Unit1, -1);
  731. canSee2[Unit1] = -1;
  732. }
  733. else
  734. {
  735. // Console.WriteLine(Unit2 + "---->" + canSee1.Count);
  736. //canSee1.RemoveAt(Unit2);
  737. //canSee1.Insert(Unit2, 1);
  738. canSee1[Unit2] = 1;
  739. // Console.WriteLine(Unit1 + "---->" + canSee1.Count);
  740. //canSee2.RemoveAt(Unit1);
  741. //canSee2.Insert(Unit1, 1);
  742. canSee2[Unit1] = 1;
  743. }
  744. object[] status1 = status[Unit1];
  745. object[] status2 = status[Unit2];
  746. status1[9] = canSee1;
  747. status2[9] = canSee2;
  748. //status.RemoveAt(Unit1);
  749. //status.Insert( Unit1,status1);
  750. status[Unit1] = status1;
  751. //status.RemoveAt(Unit2);
  752. //status.Insert( Unit2,status2);
  753. status[Unit2] = status2;
  754. }
  755. }
  756. //Console.WriteLine((string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "bolck:" + isBlock);
  757. if (isBlock != true)
  758. {
  759. if (SafeL1to2 >= SafeL2to1)
  760. {
  761. //Console.WriteLine((string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "连通");
  762. return SafeL2to1 - Loss12; }//输出双向通信余量的小者
  763. else {
  764. // Console.WriteLine((string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "连通");
  765. return SafeL1to2 - Loss12; }
  766. }
  767. else
  768. {
  769. //Console.WriteLine((string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "不连通:地形遮挡");
  770. return -1;//通不上就返-1
  771. }
  772. }
  773. else
  774. {
  775. //Console.WriteLine((string)Unit[Unit1][1] + "与" + (string)Unit[Unit2][1] + "不连通:在距离外");
  776. return -1;//通不上就返-1
  777. }
  778. }
  779. }
  780. public static List<object[]> ASAStatusLevel(List<object[]> Device, List<object[]> Unit, List<object[]> Status, double MarginLimit, int RelayLimit, string TXEnvironment, DemHelper demHelper)
  781. //RelayLimit是中继次数限制
  782. {
  783. bool[] isOpen = new bool[Unit.Count];//本轮通信是否被激活
  784. bool[] isConnected = new bool[Unit.Count];//是否被联通
  785. int[] Level = new int[Unit.Count];//记录本轮通信层级
  786. double[] margin = new double[Unit.Count];//记录余量
  787. int[] UpID = new int[Unit.Count];//记录上一级ID
  788. int[] BaseID = new int[Unit.Count];//记录指向的base
  789. double[] UploadSpeed = new double[Unit.Count];//记录上行数据速度
  790. for (int i = 0; i < Unit.Count; i++)//初始化
  791. {
  792. isOpen[i] = false;
  793. margin[i] = -1;
  794. UploadSpeed[i] = 0;
  795. if ((bool)Unit[i][7] == true)
  796. {
  797. isConnected[i] = true;
  798. BaseID[i] = (int)Unit[i][0];
  799. Level[i] = 0;
  800. UpID[i] = i;
  801. }
  802. else
  803. {
  804. isConnected[i] = false;
  805. BaseID[i] = -1;
  806. Level[i] = -1;
  807. UpID[i] = -1;
  808. }
  809. }
  810. for (int relay = 1; relay <= RelayLimit; relay++)//relay是将要更新的层级
  811. {
  812. //单层初始化
  813. for (int i = 0; i < Unit.Count; i++)
  814. {
  815. if (Level[i] == relay - 1 && (bool)Device[(int)Unit[i][2]][7] == true)
  816. {
  817. isOpen[i] = true;//仅开启上一级能中继的设备
  818. //Console.WriteLine(i + "open");
  819. }
  820. else { isOpen[i] = false; }
  821. }
  822. //找一个指向上一级的目标
  823. //TaskFactory fac1 = new TaskFactory(new LimitedConcurrencyLevelTaskScheduler(128));
  824. Task[] LevelTasks = new Task[Unit.Count];// Unit.Count];
  825. for (int i = 0; i < Unit.Count; i++)
  826. {
  827. int ii = i;
  828. LevelTasks[ii] = Task.Run(() =>
  829. {
  830. if (ii < Unit.Count && isOpen[ii] == true)
  831. {
  832. //Console.WriteLine("UNC" + Unit.Count);
  833. Task[] UnitTasks = new Task[Unit.Count];
  834. for (int j = 0; j < Unit.Count; j++)
  835. {
  836. int jj = j;
  837. UnitTasks[jj] = //fac1.StartNew(s =>
  838. Task.Run(() =>
  839. {
  840. //int Levelj = ;
  841. double mar = -1;
  842. if (jj < Unit.Count && ii != jj && (Level[jj] == -1 || Level[jj] == relay))
  843. {
  844. mar = Margin(ii, jj, Device, Unit, Status, MarginLimit,TXEnvironment ,demHelper);
  845. // Console.WriteLine("完成,mar:" + mar + "jj:" + jj);
  846. if (jj < Unit.Count && mar > 0 && (margin[jj] < 0 || mar > margin[jj]))
  847. {
  848. margin[jj] = mar;
  849. UpID[jj] = ii;
  850. BaseID[jj] = BaseID[ii];
  851. Level[jj] = relay;
  852. isConnected[jj] = true;
  853. //Console.WriteLine("单位" + ii + "与" + "单位" + jj + "连通");
  854. }
  855. }
  856. //Console.WriteLine("完成单位" + ii + "与" + "单位" + jj + "连通判定");
  857. }
  858. );//,ii*Unit.Count+jj);
  859. }
  860. Task.WaitAll(UnitTasks);
  861. }
  862. });
  863. }
  864. Task.WaitAll(LevelTasks);
  865. }
  866. for (int rerelay = Level.Max(); rerelay >= 0; rerelay--)//倒查并记录数据流量
  867. {
  868. for (int i = 0; i < Unit.Count; i++)
  869. {
  870. if (Level[i] == rerelay)
  871. {
  872. //Console.WriteLine(i + "号设备上行速率需求" + (double)Unit[i][5] + "Mbps");
  873. UploadSpeed[i] += (double)Unit[i][5];
  874. if (i != UpID[i])
  875. {
  876. UploadSpeed[UpID[i]] += UploadSpeed[i];
  877. }
  878. //Console.WriteLine(i + "号设备上行速率" + UploadSpeed[i] + "Mbps");
  879. }
  880. }
  881. }
  882. List<object[]> newStatus = new List<object[]>();
  883. for (int i = 0; i < Unit.Count; i++)
  884. {
  885. 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] };
  886. newStatus.Add(StatusToAdd);
  887. }//将2,3,5写入新Status
  888. return newStatus;
  889. }
  890. public static void ASASLevelCalculate(List<object[]> Device, List<object[]> Unit, List<object[]> Status, double MarginLimit, int RelayLimit, string TXEnvironment, DemHelper demHelper)
  891. //RelayLimit是中继次数限制
  892. {
  893. List<object[]> newStatus = YJTX.ASAStatusLevel(Device, Unit, Status, MarginLimit, RelayLimit, TXEnvironment, demHelper);
  894. Status.Clear();
  895. for (int i = 0; i < Unit.Count; i++)
  896. {
  897. Status.Add(newStatus[i]);
  898. }//刷新status
  899. }
  900. public static void ShowStatus(List<object[]> Device, List<object[]> Unit, List<object[]> Status)
  901. {
  902. for (int i = 0; i < Unit.Count; i++)
  903. {
  904. double[] Location = (double[])Status[i][1];
  905. string ConMark;
  906. if ((bool)Status[i][2] == true)
  907. { ConMark = "是"; }
  908. else
  909. { ConMark = "否"; }
  910. string OnMark;
  911. if ((bool)Status[i][4] == true)
  912. { OnMark = "开启"; }
  913. else
  914. { OnMark = "关闭"; }
  915. Console.WriteLine("编号:" + (int)Status[i][0] + "|单位名称:" + (string)Unit[i][1] + "|设备名称:" + (string)Device[(int)Unit[i][2]][1] +
  916. "|位置:E" + Location[0] + "°N" + Location[1] + "°H" + Location[2] + "m|方向角:" + (double)Status[i][6] + "°|连通状态:"
  917. + ConMark + "|当前通信层级:" + (int)Status[i][3] + "|当前载荷状态:" + OnMark +
  918. "|所连基点ID:" + (int)Status[i][5] + "上行数据速率:" + (double)Status[i][7] + "Mbps");
  919. Console.WriteLine("___________________________________________");
  920. }
  921. }
  922. //区域网格生成
  923. public static List<object[]> TXNPGenerate(List<double[]> juxing, double netscalelon, double netscalelat, double DeviceHeight,
  924. string DeviceName, string NetName, double LocalLost,
  925. List<object[]> Device,
  926. DemHelper demHelper)
  927. //DeviceHeight设备高度,单位m
  928. //LocalLost网格本地遮挡,单位dB
  929. {
  930. Console.WriteLine("格点生成");
  931. List<object[]> netpoints = new List<object[]>();
  932. int DeviceNumber = new int();
  933. for (int i = 0; i < Device.Count; i++)
  934. {
  935. if ((string)Device[i][1] == DeviceName)
  936. { DeviceNumber = i; break; }
  937. }
  938. double lonmin = -1000;
  939. double lonmax = -1000;
  940. double latmin = -1000;
  941. double latmax = -1000;
  942. foreach (double[] element in juxing)
  943. {
  944. if (lonmin == -1000 || element[0] < lonmin)
  945. { lonmin = element[0]; }
  946. if (lonmax == -1000 || element[0] > lonmax)
  947. { lonmax = element[0]; }
  948. if (latmin == -1000 || element[1] < latmin)
  949. { latmin = element[1]; }
  950. if (latmax == -1000 || element[1] > latmax)
  951. { latmax = element[1]; }
  952. }
  953. for (double[] netpointprev = new double[3] { lonmin, latmax, 0 }; netpointprev[1] >= latmin; netpointprev[1] = netpointprev[1] - netscalelat)
  954. {
  955. int i = 0;
  956. for (netpointprev[0] = lonmin; netpointprev[0] <= lonmax; netpointprev[0] = netpointprev[0] + netscalelon)
  957. {
  958. if (isinpoly(netpointprev, juxing, demHelper) == true)
  959. {
  960. double HH = HeightLL(netpointprev[0], netpointprev[1]);//需要替换为该点【netpointprev[0], netpointprev[1]】高程
  961. double[] netpointtemp = new double[3] { netpointprev[0], netpointprev[1], HH + DeviceHeight };
  962. //netpointtemp = netpointprev;
  963. string GridName = NetName + i;
  964. object[] GridToAdd = { i, GridName, DeviceNumber, netpointtemp, LocalLost, 0.0, false, false, 0.0, true };
  965. netpoints.Add(GridToAdd);
  966. i++;
  967. }
  968. }
  969. }
  970. return netpoints;
  971. }
  972. //区域网格计算
  973. public static int[] AreaConnectCheck(List<object[]> TXNP,
  974. List<object[]> Device, List<object[]> Unit, List<object[]> Status,
  975. int[] UnitInvolved,//计算涉及的通信网络,至少含一基站类目标
  976. double MarginLimit,//有效计算的通信余量
  977. string TXEnvironment,
  978. DemHelper demHelper
  979. )
  980. {
  981. int TXNPCount = TXNP.Count;
  982. int[] AreaCheck = new int[TXNPCount];
  983. //if (TXNPCount == 0)
  984. //{
  985. // Console.WriteLine("无网格");
  986. // return AreaCheck;
  987. //}
  988. //else
  989. //{
  990. List<object[]> NPStatus = status(TXNP);
  991. for (int i = 0; i < UnitInvolved.Length; i++)
  992. {
  993. TXNP.Add(Unit[UnitInvolved[i]]);
  994. }
  995. for (int i = 0; i < UnitInvolved.Length; i++)
  996. {
  997. object[] StatusToAdd = Status[UnitInvolved[i]];
  998. bool isMoved = true;
  999. StatusToAdd[10] = isMoved;
  1000. NPStatus.Add(StatusToAdd);
  1001. //Console.WriteLine("involve" + Status[UnitInvolved[i]].Length);
  1002. }
  1003. List<Object[]> NPstatusLevel = ASAStatusLevel(Device, TXNP, NPStatus, MarginLimit, 1, TXEnvironment, demHelper);
  1004. for (int i = 0; i < TXNPCount; i++)
  1005. {
  1006. if ((int)NPstatusLevel[i][3] > 0)
  1007. {
  1008. AreaCheck[i] = (int)NPstatusLevel[i][5];
  1009. }
  1010. else
  1011. {
  1012. AreaCheck[i] = -1;
  1013. }
  1014. }
  1015. for (int i = 0; i < UnitInvolved.Length; i++)
  1016. {
  1017. TXNP.RemoveAt(TXNP.Count - 1);
  1018. }
  1019. return AreaCheck;
  1020. //}
  1021. }
  1022. public static void AreaCheckPostProcess(double Time, List<double[]> poly, int[] BaseList, int[] AreaConnectCheck, List<object[]> TXNP, string CalculateName, double netscalelon, double netscalelat, List<object[]> GridResult)
  1023. //区域网格后处理
  1024. {
  1025. double[,] MM1 = MaxMinPoly(poly);
  1026. double W = MM1[0, 0];//经度最小(西界)
  1027. double E = MM1[0, 1];//经度最大(东界)
  1028. double S = MM1[1, 0]; //纬度最小(南界)
  1029. double N = MM1[1, 1];//纬度最大(北界);
  1030. double kmPerlat = 111.1;
  1031. double kmPerlon = kmPerlat * Math.Cos((Math.PI / 180) * ((N + S) / 2));
  1032. double SPerGrid = (netscalelon * kmPerlon) * (netscalelat * kmPerlat);
  1033. int NPNumber = AreaConnectCheck.Length;
  1034. int ConnectedNP = 0;
  1035. int[] ConnectedSingle = new int[BaseList.Length];
  1036. for (int j = 0; j < BaseList.Length; j++)
  1037. {
  1038. ConnectedSingle[j] = 0;
  1039. }
  1040. for (int i = 0; i < NPNumber; i++)
  1041. {
  1042. if (AreaConnectCheck[i] >= 0)
  1043. {
  1044. ConnectedNP++;
  1045. for (int j = 0; j < BaseList.Length; j++)
  1046. {
  1047. if (BaseList[j] == AreaConnectCheck[i]) { ConnectedSingle[j]++; }
  1048. }
  1049. }
  1050. }
  1051. double[] AreaSingle = new double[ConnectedSingle.Length];//各单机连接区域面积
  1052. for (int j = 0; j < ConnectedSingle.Length; j++)
  1053. {
  1054. AreaSingle[j] = SPerGrid * ConnectedSingle[j];
  1055. }
  1056. double Ratio = (double)ConnectedNP / NPNumber;
  1057. double AreaTotal = SPerGrid * ConnectedNP;
  1058. Console.WriteLine("计算名称:" + CalculateName + "||网格总数:" + NPNumber + "||连接网格数:" + ConnectedNP + "||比例:" + Ratio * 100 + "%");
  1059. //string csvFilePath = CalculateName + "output.csv";//需csv输出则取消注释1/5
  1060. //using (var writer = new StreamWriter(csvFilePath))//需csv输出则取消注释2/5
  1061. //{//需csv输出则取消注释3/5
  1062. // for (int k = 0; k < NPNumber; k++)
  1063. // {
  1064. // double[] item = (double[])TXNP[k][3];
  1065. // if (AreaConnectCheck[k] >= 0)
  1066. // {
  1067. // string Fmt = "{0} , {1}";
  1068. // for (int i = 0; i <= AreaConnectCheck[k]; i++)
  1069. // { Fmt += " ,"; }
  1070. // Fmt += "{1}";
  1071. // writer.WriteLine(String.Format(Fmt, item[0], item[1]));
  1072. // }
  1073. // else
  1074. // { writer.WriteLine(String.Format("{0} ,{1} ", item[0], item[1])); }
  1075. // }
  1076. //}
  1077. object[] StepResult = { Time, BaseList, AreaSingle, Ratio, AreaTotal };
  1078. GridResult.Add(StepResult);
  1079. }
  1080. //区域内随机数生成
  1081. public static List<object[]> TXRandomGenerate(List<double[]> juxing, int pointnumber, //生成的随机格点数量
  1082. double DeviceHeight,//DeviceHeight设备高度,单位m
  1083. string DeviceName, string NetName, double LocalLost,
  1084. double DataSpeedPerPiont,
  1085. int firstNum,//首点ID
  1086. //List<object[]> Device,
  1087. List<object[]>Device,DemHelper demHelper)
  1088. //LocalLost网格本地遮挡,单位dB
  1089. {
  1090. Console.WriteLine("随机点生成");
  1091. List<object[]> netpoints = new List<object[]>();
  1092. double lonmin = -1000;
  1093. double lonmax = -1000;
  1094. double latmin = -1000;
  1095. double latmax = -1000;
  1096. foreach (double[] element in juxing)
  1097. {
  1098. if (lonmin == -1000 || element[0] < lonmin)
  1099. { lonmin = element[0]; }
  1100. if (lonmax == -1000 || element[0] > lonmax)
  1101. { lonmax = element[0]; }
  1102. if (latmin == -1000 || element[1] < latmin)
  1103. { latmin = element[1]; }
  1104. if (latmax == -1000 || element[1] > latmax)
  1105. { latmax = element[1]; }
  1106. }
  1107. //四界
  1108. int DeviceNumber = new int();
  1109. for (int i = 0; i < Device.Count; i++)
  1110. {
  1111. if ((string)Device[i][1] == DeviceName)
  1112. { DeviceNumber = i; break; }
  1113. }
  1114. System.Random lonRam = new System.Random();
  1115. System.Random latRam = new System.Random();
  1116. TaskFactory fac = new TaskFactory(new LimitedConcurrencyLevelTaskScheduler(64));
  1117. Task[] PointTasks = new Task[pointnumber];
  1118. for (int i = 0; i < pointnumber;)
  1119. {
  1120. double lon = lonmin + lonRam.NextDouble() * (lonmax - lonmin);
  1121. double lat = latmin + latRam.NextDouble() * (latmax - latmin);
  1122. double[] netpointprev = { lon, lat };
  1123. if (isinpoly(netpointprev, juxing, demHelper) == true)
  1124. {
  1125. int ii = i;
  1126. //PointTasks[ii] = Task.Run(() =>
  1127. //{
  1128. PointTasks[ii] = fac.StartNew(s =>
  1129. {
  1130. if (ii < pointnumber)
  1131. {
  1132. double HH = HeightLL(netpointprev[0], netpointprev[1]);
  1133. double[] netpointtemp = new double[3] { netpointprev[0], netpointprev[1], HH + DeviceHeight };
  1134. string GridName = NetName + ii;
  1135. object[] GridToAdd = { ii + firstNum, GridName, DeviceNumber, netpointtemp, LocalLost, DataSpeedPerPiont, false, false, 0.0, false };
  1136. netpoints.Add(GridToAdd);
  1137. }
  1138. }, ii);
  1139. //});
  1140. i++;
  1141. }
  1142. }
  1143. //Task.WaitAll(fac.);
  1144. //TaskFactory.Continue(fac);
  1145. Task.WaitAll(PointTasks);
  1146. return netpoints;
  1147. }
  1148. public static void TXRandomAdd(List<double[]> juxing, int pointnumber, //生成的随机格点数量
  1149. double DeviceHeight,//DeviceHeight设备高度,单位m
  1150. string DeviceType, string NetName, double LocalLost,
  1151. double DataSpeedPerPiont,
  1152. //int firstNum,//首点ID
  1153. List<object[]> Unit,
  1154. List<object[]>Device,
  1155. DemHelper demHelper)
  1156. {
  1157. List<object[]> TXNP = TXRandomGenerate(juxing, pointnumber, DeviceHeight, DeviceType, NetName, LocalLost, DataSpeedPerPiont, Unit.Count,Device,demHelper);
  1158. foreach (object[] element in TXNP)
  1159. {
  1160. Unit.Add(element);
  1161. }
  1162. }
  1163. public static void ConnectNetPostProcess(double Time, List<object[]> Device, List<object[]> Unit, List<object[]> Status, string CalculateName, string involvedUnit, List<object[]> NetResult)
  1164. //通信网络后处理
  1165. {
  1166. List<int> involvedUnitNum = intList(involvedUnit);
  1167. bool[] isInvolved = new bool[Status.Count];
  1168. List<int> BaseList = new List<int>();
  1169. List<int> ConnectedSingle = new List<int>();
  1170. List<double> BaseFull = new List<double>();
  1171. for (int i = 0; i < Status.Count; i++)
  1172. {
  1173. isInvolved[i] = false;
  1174. }
  1175. int involvedNP = 0;
  1176. int Fulfilled = 0;
  1177. foreach (int i in involvedUnitNum)
  1178. { if (i < Status.Count)
  1179. {
  1180. isInvolved[i] = true; involvedNP++;
  1181. if ((int)Status[i][3] == 0)
  1182. {
  1183. BaseList.Add(i);
  1184. ConnectedSingle.Add(0);
  1185. double UpLimit = (double)Device[(int)Unit[i][2]][8];
  1186. double UpRatio = (double)Status[i][7] / UpLimit;
  1187. BaseFull.Add(UpRatio);
  1188. }
  1189. }
  1190. }
  1191. int NPNumber = Status.Count;
  1192. int ConnectedNP = 0;
  1193. for (int i = 0; i < NPNumber; i++)
  1194. {
  1195. if ((int)Status[i][3] >= 0 && isInvolved[i] == true)
  1196. {
  1197. ConnectedNP++;
  1198. }
  1199. if ((int)Status[i][3] > 0 && isInvolved[i] == true)
  1200. {
  1201. for (int j = 0; j < BaseList.Count; j++)
  1202. {
  1203. if (BaseList[j] == (int)Status[i][5])
  1204. {
  1205. ConnectedSingle[j]++;
  1206. if (BaseFull[j]<1)
  1207. {
  1208. Fulfilled++;
  1209. }
  1210. }
  1211. }
  1212. }
  1213. }
  1214. int TotalConnected = ConnectedNP - BaseList.Count;
  1215. int nonBasePoint = involvedNP - BaseList.Count;
  1216. double Ratio = (double)TotalConnected / nonBasePoint;
  1217. double FulRatio=(double)Fulfilled/ nonBasePoint;
  1218. object[] StepResult = { Time, BaseList, ConnectedSingle, TotalConnected, BaseFull, FulRatio };
  1219. NetResult.Add(StepResult);
  1220. Console.WriteLine("计算名称:" + CalculateName + "||基站数:" + BaseList.Count + "||非基站节点数:" + nonBasePoint + "||连接节点数:" + TotalConnected + "||比例:" + Ratio * 100 + "%");
  1221. //string csvFilePath = CalculateName + "output.csv";
  1222. //using (var writer = new StreamWriter(csvFilePath))
  1223. //{
  1224. // for (int k = 0; k < NPNumber; k++)
  1225. // {
  1226. // if (isInvolved[k] == true)
  1227. // {
  1228. // double[] item = (double[])Status[k][1];
  1229. // int level = (int)Status[k][3];
  1230. // if ((int)Status[k][3] >= 0)
  1231. // {
  1232. // string Fmt = "{0} , {1},{2}";
  1233. // for (int i = 0; i <= (int)Status[k][5]; i++)
  1234. // { Fmt += " ,"; }
  1235. // Fmt += "{2}";
  1236. // writer.WriteLine(String.Format(Fmt, level, item[0], item[1]));
  1237. // }
  1238. // else
  1239. // { writer.WriteLine(String.Format("{0} ,{1},{2} ", level, item[0], item[1])); }
  1240. // }
  1241. // }
  1242. //}
  1243. }
  1244. public static void Draw(List<double[]> poly, List<double[]> point, List<Color> ColorP, List<List<double[]>> points, List<Color> color, int PxPerKm, string name)//可视化,下一步改成自动颜色!
  1245. {
  1246. // 创建一个位图
  1247. double[,] MM1 = MaxMinPoly(poly);
  1248. double W = MM1[0, 0];//经度最小(西界)
  1249. double E = MM1[0, 1];//经度最大(东界)
  1250. double S = MM1[1, 0]; //纬度最小(南界)
  1251. double N = MM1[1, 1];//纬度最大(北界);
  1252. double kmPerlat = 111.1;
  1253. double kmPerlon = kmPerlat * Math.Cos((Math.PI / 180) * ((N + S) / 2));
  1254. //Console.WriteLine(E+"+"+W);
  1255. static int LonToPx(double lon, double W, double kmPerlon, int PxPerKm)
  1256. {
  1257. double LonKm = (lon - W) * kmPerlon;
  1258. int LonPx = (int)(LonKm * PxPerKm);
  1259. return LonPx;
  1260. }
  1261. static int LatToPx(double lat, double N, double kmPerlat, int PxPerKm)//从北向南!!
  1262. {
  1263. double LatKm = (N - lat) * kmPerlat;
  1264. int LatPx = (int)(LatKm * PxPerKm);
  1265. return LatPx;
  1266. }
  1267. int EW = LonToPx(E, W, kmPerlon, PxPerKm);
  1268. int NS = LatToPx(S, N, kmPerlat, PxPerKm);
  1269. //Console.WriteLine(EW + "EW|NS" + NS);
  1270. using Bitmap bitmap = new Bitmap(EW, NS);//位图大小东西南北界
  1271. using (Graphics g = Graphics.FromImage(bitmap))
  1272. {
  1273. g.Clear(Color.White); // 使用Clear方法填充背景色
  1274. }
  1275. using Graphics graphics = Graphics.FromImage(bitmap);
  1276. for (int i = 1; i < poly.Count; i++)
  1277. {
  1278. int penWidth = math.max(EW, NS) / 500;
  1279. using Pen Pen = new Pen(Color.Black, penWidth);
  1280. Point Point1 = new Point(LonToPx(poly[i - 1][0], W, kmPerlon, PxPerKm), LatToPx(poly[i - 1][1], N, kmPerlat, PxPerKm));
  1281. Point Point2 = new Point(LonToPx(poly[i][0], W, kmPerlon, PxPerKm), LatToPx(poly[i][1], N, kmPerlat, PxPerKm));
  1282. graphics.DrawLine(Pen, Point1, Point2);
  1283. }
  1284. for (int i = 0; i < point.Count; i++)
  1285. {
  1286. int penWidth = math.max(EW, NS) / 500;
  1287. using Pen Pen = new Pen(ColorP[i], penWidth);
  1288. //Rectangle rg = new Rectangle(0, 0, math.max(EW, NS) / 300, math.max(EW, NS) / 300);
  1289. float RGsize = math.max(EW, NS) / 300;
  1290. 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);
  1291. }
  1292. for (int i = 0; i < points.Count; i++)
  1293. {
  1294. int penWidth = math.max(EW, NS) / 1000;
  1295. using Pen Pen = new Pen(color[i % color.Count], penWidth);
  1296. for (int j = 0; j < points[i].Count; j++)
  1297. {
  1298. Point Point1 = new Point(LonToPx(points[i][j][0], W, kmPerlon, PxPerKm), LatToPx(points[i][j][1], N, kmPerlat, PxPerKm));
  1299. Point Point2 = new Point(LonToPx(points[i][j][2], W, kmPerlon, PxPerKm), LatToPx(points[i][j][3], N, kmPerlat, PxPerKm));
  1300. graphics.DrawLine(Pen, Point1, Point2);
  1301. }
  1302. }
  1303. // 定义两个坐标点
  1304. // Point point1 = new Point(50, 50);
  1305. // Point point2 = new Point(150, 150);
  1306. // Point point3= new Point(100, 150);
  1307. // 使用Pen来定义直线的颜色和宽度
  1308. // using Pen pen = new Pen(Color.Black, 2);
  1309. // 画直线
  1310. // graphics.DrawLine(pen, point1, point2);
  1311. // graphics.DrawLine(pen, point1, point3);
  1312. // 保存图像到文件
  1313. //bitmap.Save("line.png");
  1314. // 或者显示图像
  1315. bitmap.Save(name + ".jpeg");
  1316. Console.WriteLine("已画制并保存到" + name + ".jpeg文件中。||" + EW + "EW|NS" + NS);
  1317. }
  1318. public static void Drawnet(List<object[]> Status, string involvedUnit, List<double[]> poly, int PxPerKm, string name)
  1319. {
  1320. List<Color> color = new List<Color>();
  1321. //color.Add(Color.Black);
  1322. color.Add(Color.Red);
  1323. color.Add(Color.Orange);
  1324. color.Add(Color.Yellow);
  1325. color.Add(Color.Green);
  1326. color.Add(Color.Cyan);
  1327. color.Add(Color.Blue);
  1328. color.Add(Color.Purple);
  1329. List<Color> colorP = new List<Color>();//不同基站的上色方案:红橙黄绿青蓝紫,循环
  1330. List<int> involvedUnitNum = intList(involvedUnit);//读取需要画进去的单位ID
  1331. List<List<double[]>> points = new List<List<double[]>>();//把每个基站连接的不同单位存储在不同的List里,方便上色
  1332. List<double[]> UnitsP = new List<double[]>();
  1333. int[] BaseCatalogue = new int[Status.Count];//基站单位着色索引
  1334. int BaseTemp = 0;
  1335. bool[] isInvolved = new bool[Status.Count];
  1336. for (int i = 0; i < Status.Count; i++)//找出基站并针对基站情况初始化列表
  1337. {
  1338. isInvolved[i] = false;//true为画入的单位
  1339. if ((int)Status[i][3] == 0)//是基站
  1340. {
  1341. BaseCatalogue[i] = BaseTemp;//加入基站单位着色索引,表示该单位为目录中第 BaseTemp+1个基站
  1342. BaseTemp++;
  1343. points.Add(new List<double[]>());//为每个基站新建一个列表
  1344. }
  1345. else
  1346. { BaseCatalogue[i] = -1; }
  1347. }
  1348. foreach (int i in involvedUnitNum) { if (i < isInvolved.Length) { isInvolved[i] = true; } }//将需要画入的单位画入开关打开
  1349. foreach (object[] element in Status)
  1350. {
  1351. if (isInvolved[(int)element[0]] == true)//若画入开关打开
  1352. {
  1353. UnitsP.Add((double[])element[1]);//记录该点坐标用于散点绘制
  1354. if ((int)element[3] >= 1)
  1355. {
  1356. int BaseID = (int)element[5];
  1357. int upID = (int)element[8];
  1358. double[] point12 = new double[4];
  1359. point12[0] = ((double[])element[1])[0];
  1360. point12[1] = ((double[])element[1])[1];
  1361. double[] pointUp = (double[])Status[upID][1];
  1362. point12[2] = pointUp[0];
  1363. point12[3] = pointUp[1];
  1364. points[BaseCatalogue[BaseID]].Add(point12);
  1365. colorP.Add(color[BaseCatalogue[BaseID] % color.Count]);
  1366. }
  1367. else if ((int)element[3] == 0)
  1368. {
  1369. colorP.Add(Color.Magenta);
  1370. }
  1371. else
  1372. { colorP.Add(Color.Black); }
  1373. }
  1374. }
  1375. Draw(poly, UnitsP, colorP, points, color, PxPerKm, name);
  1376. }
  1377. public static void Drawgrid(List<double[]> poly, List<object[]> Grids, int[] ACC, int PxPerKm, string name, double netscalelon, double netscalelat)
  1378. {
  1379. List<double[]> UnitsP = new List<double[]>();
  1380. foreach (object[] element in Grids)
  1381. {
  1382. UnitsP.Add((double[])element[3]);
  1383. }
  1384. List<Color> color = new List<Color>();
  1385. //color.Add(Color.Black);
  1386. //color.Add(Color.White);
  1387. color.Add(Color.Red);
  1388. color.Add(Color.Orange);
  1389. color.Add(Color.Yellow);
  1390. color.Add(Color.Green);
  1391. color.Add(Color.Cyan);
  1392. color.Add(Color.Blue);
  1393. color.Add(Color.Purple);
  1394. // 创建一个位图
  1395. double[,] MM1 = MaxMinPoly(poly);
  1396. double W = MM1[0, 0];//经度最小(西界)
  1397. double E = MM1[0, 1];//经度最大(东界)
  1398. double S = MM1[1, 0]; //纬度最小(南界)
  1399. double N = MM1[1, 1];//纬度最大(北界);
  1400. double kmPerlat = 111.1;
  1401. double kmPerlon = kmPerlat * Math.Cos((Math.PI / 180) * ((N + S) / 2));
  1402. //Console.WriteLine(E + "+" + W);
  1403. static int LonToPx(double lon, double W, double kmPerlon, int PxPerKm)
  1404. {
  1405. double LonKm = (lon - W) * kmPerlon;
  1406. int LonPx = (int)(LonKm * PxPerKm);
  1407. return LonPx;
  1408. }
  1409. static int LatToPx(double lat, double N, double kmPerlat, int PxPerKm)//从北向南!!
  1410. {
  1411. double LatKm = (N - lat) * kmPerlat;
  1412. int LatPx = (int)(LatKm * PxPerKm);
  1413. return LatPx;
  1414. }
  1415. int EW = LonToPx(E, W, kmPerlon, PxPerKm);
  1416. int NS = LatToPx(S, N, kmPerlat, PxPerKm);
  1417. int RGEW = LonToPx(W + netscalelon, W, kmPerlon, PxPerKm);
  1418. int RGNS = LatToPx(N - netscalelat, N, kmPerlat, PxPerKm);
  1419. //Console.WriteLine(EW + "EW|NS" + NS);
  1420. //Console.WriteLine(RGEW + "RGEW|RGNS" + RGNS);
  1421. using Bitmap bitmap = new Bitmap(EW, NS);//位图大小东西南北界
  1422. using (Graphics g = Graphics.FromImage(bitmap))
  1423. {
  1424. g.Clear(Color.White); // 使用Clear方法填充背景色
  1425. }
  1426. using Graphics graphics = Graphics.FromImage(bitmap);
  1427. for (int i = 0; i < ACC.Length; i++)
  1428. {
  1429. int penWidth = math.max(EW, NS) / 500;
  1430. Color colorThis = Color.White;
  1431. if (ACC[i] >= 0)
  1432. {
  1433. colorThis = color[ACC[i] % (color.Count)];
  1434. }
  1435. using Pen Pen = new Pen(Color.Black, penWidth);
  1436. //Rectangle rg = new Rectangle(0, 0, math.max(EW, NS) / 300, math.max(EW, NS) / 300);
  1437. //float RGsize = math.max(EW, NS) / 300;
  1438. 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);
  1439. using Brush BrushT = new SolidBrush(colorThis);
  1440. 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);
  1441. }
  1442. for (int i = 1; i < poly.Count; i++)
  1443. {
  1444. int penWidth = math.max(EW, NS) / 250;
  1445. using Pen Pen = new Pen(Color.Black, penWidth);
  1446. Point Point1 = new Point(LonToPx(poly[i - 1][0], W, kmPerlon, PxPerKm), LatToPx(poly[i - 1][1], N, kmPerlat, PxPerKm));
  1447. Point Point2 = new Point(LonToPx(poly[i][0], W, kmPerlon, PxPerKm), LatToPx(poly[i][1], N, kmPerlat, PxPerKm));
  1448. graphics.DrawLine(Pen, Point1, Point2);
  1449. }
  1450. bitmap.Save(name + ".jpeg");
  1451. Console.WriteLine(ACC.Length + "个网格已画制并保存到" + name + ".jpeg文件中||" + EW + "EW|NS" + NS);
  1452. }
  1453. public static List<double[]> CirclePoint(double[] Center, double r, int pointnumber, double startPoint, double H,bool isClockWise)
  1454. //经纬度,半径(km),点数量,起始点(角度,正北为0,顺时针),海拔高度
  1455. {
  1456. List<double[]> CirclePoint = new List<double[]>();
  1457. double kmPerlat = 111.1;
  1458. double kmPerlon = kmPerlat * Math.Cos((Math.PI / 180) * Center[1]);
  1459. double Rlat = r / kmPerlat;
  1460. double Rlon = r / kmPerlon;
  1461. double DevideAngleRad = 2 * Math.PI / pointnumber;
  1462. double startPointRad = startPoint * (Math.PI / 180);
  1463. int k = 1;
  1464. if(isClockWise==false)
  1465. { k = -1; }
  1466. for (int i = 0; i < pointnumber; i++)
  1467. {
  1468. double AngleRad = (startPointRad + k*i * DevideAngleRad) % (2 * Math.PI);
  1469. double pointLon = Center[0] + Math.Sin(AngleRad) * Rlon;
  1470. double pointLat = Center[1] + Math.Cos(AngleRad) * Rlat;
  1471. double[] point = { pointLon, pointLat, H };
  1472. CirclePoint.Add(point);
  1473. }
  1474. return CirclePoint;
  1475. }
  1476. public static void PostProcessTotal(double ResultStartTime,double ResultEndTime, TXResult TXR, List<object[]>Unit, List<object[]> GridResult, List<object[]> NetResult,int FirstOne,double Timestep,string CalculateName)
  1477. //结果统计开始时间、结束时间
  1478. {
  1479. List<int> netBaseList = (List<int>)NetResult[0][1];
  1480. int[] maxSingle = new int[netBaseList.Count];
  1481. if (NetResult.Count > 0)
  1482. {
  1483. //List<int> netBaseList = (List<int>)NetResult[0][1];
  1484. int maxTotal = 0;
  1485. double TimeConnected = 0;
  1486. for(int k = 0;k< netBaseList.Count;k++)
  1487. {
  1488. maxSingle[k] = 0;
  1489. }
  1490. double[] FulRatio = new double[NetResult.Count];
  1491. for (int i = 0; i < NetResult.Count; i++)//读取每时步结果
  1492. {
  1493. List<int> ConnectedSingle = (List<int>)NetResult[i][2];
  1494. if (ConnectedSingle[FirstOne] > 0)
  1495. {
  1496. TXR.FirstOneArriveTime = (double)NetResult[i][0];//记录最早连接的时间
  1497. break;
  1498. }
  1499. }
  1500. int iStart = (int)((ResultStartTime+0.5*Timestep) / Timestep);
  1501. int iEnd = (int)((ResultEndTime+0.5 * Timestep) / Timestep);
  1502. for (int i = 0; i < NetResult.Count; i++)//读取每时步结果
  1503. {
  1504. FulRatio[i] = (double)NetResult[i][5];
  1505. List<int> ConnectedSingle = (List<int>)NetResult[i][2];
  1506. //List < double>BaseFull= (List<double>)NetResult[i][4];
  1507. for (int j=0;j< ConnectedSingle.Count;j++)
  1508. {
  1509. if (ConnectedSingle[j]> maxSingle[j]) { maxSingle[j] = ConnectedSingle[j]; }
  1510. }
  1511. if(maxTotal < (int)NetResult[i][3])
  1512. { maxTotal = (int)NetResult[i][3]; }
  1513. if (i>=iStart && i<=iEnd &&(int)NetResult[i][3]>0)
  1514. {
  1515. if(NetResult.Count >1 && i==iStart)
  1516. {
  1517. TimeConnected += (iStart*Timestep-ResultStartTime)+0.5 * Timestep;
  1518. }
  1519. else if(NetResult.Count > 1 && i == iEnd)
  1520. {
  1521. TimeConnected +=(ResultEndTime-iEnd*Timestep) + 0.5 * Timestep;
  1522. }
  1523. else
  1524. {
  1525. { TimeConnected += Timestep; }
  1526. }
  1527. }
  1528. }
  1529. int maxmaxSingle = maxSingle.Max();
  1530. double FulRatioAve = FulRatio.Average();
  1531. TXR.SingleMaxConnect = maxmaxSingle;
  1532. TXR.MaxTotalConnect = maxTotal;
  1533. TXR.ConnectTimeRatio = TimeConnected/(ResultEndTime-ResultStartTime);
  1534. TXR.UnitFulfilledRatio = FulRatioAve;
  1535. }
  1536. if (GridResult.Count > 0)
  1537. {
  1538. double FirstMaxCover = 0;
  1539. for (int i = 0; i < GridResult.Count; i++)//读取每时步结果
  1540. {
  1541. if ((double)GridResult[i][3] >= 1)
  1542. {
  1543. TXR.FullCoverTime = (double)GridResult[i][0];//记录最早100%连接的时间
  1544. break;
  1545. }
  1546. }
  1547. double[] TotalCover = new double[GridResult.Count];
  1548. for (int i = 0; i < GridResult.Count; i++)//读取每时步结果
  1549. {
  1550. double FirstCover = ((double[])GridResult[i][2])[FirstOne];
  1551. if (FirstMaxCover < FirstCover)
  1552. { FirstMaxCover =FirstCover; }
  1553. TotalCover[i] = (double)GridResult[i][4];
  1554. }
  1555. double AveTotalCover = TotalCover.Average();
  1556. TXR.FirstOneMaxCover = FirstMaxCover;
  1557. TXR.AverageTotalCover = AveTotalCover;
  1558. }
  1559. Console.WriteLine("准备时间:" + TXR.FirstOneReadyTime+"s||到达任务区域时间:"+TXR.FirstOneArriveTime+ "s||首架次覆盖范围最大值:"+ TXR.FirstOneMaxCover
  1560. +"km²||最大单架接入用户数:"+ TXR.SingleMaxConnect+"个||第一次完全覆盖时间:"+ TXR.FullCoverTime+"s||平均总覆盖面积:"
  1561. + TXR.AverageTotalCover + "km²||同时连接最大用户数量:"+ TXR.MaxTotalConnect+ "个||保持至少一个单位有通信情况下的时间比例:"+
  1562. (TXR.ConnectTimeRatio*100)+ "%||能满足流量需求的单位比例:"+ (TXR.UnitFulfilledRatio*100)+"%");
  1563. string csvFilePath = CalculateName + "/应急通信计算报告.csv";
  1564. using (var writer = new StreamWriter(csvFilePath, Encoding.UTF8, new FileStreamOptions{Access = FileAccess.Write,
  1565. Mode = FileMode.Create,
  1566. Share = FileShare.None,
  1567. Options = FileOptions.None}))
  1568. {
  1569. writer.WriteLine(String.Format("{0} ,{1}", "指标名", "数值"));
  1570. writer.WriteLine(String.Format("{0} ,{1}", "首架次出动准备时间(秒)", TXR.FirstOneReadyTime));
  1571. writer.WriteLine(String.Format("{0} ,{1}", "首架次飞抵时间(秒)", TXR.FirstOneArriveTime));
  1572. writer.WriteLine(String.Format("{0} ,{1}", "首架次最大单次覆盖范围(平方千米)", TXR.FirstOneMaxCover));
  1573. writer.WriteLine(String.Format("{0} ,{1}", "任务区域全覆盖实现时间(秒)", TXR.FullCoverTime));
  1574. writer.WriteLine(String.Format("{0} ,{1}", "平均覆盖地面总面积(平方千米)", TXR.AverageTotalCover));
  1575. writer.WriteLine(String.Format("{0} ,{1}", "最大单次总接入数量", TXR.MaxTotalConnect));
  1576. writer.WriteLine(String.Format("{0} ,{1}", "给定时间内持续保障率(%)", TXR.ConnectTimeRatio * 100));
  1577. writer.WriteLine(String.Format("{0} ,{1}", "满足通信速率要求的用户比例(%)", TXR.UnitFulfilledRatio * 100));
  1578. writer.WriteLine(String.Format("{0} ,{1}", "通信稳定性", TXR.Stability));
  1579. writer.WriteLine(String.Format("{0} ,{1}", "鲁棒性", TXR.Robustness));
  1580. writer.WriteLine(String.Format("{0} ,{1}", "安全性", TXR.Security));
  1581. writer.WriteLine(String.Format("{0}", " "));
  1582. writer.WriteLine(String.Format("{0} ,{1}", "基站名称", "单基站最大接入数量"));
  1583. for (int i = 0; i < netBaseList.Count; i++)
  1584. { writer.WriteLine(String.Format("{0} ,{1}", (string)(Unit[netBaseList[i]][1]), maxSingle[i])); }
  1585. }
  1586. }
  1587. public static List<double[]> Hover(double[]Location,double Direction,double H,bool isRealHeight,double EnterDistance)
  1588. {
  1589. double kmPerlat = 111.1;
  1590. double kmPerlon = kmPerlat * Math.Cos((Math.PI / 180) * Location[1]);
  1591. double Dlat = EnterDistance / kmPerlat;
  1592. double Dlon = EnterDistance / kmPerlon;
  1593. double DirectionRad = Direction * (Math.PI / 180);
  1594. double EnterLon = Location[0] - Math.Sin(DirectionRad) * Dlon;
  1595. double EnterLat = Location[1] - Math.Cos(DirectionRad) * Dlat;
  1596. double H1 = H;
  1597. if (isRealHeight) { H1 += HeightLL(Location[0], Location[1]); }
  1598. double[] Point1 = { Location[0], Location[1], H1 };
  1599. double[]Point0= { EnterLon, EnterLat, H1 };
  1600. List<double[]> Hover = new List<double[]>();
  1601. Hover.Add(Point0);
  1602. Hover.Add(Point1);
  1603. return Hover;
  1604. }
  1605. }
  1606. }