FlightPlanner.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. namespace SimulationCommon;
  2. public class FlightPlanner
  3. {
  4. private const double EarthRadius = 6371000; // 地球半径,单位:米
  5. private const double RadiansPerDegree = Math.PI / 180.0; // 角度转弧度的转换常数
  6. private static Dictionary<(int, int), List<Point3D>> gridCells; // 网格单元
  7. private static double cellSize; // 网格单元大小
  8. // 规划飞行路径
  9. public static List<Point3D> PlanFlightPath(Point3D start, Point3D end, List<Point3D> areaPoints)
  10. {
  11. InitializeGrid(areaPoints); // 初始化网格
  12. var path = new List<Point3D> { start }; // 初始化路径,包含起点
  13. var current = FindClosestPoint(start); // 找到起点最近的点
  14. var target = FindClosestPoint(end); // 找到终点最近的点
  15. // 循环查找路径直到到达目标点
  16. while (current != target)
  17. {
  18. path.Add(current); // 添加当前点到路径
  19. current = FindNextPoint(current, target); // 找到下一个点
  20. }
  21. path.Add(target); // 添加目标点
  22. path.Add(end); // 添加终点
  23. // 对路径中除第一个和最后一个点的高度加 300
  24. for (int j = 1; j < path.Count - 1; j++)
  25. {
  26. path[j].Z += 300;
  27. }
  28. return path; // 返回完整路径
  29. }
  30. // 初始化网格
  31. private static void InitializeGrid(List<Point3D> points)
  32. {
  33. cellSize = 0.01; // 根据数据密度调整此值
  34. gridCells = new Dictionary<(int, int), List<Point3D>>(); // 初始化网格字典
  35. foreach (var point in points)
  36. {
  37. var cellX = (int)(point.Lon / cellSize); // 计算网格 X 坐标
  38. var cellY = (int)(point.Lat / cellSize); // 计算网格 Y 坐标
  39. var key = (cellX, cellY);
  40. if (!gridCells.ContainsKey(key))
  41. {
  42. gridCells[key] = new List<Point3D>(); // 如果网格不存在,初始化列表
  43. }
  44. gridCells[key].Add(point); // 将点添加到对应的网格单元
  45. }
  46. }
  47. // 找到离目标点最近的点
  48. private static Point3D FindClosestPoint(Point3D target)
  49. {
  50. var cellX = (int)(target.Lon / cellSize); // 计算目标点的网格 X 坐标
  51. var cellY = (int)(target.Lat / cellSize); // 计算目标点的网格 Y 坐标
  52. var nearbyPoints = new List<Point3D>(); // 存储附近点
  53. for (int i = -1; i <= 1; i++)
  54. {
  55. for (int j = -1; j <= 1; j++)
  56. {
  57. var key = (cellX + i, cellY + j);
  58. if (gridCells.TryGetValue(key, out var cellPoints))
  59. {
  60. nearbyPoints.AddRange(cellPoints); // 添加附近网格的点
  61. }
  62. }
  63. }
  64. // 根据距离排序并返回最近的点
  65. return nearbyPoints.OrderBy(p => DistanceSquared(p, target)).First();
  66. }
  67. // 找到下一个最佳点
  68. private static Point3D FindNextPoint(Point3D current, Point3D target)
  69. {
  70. var cellX = (int)(current.Lon / cellSize); // 当前点的网格 X 坐标
  71. var cellY = (int)(current.Lat / cellSize); // 当前点的网格 Y 坐标
  72. var bestPoint = current; // 初始化最佳点为当前点
  73. var bestDistance = double.MaxValue; // 初始化最佳距离为最大值
  74. // 遍历附近的网格点
  75. for (int i = -1; i <= 1; i++)
  76. {
  77. for (int j = -1; j <= 1; j++)
  78. {
  79. var key = (cellX + i, cellY + j);
  80. if (gridCells.TryGetValue(key, out var cellPoints))
  81. {
  82. foreach (var point in cellPoints)
  83. {
  84. if (point != current) // 不考虑当前点
  85. {
  86. var distanceToCurrent = DistanceSquared(point, current); // 当前点到候选点的距离
  87. var distanceToTarget = DistanceSquared(point, target); // 候选点到目标点的距离
  88. var totalDistance = distanceToCurrent + distanceToTarget; // 总距离
  89. if (totalDistance < bestDistance) // 如果找到更短的距离
  90. {
  91. bestDistance = totalDistance; // 更新最佳距离
  92. bestPoint = point; // 更新最佳点
  93. }
  94. }
  95. }
  96. }
  97. }
  98. }
  99. return bestPoint; // 返回最佳点
  100. }
  101. // 计算两个点之间的平方距离
  102. private static double DistanceSquared(Point3D a, Point3D b)
  103. {
  104. var dLon = (b.Lon - a.Lon) * RadiansPerDegree; // 经度差
  105. var dLat = (b.Lat - a.Lat) * RadiansPerDegree; // 纬度差
  106. var lat1 = a.Lat * RadiansPerDegree; // 点 A 的纬度弧度
  107. var lat2 = b.Lat * RadiansPerDegree; // 点 B 的纬度弧度
  108. var x = dLon * Math.Cos((lat1 + lat2) / 2); // X 轴距离
  109. var y = dLat; // Y 轴距离
  110. return EarthRadius * EarthRadius * (x * x + y * y); // 返回平方距离
  111. }
  112. // 计算路径总距离
  113. public static double CalculatePathDistance(List<Point3D> path)
  114. {
  115. double totalDistance = 0; // 初始化总距离
  116. for (int i = 0; i < path.Count - 1; i++)
  117. {
  118. totalDistance += Math.Sqrt(DistanceSquared(path[i], path[i + 1])); // 累加每段距离
  119. }
  120. return totalDistance; // 返回总距离
  121. }
  122. }