/// <summary> /// Метод подготовки данных и запуска алгоритма размещения многоугольников. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Barriers_Click(object sender, RoutedEventArgs e) { List<Polygon2d> polygons = new List<Polygon2d>(this.polygons.List); #region Шаг 1. Создаём начальную точку. #region Шаг 1.1. Заполняем координаты полюсов. double[] X = new double[2 * polygons.Count + 1]; for (int i = 0; i < polygons.Count; i++) { X[2 * i] = polygons[i].Pole.X; X[2 * i + 1] = polygons[i].Pole.Y; } #endregion #region Шаг 1.2. Заполняем длину занятой части полосы. X[2 * polygons.Count] = 0; for (int i = 0; i < polygons.Count; i++) { double max_x = double.NegativeInfinity; for (int j = 0; j < polygons[i].Count; j++) if (max_x < polygons[i][j].X) max_x = polygons[i][j].X; if (X[2 * polygons.Count] < polygons[i].Pole.X + max_x) X[2 * polygons.Count] = polygons[i].Pole.X + max_x; } X[2 * polygons.Count] *= 2; #endregion #endregion #region Шаг 2. Создаём функцию цели. double[] F = new double[2 * polygons.Count + 2]; F[2 * polygons.Count] = 1; #endregion #region Шаг 3. Создаём набор ограничений. List<double[]> G = new List<double[]>(); #region Шаг 3.1. Для каждого многоугольника... for (int i = 0; i < polygons.Count; i++) { #region Шаг 3.1.1. Находим минимальное и максимальное значение прямоугольной оболочки для многоугольника. Point min = new Point { X = double.PositiveInfinity, Y = double.PositiveInfinity }; Point max = new Point { X = double.NegativeInfinity, Y = double.NegativeInfinity }; for (int j = 0; j < polygons[i].Count; j++) { if (min.X > polygons[i][j].X) min.X = polygons[i][j].X; if (max.X < polygons[i][j].X) max.X = polygons[i][j].X; if (min.Y > polygons[i][j].Y) min.Y = polygons[i][j].Y; if (max.Y < polygons[i][j].Y) max.Y = polygons[i][j].Y; } #endregion #region Шаг 3.1.2. Создаём набор ограничений по полосе. Проверить!! double[] g; #region Шаг 3.1.2.1. Ограничение по нижней границе. // Y-min.Y>=0 --> -Y+min.Y<=0 g = new double[2 * polygons.Count + 2]; g[2 * i + 1] = -1; g[2 * polygons.Count + 1] = min.Y; G.Add(g); #endregion #region Шаг 3.1.2.2. Ограничение по левой границе. // X-min.X>=0 --> -X+min.X<=0 g = new double[2 * polygons.Count + 2]; g[2 * i] = -1; g[2 * polygons.Count + 1] = min.X; G.Add(g); #endregion #region Шаг 3.1.2.3. Ограничение по верхней границе. // Y+max.Y<=H --> Y+max.Y-H<=0 g = new double[2 * polygons.Count + 2]; g[2 * i + 1] = 1; g[2 * polygons.Count + 1] = max.Y - strip.Height; G.Add(g); #endregion #region Шаг 3.1.2.4. Ограничение по правой границе. // X+max.X<=Z --> X-Z+max.X<=0 g = new double[2 * polygons.Count + 2]; g[2 * i] = 1; g[2 * polygons.Count] = -1; g[2 * polygons.Count + 1] = max.X; G.Add(g); #endregion #endregion } #endregion #region Шаг 3.2. Для каждой пары многоугольников... for (int i = 0; i < polygons.Count - 1; i++) for (int j = i + 1; j < polygons.Count; j++) { #region Шаг 3.2.1. Создаём и находим разделяющую. PlaneDividing pd = new PlaneDividing(new Polygon2d.Iterator(i, polygons[i], 0), new Polygon2d.Iterator(j, polygons[j], 0)); pd.Find(); #endregion #region Шаг 3.2.2. Создаём ограничение. !!Проверить!! Vector2d vector = pd.IteratorPlane.Point(1) - pd.IteratorPlane.Point(0); Vector2d normal = new Vector2d { X = -vector.Y, Y = vector.X }; double length = Math.Sqrt(normal * normal); normal.X /= length; normal.Y /= length; double[] g = new double[2 * polygons.Count + 2]; g[2 * pd.IteratorPoint.IndexPolygon] = normal.X; g[2 * pd.IteratorPoint.IndexPolygon + 1] = normal.Y; g[2 * pd.IteratorPlane.IndexPolygon] = -normal.X; g[2 * pd.IteratorPlane.IndexPolygon + 1] = -normal.Y; g[2 * polygons.Count + 1] = ((pd.IteratorPoint.Polygon[pd.IteratorPoint.Index] - pd.IteratorPlane.Polygon[pd.IteratorPlane.Index]) * normal); G.Add(g); #endregion } #endregion #endregion #region Шаг 6. Выполняем поиск локального минимума с заданными ограничениями. double mu = 1000; // Должно вводиться с формы! double beta = 0.5; // Должно вводиться с формы! double eps = 1e-3; // Должно вводиться с формы! Calculate(F, G, ref X, mu, beta, eps); #endregion #region Шаг 7. Преобразуем результат метода барьеров в результат задачи размещения и возвращаем длину занятой части полосы. for (int i = 0; i < polygons.Count; i++) { polygons[i].Pole.X = X[2 * i]; polygons[i].Pole.Y = X[2 * i + 1]; } strip_length.Text = X[X.Length - 1].ToString(); #endregion this.polygons.InvalidateVisual(); }
private void toolStripMenuItemCreateDividePlane_Click(object sender, EventArgs e) { if (plane_dividing_list.Count == 0) for (int i = 0; i < polygon_list.Count - 1; i++) { for (int j = i + 1; j < polygon_list.Count; j++) { PlaneDividing plane_dividing = new PlaneDividing(new Polygon2d.Iterator(0, polygon_list[i], 0), new Polygon2d.Iterator(0, polygon_list[j], 0)); plane_dividing.Find(); plane_dividing_list.Add(plane_dividing); } } else plane_dividing_list.Clear(); Invalidate(); }