using OpenCvSharp; namespace SimulationCommon; public class Rectangular_Area_Search_Function { //墨卡托投影 public static double MokatuoLon(double lat) { double R = 6378.137; double y = R * Math.Log(Math.Tan((lat + 90) * Math.PI / 360)); return y; } public static double MokatuoLat(double lon) { double R = 6378.137; double x = (lon * Math.PI * R) / 180; return x; } //反墨卡托投影 public static double RMokatuoLat(double y) { double R = 6378.137; double lat = Math.Atan(Math.Exp(y / R)) * 360 / Math.PI - 90; return lat; } public static double RMokatuoLon(double x) { double R = 6378.137; double lon = x * 180 / (R * Math.PI); return lon; } private static double[] GetLinearEquation(Point2f point1, Point2f point2) { double sign = 1; double parameter_a = point2.Y - point1.Y; if (parameter_a < 0) { sign = -1; parameter_a = sign * parameter_a; } double parameter_b = sign * (point1.X - point2.X); double parameter_c = sign * (point1.Y * point2.X - point1.X * point2.Y); return new double[] { parameter_a, parameter_b, parameter_c }; } private static double[] GetParallelLine(Point2f point, double[] line) { double parameter_a = line[0]; double parameter_b = line[1]; double parameter_c = -point.X * parameter_a - point.Y * parameter_b; return new double[] { parameter_a, parameter_b, parameter_c }; } private static double[] GetpPerpendicular(Point2f point, double[] line) { double parameter_a = line[1]; double parameter_b = -line[0]; double parameter_c = -point.Y * parameter_b - point.X * parameter_a; return new double[] { parameter_a, parameter_b, parameter_c }; } private static double[] GetCrossPoint(double[] line1, double[] line2) { double cross_y = (line1[2] * line2[0] - line2[2] * line1[0]) / (line1[0] * line2[1] - line2[0] * line1[1]); double cross_x = (line2[2] * line1[1] - line1[2] * line2[1]) / (line1[0] * line2[1] - line2[0] * line1[1]); return new double[] { cross_x, cross_y }; } private static double GetDistance(Point2f point, double[] line) { return Math.Abs(line[0] * point.X + line[1] * point.Y + line[2]) / Math.Sqrt(Math.Pow(line[0], 2) + Math.Pow(line[1], 2)); } private static int CheckDirection(Point2f point, double[] line) { double result = line[0] * point.X + line[1] * point.Y + line[2]; if (result < 0) return -1; if (result > 0) return 1; return 0; } private static double GetRectangularArea(double[] Point0, double[] Point1, double[] Point2, double[] Point3) { double width = Math.Sqrt(Math.Pow(Point0[0] - Point1[0], 2) + Math.Pow(Point0[1] - Point1[1], 2)); double height = Math.Sqrt(Math.Pow(Point1[0] - Point2[0], 2) + Math.Pow(Point1[1] - Point2[1], 2)); return width * height; } public static Point2f[] GetConvexHull(List pointList) { Point2f[] hull = Cv2.ConvexHull(pointList); return hull; } public static List MinEnclosingRectangle(Point2f[] hull) { double min_rectangular_area = double.PositiveInfinity; List Point_muster = new List { }; for (int num = 0; num < hull.Length - 1; num++) { double[] Base_line = GetLinearEquation(hull[num], hull[num + 1]); double max_Ditance = 0; Point2f Point = hull[num + 1]; Point2f Point_left = hull[num + 1]; Point2f Point_right = hull[num + 1]; foreach (Point2f i_point in hull) { if ((i_point.X == hull[num].X && i_point.Y == hull[num].Y) || (i_point.X == hull[num + 1].X && i_point.Y == hull[num + 1].Y)) { continue; } double distance = GetDistance(i_point, Base_line); if (distance > max_Ditance) { max_Ditance = distance; Point = i_point; } } double[] line_Parallel_Base = GetParallelLine(Point, Base_line); double[] line_Perpendicular_Base_right = null; double[] line_Perpendicular_Base_left = null; foreach (Point2f j_point in hull) { double[] line_Preparatory = GetpPerpendicular(j_point, Base_line); int point_right = 0; int point_left = 0; foreach (Point2f k_point in hull) { if (k_point.X == j_point.X && k_point.Y == j_point.Y) { continue; } //添加点在直线上的条件 if (CheckDirection(k_point, line_Preparatory) <= 0) { point_left++; } else if (CheckDirection(k_point, line_Preparatory) >= 0) { point_right++; } } if (point_right == hull.Length - 1) { line_Perpendicular_Base_right = line_Preparatory; } if (point_left == hull.Length - 1) { line_Perpendicular_Base_left = line_Preparatory; } } if (line_Perpendicular_Base_left == null || line_Perpendicular_Base_right == null) { double max_Ditance_left = 0; double distance_left = 0; double max_Distance_right = 0; double distance_right = 0; double[] line_inite_Preparatory = GetpPerpendicular(hull[num], Base_line); foreach (Point2f m_point in hull) { if (CheckDirection(m_point, line_inite_Preparatory) <= 0) { distance_left = GetDistance(m_point, line_inite_Preparatory); if (distance_left >= max_Ditance_left) { max_Ditance_left = distance_left; Point_left = m_point; line_Perpendicular_Base_left = GetpPerpendicular(Point_left, Base_line); } } if (CheckDirection(m_point, line_inite_Preparatory) >= 0) { distance_right = GetDistance(m_point, line_inite_Preparatory); if (distance_right >= max_Distance_right) { max_Distance_right = distance_right; Point_right = m_point; line_Perpendicular_Base_right = GetpPerpendicular(Point_right, Base_line); } } } } double[] Point0 = GetCrossPoint(Base_line, line_Perpendicular_Base_left); double[] Point1 = GetCrossPoint(Base_line, line_Perpendicular_Base_right); double[] Point2 = GetCrossPoint(line_Parallel_Base, line_Perpendicular_Base_right); double[] Point3 = GetCrossPoint(line_Parallel_Base, line_Perpendicular_Base_left); //List temp0 = new List(); //List temp1 = new List(); //List temp2 = new List(); //List temp3 = new List(); //double lat0 = Point0[0]; //double lon0 = Point0[1]; //double lat1 = Point1[0]; //double lon1 = Point1[1]; //double lat2 = Point2[0]; //double lon2 = Point2[1]; //double lat3 = Point3[0]; //double lon3 = Point3[1]; //temp0.Add(Math.Max(Math.Max(Math.Max(lat0, lat1), lat2), lat3)); //temp0.Add(Math.Min(Math.Min(Math.Min(lon0, lon1), lon2), lon3)); //temp1.Add(Math.Max(Math.Max(Math.Max(lat0, lat1), lat2), lat3)); //temp1.Add(Math.Max(Math.Max(Math.Max(lon0, lon1), lon2), lon3)); //temp2.Add(Math.Min(Math.Min(Math.Min(lat0, lat1), lat2), lat3)); //temp2.Add(Math.Max(Math.Max(Math.Max(lon0, lon1), lon2), lon3)); //temp3.Add(Math.Min(Math.Min(Math.Min(lat0, lat1), lat2), lat3)); //temp3.Add(Math.Min(Math.Min(Math.Min(lon0, lon1), lon2), lon3)); //Point0 = temp0.ToArray(); //Point1 = temp1.ToArray(); //Point2 = temp2.ToArray(); //Point3 = temp3.ToArray(); double rectangular_area = GetRectangularArea(Point0, Point1, Point2, Point3); if (rectangular_area < min_rectangular_area) { min_rectangular_area = rectangular_area; Point_muster = new List { Point0, Point1, Point2, Point3 }; } //double lat = Rectangular_Area_Search_Function.RMokatuoLat(Point0[0]); //double lon = Rectangular_Area_Search_Function.RMokatuoLon(Point0[1]); //Console.WriteLine("Point0:" + lat + "-" + lon); //double lat1 = Rectangular_Area_Search_Function.RMokatuoLat(Point1[0]); //double lon1 = Rectangular_Area_Search_Function.RMokatuoLon(Point1[1]); //Console.WriteLine("Point1:" + lat1 + "-" + lon1); //double lat2 = Rectangular_Area_Search_Function.RMokatuoLat(Point2[0]); //double lon2 = Rectangular_Area_Search_Function.RMokatuoLon(Point2[1]); //Console.WriteLine("Point2:" + lat2 + "-" + lon2); //double lat3 = Rectangular_Area_Search_Function.RMokatuoLat(Point3[0]); //double lon3 = Rectangular_Area_Search_Function.RMokatuoLon(Point3[1]); //Console.WriteLine("Point3:" + lat3 + "-" + lon3); } //foreach (var item in Point_muster) //{ // Console.WriteLine("Point_muster:" + item[0] + "-" + item[1]); //} min_area = GetRectangularArea(Point_muster[0], Point_muster[1], Point_muster[2], Point_muster[3]); //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)); //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)); //Console.WriteLine("width:" + width + "-" + "height:" + height); return Point_muster; } public static double min_area; }