Rectangular_Area_Search_Function.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  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. Point2f Point_left = hull[num + 1];
  97. Point2f Point_right = hull[num + 1];
  98. foreach (Point2f i_point in hull)
  99. {
  100. if ((i_point.X == hull[num].X && i_point.Y == hull[num].Y) ||
  101. (i_point.X == hull[num + 1].X && i_point.Y == hull[num + 1].Y))
  102. {
  103. continue;
  104. }
  105. double distance = GetDistance(i_point, Base_line);
  106. if (distance > max_Ditance)
  107. {
  108. max_Ditance = distance;
  109. Point = i_point;
  110. }
  111. }
  112. double[] line_Parallel_Base = GetParallelLine(Point, Base_line);
  113. double[] line_Perpendicular_Base_right = null;
  114. double[] line_Perpendicular_Base_left = null;
  115. foreach (Point2f j_point in hull)
  116. {
  117. double[] line_Preparatory = GetpPerpendicular(j_point, Base_line);
  118. int point_right = 0;
  119. int point_left = 0;
  120. foreach (Point2f k_point in hull)
  121. {
  122. if (k_point.X == j_point.X && k_point.Y == j_point.Y)
  123. {
  124. continue;
  125. }
  126. //添加点在直线上的条件
  127. if (CheckDirection(k_point, line_Preparatory) <= 0)
  128. {
  129. point_left++;
  130. }
  131. else if (CheckDirection(k_point, line_Preparatory) >= 0)
  132. {
  133. point_right++;
  134. }
  135. }
  136. if (point_right == hull.Length - 1)
  137. {
  138. line_Perpendicular_Base_right = line_Preparatory;
  139. }
  140. if (point_left == hull.Length - 1)
  141. {
  142. line_Perpendicular_Base_left = line_Preparatory;
  143. }
  144. }
  145. if (line_Perpendicular_Base_left == null || line_Perpendicular_Base_right == null)
  146. {
  147. double max_Ditance_left = 0;
  148. double distance_left = 0;
  149. double max_Distance_right = 0;
  150. double distance_right = 0;
  151. double[] line_inite_Preparatory = GetpPerpendicular(hull[num], Base_line);
  152. foreach (Point2f m_point in hull)
  153. {
  154. if (CheckDirection(m_point, line_inite_Preparatory) <= 0)
  155. {
  156. distance_left = GetDistance(m_point, line_inite_Preparatory);
  157. if (distance_left >= max_Ditance_left)
  158. {
  159. max_Ditance_left = distance_left;
  160. Point_left = m_point;
  161. line_Perpendicular_Base_left = GetpPerpendicular(Point_left, Base_line);
  162. }
  163. }
  164. if (CheckDirection(m_point, line_inite_Preparatory) >= 0)
  165. {
  166. distance_right = GetDistance(m_point, line_inite_Preparatory);
  167. if (distance_right >= max_Distance_right)
  168. {
  169. max_Distance_right = distance_right;
  170. Point_right = m_point;
  171. line_Perpendicular_Base_right = GetpPerpendicular(Point_right, Base_line);
  172. }
  173. }
  174. }
  175. }
  176. double[] Point0 = GetCrossPoint(Base_line, line_Perpendicular_Base_left);
  177. double[] Point1 = GetCrossPoint(Base_line, line_Perpendicular_Base_right);
  178. double[] Point2 = GetCrossPoint(line_Parallel_Base, line_Perpendicular_Base_right);
  179. double[] Point3 = GetCrossPoint(line_Parallel_Base, line_Perpendicular_Base_left);
  180. //List<double> temp0 = new List<double>();
  181. //List<double> temp1 = new List<double>();
  182. //List<double> temp2 = new List<double>();
  183. //List<double> temp3 = new List<double>();
  184. //double lat0 = Point0[0];
  185. //double lon0 = Point0[1];
  186. //double lat1 = Point1[0];
  187. //double lon1 = Point1[1];
  188. //double lat2 = Point2[0];
  189. //double lon2 = Point2[1];
  190. //double lat3 = Point3[0];
  191. //double lon3 = Point3[1];
  192. //temp0.Add(Math.Max(Math.Max(Math.Max(lat0, lat1), lat2), lat3));
  193. //temp0.Add(Math.Min(Math.Min(Math.Min(lon0, lon1), lon2), lon3));
  194. //temp1.Add(Math.Max(Math.Max(Math.Max(lat0, lat1), lat2), lat3));
  195. //temp1.Add(Math.Max(Math.Max(Math.Max(lon0, lon1), lon2), lon3));
  196. //temp2.Add(Math.Min(Math.Min(Math.Min(lat0, lat1), lat2), lat3));
  197. //temp2.Add(Math.Max(Math.Max(Math.Max(lon0, lon1), lon2), lon3));
  198. //temp3.Add(Math.Min(Math.Min(Math.Min(lat0, lat1), lat2), lat3));
  199. //temp3.Add(Math.Min(Math.Min(Math.Min(lon0, lon1), lon2), lon3));
  200. //Point0 = temp0.ToArray();
  201. //Point1 = temp1.ToArray();
  202. //Point2 = temp2.ToArray();
  203. //Point3 = temp3.ToArray();
  204. double rectangular_area = GetRectangularArea(Point0, Point1, Point2, Point3);
  205. if (rectangular_area < min_rectangular_area)
  206. {
  207. min_rectangular_area = rectangular_area;
  208. Point_muster = new List<double[]> {
  209. Point0,
  210. Point1,
  211. Point2,
  212. Point3
  213. };
  214. }
  215. //double lat = Rectangular_Area_Search_Function.RMokatuoLat(Point0[0]);
  216. //double lon = Rectangular_Area_Search_Function.RMokatuoLon(Point0[1]);
  217. //Console.WriteLine("Point0:" + lat + "-" + lon);
  218. //double lat1 = Rectangular_Area_Search_Function.RMokatuoLat(Point1[0]);
  219. //double lon1 = Rectangular_Area_Search_Function.RMokatuoLon(Point1[1]);
  220. //Console.WriteLine("Point1:" + lat1 + "-" + lon1);
  221. //double lat2 = Rectangular_Area_Search_Function.RMokatuoLat(Point2[0]);
  222. //double lon2 = Rectangular_Area_Search_Function.RMokatuoLon(Point2[1]);
  223. //Console.WriteLine("Point2:" + lat2 + "-" + lon2);
  224. //double lat3 = Rectangular_Area_Search_Function.RMokatuoLat(Point3[0]);
  225. //double lon3 = Rectangular_Area_Search_Function.RMokatuoLon(Point3[1]);
  226. //Console.WriteLine("Point3:" + lat3 + "-" + lon3);
  227. }
  228. //foreach (var item in Point_muster)
  229. //{
  230. // Console.WriteLine("Point_muster:" + item[0] + "-" + item[1]);
  231. //}
  232. min_area = GetRectangularArea(Point_muster[0], Point_muster[1], Point_muster[2], Point_muster[3]);
  233. //double width = Math.Sqrt(Math.Pow(Point_muster[0][0] - Point_muster[1][0], 2) + Math.Pow(Point_muster[0][1] - Point_muster[1][1], 2));
  234. //double height = Math.Sqrt(Math.Pow(Point_muster[1][0] - Point_muster[2][0], 2) + Math.Pow(Point_muster[1][1] - Point_muster[2][1], 2));
  235. //Console.WriteLine("width:" + width + "-" + "height:" + height);
  236. return Point_muster;
  237. }
  238. public static double min_area;
  239. }