private void ReadFromFile(string filename) { StreamReader sr = new StreamReader(filename); strip_vector = new Vector2d(); string[] s = sr.ReadLine().Split(' '); strip_vector.X = double.Parse(s[0]); strip_vector.Y = double.Parse(s[1]); polygons = new PolygonWithMinMax[int.Parse(sr.ReadLine())]; for (int i = 0; i < polygons.Length; i++) { polygons[i] = new PolygonWithMinMax(); s = sr.ReadLine().Split(' '); polygons[i].Pole.X = double.Parse(s[0]); polygons[i].Pole.Y = double.Parse(s[1]); for (int j = 2; j < s.Length; j += 2) polygons[i].Add(new Point2d() { X = double.Parse(s[j]), Y = double.Parse(s[j + 1]) }); polygons[i].Check(); } sr.Close(); }
} // !!!Дописать!!! public static Point2d Calc(StripLine strip_line_i, StripLine strip_line_j) { Vector2d vector_i = strip_line_i.Vector; Vector2d vector_j_ = new Vector2d() { X = -strip_line_j.VY, Y = strip_line_j.VX }; double d = vector_i * vector_j_; if (d == 0) return null; else return strip_line_i.Point + vector_i * ((strip_line_j.Point - strip_line_i.Point) * vector_j_ / d); } // !!Проверить!!
public PlacingOpt(PolygonWithMinMax[] polygons, Vector2d strip_vector) { this.polygons = polygons; this.strip_vector = strip_vector; int n = polygons.Length; X = new double[2 * n + 1]; Gs = new double[4 * n + n * (n - 1) / 2][]; for (int i = 0; i < Gs.Length; i++) Gs[i] = new double[10]; index_strip = 2 * n; }
/// <summary> /// Вычесть вектор из текущего. /// </summary> /// <param name="vector">Вектор.</param> public void _Deduct(Vector2d vector) { this.x -= vector.x; this.y -= vector.y; }
/// <summary> /// Добавить вектор к текущему. /// </summary> /// <param name="vector">Вектор.</param> public void _Add(Vector2d vector) { this.x += vector.x; this.y += vector.y; }
/// <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(); }
/// <summary> /// Метод подготовки данных и запуска алгоритма размещения многоугольников (метод барьерных функций). /// </summary> /// <param name="mu"></param> /// <param name="beta"></param> /// <param name="eps"></param> public void CalculateStart(double mu, double beta, double eps) { double width_old; do { width_old = strip_vector.X; #region Шаг 1. Создаём начальную точку. FillPoint(); #endregion #region Шаг 2. Создаём функцию цели. Clear(F); F[index_strip] = 1; #endregion #region Шаг 3. Создаём набор ограничений. Clear(Gs); int k = 0; #region Шаг 3.1. Для каждого многоугольника... for (int i = 0; i < polygons.Length; i++) { #region Шаг 3.1.1. Создаём набор ограничений (G >= 0) по полосе. #region Шаг 3.1.1.1. Ограничение по нижней границе. // Y - min.Y >= 0 Gs[k][2 * i + 1] = 1; Gs[k][index_strip + 1] = -polygons[i].MinY; k++; #endregion #region Шаг 3.1.1.2. Ограничение по левой границе. // X - min.X >= 0 Gs[k][2 * i] = 1; Gs[k][index_strip + 1] = -polygons[i].MinX; k++; #endregion #region Шаг 3.1.1.3. Ограничение по верхней границе. // Y + max.Y <= H --> -Y - max.Y + H >= 0 Gs[k][2 * i + 1] = -1; Gs[k][index_strip + 1] = -polygons[i].MaxY + strip_vector.Y; k++; #endregion #region Шаг 3.1.1.4. Ограничение по правой границе. // X + max.X <= Z --> -X + Z - max.X >= 0 Gs[k][2 * i] = -1; Gs[k][index_strip] = 1; Gs[k][index_strip + 1] = -polygons[i].MaxX; k++; #endregion #endregion } #endregion #region Шаг 3.2. Для каждой пары многоугольников... for (int i = 0; i < polygons.Length - 1; i++) for (int j = i + 1; j < polygons.Length; 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(); #region Временный код. PlaneDividing pd; Polygon2d.Iterator it1i = new Polygon2d.Iterator(i, polygons[i], 0); Polygon2d.Iterator it1j = new Polygon2d.Iterator(j, polygons[j], 0); double ed1 = Find(it1i, it1j); Polygon2d.Iterator it2i = new Polygon2d.Iterator(i, polygons[i], 0); Polygon2d.Iterator it2j = new Polygon2d.Iterator(j, polygons[j], 0); double ed2 = Find(it2j, it2i); if (ed1 > ed2) pd = new PlaneDividing(it1i, it1j); else pd = new PlaneDividing(it2j, it2i); #endregion #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 }; //normal.Normalize(); // Нужна ли нормализация вектора? Gs[k][2 * pd.IteratorPoint.IndexPolygon] = -normal.X; Gs[k][2 * pd.IteratorPoint.IndexPolygon + 1] = -normal.Y; Gs[k][2 * pd.IteratorPlane.IndexPolygon] = normal.X; Gs[k][2 * pd.IteratorPlane.IndexPolygon + 1] = normal.Y; Gs[k][index_strip + 1] = -((pd.IteratorPoint.Polygon[pd.IteratorPoint.Index] - pd.IteratorPlane.Polygon[pd.IteratorPlane.Index]) * normal); k++; #endregion } #endregion #endregion #region Шаг 4. Выполняем поиск локального минимума с заданными ограничениями. Calculate(mu, beta, eps); #endregion #region Шаг 5. Преобразуем результат метода барьеров в результат задачи размещения. FillPolygons(); #endregion } while (Math.Abs(strip_vector.X - width_old) > eps); }
public static void FillAndDraw(this Plane2d plane, System.Drawing.Graphics graphics, System.Drawing.Color color_brush, System.Drawing.Color color_pen) { //graphics.FillEllipse(new System.Drawing.SolidBrush(color_brush), (float)(circle.Pole.X - circle.R), (float)(circle.Pole.Y - circle.R), (float)(2 * circle.R), (float)(2 * circle.R)); Vector2d vector = new Vector2d() { X = -plane.Normal.Y, Y = plane.Normal.X }; Point2d point_prev = plane.Pole - vector * 1000; Point2d point_next = plane.Pole + vector * 1000; graphics.DrawLine(new System.Drawing.Pen(color_pen), (float)(point_prev.X), (float)(point_prev.Y), (float)(point_next.X), (float)(point_next.Y)); }
protected Placement() { region_size = new Vector2d(); }
private bool CheckIntersectBetweenRectangles(Point2d point_i, Vector2d size_i, Point2d point_j, Vector2d size_j) { double eps = 1e-4f; return point_i.X + size_i.X <= point_j.X + eps || point_i.Y + size_i.Y <= point_j.Y + eps || point_j.X + size_j.X <= point_i.X + eps || point_j.Y + size_j.Y <= point_i.Y + eps; }
private bool CheckIntersectWithRectangles(Point2d point, Vector2d size) { bool without_intersect = true; for (int i = 0; i < objects_busy_numbers.Count && without_intersect; i++) without_intersect = without_intersect && CheckIntersectBetweenRectangles(point, size, objects_busy_points[i], objects_sizes[objects_busy_numbers[i]]); return without_intersect; }
private bool CheckIntersectWithRegion(Point2d point, Vector2d size) { double eps = 1e-4f; return point.X + size.X <= task.RegionWidth + eps && point.Y + size.Y <= task.RegionHeight + eps; }
public void ObjectsSizesAdd(int index, Vector2d object_size) { objects_sizes.Insert(index, object_size); Initialize(); }