Rectangular_Area_Search_Function.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. using OpenCvSharp;
  2. namespace SimulationCommon;
  3. public class Rectangular_Area_Search_Function
  4. {
  5. //墨卡托投影
  6. public static double MokatuoLon(double lat)
  7. {
  8. double R = 6378.137;
  9. double y = R * Math.Log(Math.Tan((lat + 90) * Math.PI / 360));
  10. return y;
  11. }
  12. public static double MokatuoLat(double lon)
  13. {
  14. double R = 6378.137;
  15. double x = (lon * Math.PI * R) / 180;
  16. return x;
  17. }
  18. //反墨卡托投影
  19. public static double RMokatuoLat(double y)
  20. {
  21. double R = 6378.137;
  22. double lat = Math.Atan(Math.Exp(y / R)) * 360 / Math.PI - 90;
  23. return lat;
  24. }
  25. public static double RMokatuoLon(double x)
  26. {
  27. double R = 6378.137;
  28. double lon = x * 180 / (R * Math.PI);
  29. return lon;
  30. }
  31. private static double[] GetLinearEquation(Point2f point1, Point2f point2)
  32. {
  33. double sign = 1;
  34. double parameter_a = point2.Y - point1.Y;
  35. if (parameter_a < 0)
  36. {
  37. sign = -1;
  38. parameter_a = sign * parameter_a;
  39. }
  40. double parameter_b = sign * (point1.X - point2.X);
  41. double parameter_c = sign * (point1.Y * point2.X - point1.X * point2.Y);
  42. return new double[] { parameter_a, parameter_b, parameter_c };
  43. }
  44. private static double[] GetParallelLine(Point2f point, double[] line)
  45. {
  46. double parameter_a = line[0];
  47. double parameter_b = line[1];
  48. double parameter_c = -point.X * parameter_a - point.Y * parameter_b;
  49. return new double[] { parameter_a, parameter_b, parameter_c };
  50. }
  51. private static double[] GetpPerpendicular(Point2f point, double[] line)
  52. {
  53. double parameter_a = line[1];
  54. double parameter_b = -line[0];
  55. double parameter_c = -point.Y * parameter_b - point.X * parameter_a;
  56. return new double[] { parameter_a, parameter_b, parameter_c };
  57. }
  58. private static double[] GetCrossPoint(double[] line1, double[] line2)
  59. {
  60. double cross_y = (line1[2] * line2[0] - line2[2] * line1[0]) / (line1[0] * line2[1] - line2[0] * line1[1]);
  61. double cross_x = (line2[2] * line1[1] - line1[2] * line2[1]) / (line1[0] * line2[1] - line2[0] * line1[1]);
  62. return new double[] { cross_x, cross_y };
  63. }
  64. private static double GetDistance(Point2f point, double[] line)
  65. {
  66. return Math.Abs(line[0] * point.X + line[1] * point.Y + line[2]) /
  67. Math.Sqrt(Math.Pow(line[0], 2) + Math.Pow(line[1], 2));
  68. }
  69. private static int CheckDirection(Point2f point, double[] line)
  70. {
  71. double result = line[0] * point.X + line[1] * point.Y + line[2];
  72. if (result < 0) return -1;
  73. if (result > 0) return 1;
  74. return 0;
  75. }
  76. private static double GetRectangularArea(double[] Point0, double[] Point1, double[] Point2, double[] Point3)
  77. {
  78. double width = Math.Sqrt(Math.Pow(Point0[0] - Point1[0], 2) + Math.Pow(Point0[1] - Point1[1], 2));
  79. double height = Math.Sqrt(Math.Pow(Point1[0] - Point2[0], 2) + Math.Pow(Point1[1] - Point2[1], 2));
  80. return width * height;
  81. }
  82. public static Point2f[] GetConvexHull(List<Point2f> pointList)
  83. {
  84. Point2f[] hull = Cv2.ConvexHull(pointList);
  85. return hull;
  86. }
  87. public static List<double[]> MinEnclosingRectangle(Point2f[] hull)
  88. {
  89. double min_rectangular_area = double.PositiveInfinity;
  90. List<double[]> Point_muster = new List<double[]>{};
  91. for (int num = 0; num < hull.Length - 1; num++)
  92. {
  93. double[] Base_line = GetLinearEquation(hull[num], hull[num + 1]);
  94. double max_Ditance = 0;
  95. Point2f Point = hull[num + 1];
  96. foreach (Point2f i_point in hull)
  97. {
  98. if ((i_point.X == hull[num].X && i_point.Y == hull[num].Y) ||
  99. (i_point.X == hull[num + 1].X && i_point.Y == hull[num + 1].Y))
  100. {
  101. continue;
  102. }
  103. double distance = GetDistance(i_point, Base_line);
  104. if (distance > max_Ditance)
  105. {
  106. max_Ditance = distance;
  107. Point = i_point;
  108. }
  109. }
  110. double[] line_Parallel_Base = GetParallelLine(Point, Base_line);
  111. double[] line_Perpendicular_Base_right = null;
  112. double[] line_Perpendicular_Base_left = null;
  113. foreach (Point2f j_point in hull)
  114. {
  115. double[] line_Preparatory = GetpPerpendicular(j_point, Base_line);
  116. int point_right = 0;
  117. int point_left = 0;
  118. foreach (Point2f k_point in hull)
  119. {
  120. if (k_point.X == j_point.X && k_point.Y == j_point.Y)
  121. {
  122. continue;
  123. }
  124. if (CheckDirection(k_point, line_Preparatory) < 0)
  125. {
  126. point_left++;
  127. }
  128. else
  129. {
  130. point_right++;
  131. }
  132. }
  133. if (point_right == hull.Length - 1)
  134. {
  135. line_Perpendicular_Base_right = line_Preparatory;
  136. }
  137. if (point_left == hull.Length - 1)
  138. {
  139. line_Perpendicular_Base_left = line_Preparatory;
  140. }
  141. }
  142. double[] Point0 = GetCrossPoint(Base_line, line_Perpendicular_Base_left);
  143. double[] Point1 = GetCrossPoint(Base_line, line_Perpendicular_Base_right);
  144. double[] Point2 = GetCrossPoint(line_Parallel_Base, line_Perpendicular_Base_right);
  145. double[] Point3 = GetCrossPoint(line_Parallel_Base, line_Perpendicular_Base_left);
  146. double rectangular_area = GetRectangularArea(Point0, Point1, Point2, Point3);
  147. if (rectangular_area < min_rectangular_area)
  148. {
  149. min_rectangular_area = rectangular_area;
  150. Point_muster = new List<double[]> {
  151. Point0,
  152. Point1,
  153. Point2,
  154. Point3
  155. };
  156. }
  157. }
  158. return Point_muster;
  159. }
  160. }