public FormMain() { InitializeComponent(); polygon_list = new List<Polygon2d>(); polygon = null; is_edit = false; #region Тестовый вариант. pole = new Point2d { X = 0, Y = 30 }; Polygon2d polygon_temp = new Polygon2d { Pole = new Point2d { X = 30, Y = 10 } }; polygon_temp.Add(new Point2d { X = 0, Y = 0 }); polygon_temp.Add(new Point2d { X = 100, Y = 0 }); polygon_temp.Add(new Point2d { X = 100, Y = 100 }); polygon_list.Add(polygon_temp); polygon_temp = new Polygon2d { Pole = new Point2d { X = 150, Y = 90 } }; polygon_temp.Add(new Point2d { X = 50, Y = 0 }); polygon_temp.Add(new Point2d { X = 100, Y = 50 }); polygon_temp.Add(new Point2d { X = 50, Y = 150 }); polygon_temp.Add(new Point2d { X = 0, Y = 50 }); polygon_list.Add(polygon_temp); #endregion }
public bool IsContain(Rectangle rectangle, Point2d pole) { Point2d pole_temp = rectangle.Pole; rectangle.Pole = pole; bool is_checked = true; for (int j = 1; j <= this.vector.Dim && is_checked; j++) { double coor = rectangle.Pole[j] + rectangle.Vector[j]; is_checked = 0 <= coor && coor <= this.vector[j]; } rectangle.Pole = pole_temp; return is_checked; }
public Point2d OptPole(Point2d opt_pole, Point2d pole) { if (pole.X < opt_pole.X) return pole; if (pole.X > opt_pole.X) return opt_pole; if (pole.X == opt_pole.X) { if (pole.Y < opt_pole.Y) return pole; if (pole.Y > opt_pole.Y) return opt_pole; } throw new NotImplementedException(); }
private void FormMain_MouseDown(object sender, MouseEventArgs e) { point_curr.X = e.X; point_curr.Y = e.Y; is_mouse_down = true; if (e.Button == System.Windows.Forms.MouseButtons.Left && e.Clicks == 2) { is_edit = !is_edit; if (is_edit && polygon == null) { polygon = new Polygon2d { Pole = new Point2d { Vector = point_curr - pole } }; polygon_list.Add(polygon); } if (!is_edit && !polygon.IsRightPolygon()) polygon_list.Remove(polygon); } if (e.Button == System.Windows.Forms.MouseButtons.Left && e.Clicks == 1) { Point2d point = new Point2d { Vector = point_curr - pole }; if (is_edit) { point.Vector -= polygon.Pole.Vector; polygon.Add(point); } else { polygon = null; for (int i = 0; i < polygon_list.Count && polygon == null; i++) if (polygon_list[i].IsContain(point)) polygon = polygon_list[i]; } } Invalidate(); }
public void DrawGrid(System.Drawing.Graphics g, Point2d pole) { int step = 30; for (int x = (int)pole.X; x >= 0; x -= step) g.DrawLine(System.Drawing.Pens.Silver, x, 0, x, ClientRectangle.Height); for (int x = (int)pole.X; x <= ClientRectangle.Width; x += step) g.DrawLine(System.Drawing.Pens.Silver, x, 0, x, ClientRectangle.Height); for (int y = (int)pole.Y; y >= 0; y -= step) g.DrawLine(System.Drawing.Pens.Silver, 0, y, ClientRectangle.Width, y); for (int y = (int)pole.Y; y <= ClientRectangle.Width; y += step) g.DrawLine(System.Drawing.Pens.Silver, 0, y, ClientRectangle.Width, y); g.DrawLine(System.Drawing.Pens.Black, (int)pole.X, 0, (int)pole.X, ClientRectangle.Height); g.DrawLine(System.Drawing.Pens.Black, 0, (int)pole.Y, ClientRectangle.Width, (int)pole.Y); }
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; }
/// <summary> /// Проверка на попадание круга в полосу. /// </summary> /// <param name="point">Вектор размещения круга.</param> /// <param name="circle">Круг.</param> /// <param name="height">Высота полосы.</param> /// <returns>Возвращает True, если круг полностью лежит внутри полосы. False - в противном случае.</returns> private bool IsCheckedStrip(Point2d point, Circle circle, double height) { return (point.Y + circle.R <= height) && (point.X - circle.R >= 0) && (point.Y - circle.R >= 0); //!!! Необходимо учитывать погрешность. }
/// <summary> /// Получить расширенное расстояние от точки до точки. /// </summary> /// <param name="point_this">Точка.</param> /// <param name="point">Точка.</param> /// <returns>Расширенное расстояние.</returns> public static double Расширенное_расстояние(this Point2d point_this, Point2d point) { Vector2d vector = point - point_this; return Math.Sqrt(vector * vector); }
private bool StepUpgrade() { #region Шаг 5.1. Проверяем размер круга относительно полосы. if (2 * circles[current_index].Value > height) return false; #endregion #region Шаг 5.2. Устанавливаем начальное значение для точки размещения текущего объекта и связанной с ней вершиной. Point2d point_global = new Point2d { X = double.PositiveInfinity }; Vertex<Geometric2d> vertex_global = null; #endregion #region Шаг 5.3. Для каждой вершины выполняем следующее... for (int i = 0; i < triples.Count; i++) { Vertex<Geometric2d> vertex = triples[i]; do { #region Шаг 5.3.1. Если выполняются все условия существования точки плотного размещения второго рода, то находим её. if (Существует_точка_плотного_размещения_второго_рода(circles[current_index], vertex)) { Point2d point_temp = circles[current_index].Точка_близости_второго_рода(vertex.Next.DataInVertex, vertex.Prev.DataInVertex); #region Шаг 5.3.1.1. Если точка даёт меньшее приращение функции цели, то сохраняем вершину и точку размещения. if (point_temp.X < point_global.X) { point_global = point_temp; vertex_global = vertex; } #endregion } #endregion vertex = vertex.Next; } while (vertex != triples[i]); } #endregion #region Шаг 5.4. Устанавливаем объект в найденную точку размещения. circles[current_index].Pole.Copy = point_global; #endregion #region Шаг 5.5. Вставляем объект в ребро напротив найденной вершины. vertex_global.BreakCrosBy(circles[current_index]); vertex_global = vertex_global.Cros; #endregion #region Шаг 5.7. Проверяем и переразбиваем модель вокруг вершины, связанной со вставленным объектом. Vertex<Geometric2d> vertex_temp = vertex_global; do { while (CircleExt.Расширенное_расстояние(vertex_temp.DataInVertex as Circle, vertex_temp.Cros.Somes.CircleDelone) < 0) vertex_temp.Rebuild(); vertex_temp.SetCircleDelone(GeometricExt.Круг_Делоне(vertex_temp.Prev.DataInVertex, vertex_temp.DataInVertex, vertex_temp.Next.DataInVertex)); vertex_temp = vertex_temp.Next.Cros.Next; } while (vertex_temp != vertex_global); #endregion triples = this.vertex.GetTriples(); #region Шаг 5.8. Пересчёт ширины занятой части полосы. length = Math.Max(length, circles[current_index].Pole.X + circles[current_index].Value); #endregion return true; }
private bool StepUpgrade() { #region Шаг 5.1. Проверяем размер круга относительно полосы. if (2 * circles[current_index].R > height) return false; #endregion #region Шаг 5.2. Устанавливаем начальное значение для точки размещения текущего объекта и связанной с ней вершиной. Point2d point_global = new Point2d() { X = double.PositiveInfinity }; VertexClass vertex_global = null; #endregion #region Шаг 5.3. Для каждой тройки (кроме NullTriple) выполняем следующее... TripleClass.Enumerator en_triples = triple.GetEnumerator(); en_triples.MoveNext(); do { #region Шаг 5.3.1. Если радиус круга Делоне больше радиуса размещаемого круга, то... if (en_triples.Curren.Data.R >= circles[current_index].R) { #region Шаг 5.3.1.1. Для каждой вершины тройки выполняем следующее... VertexClass.Enumerator en_vertexes = en_triples.Curren.Vertex.GetEnumerator(); do { Point2d point_temp = new Point2d() { X = double.PositiveInfinity, Y = double.PositiveInfinity }; #region Шаг 5.3.1.1.1. Если выполняются все условия существования точки плотного размещения второго рода, то находим её. bool is_exist; if (en_vertexes.Current.Cros.Triple.Data.R <= circles[current_index].R) //is_exist = true; is_exist = (ModelExtending.ED(en_vertexes.Current.Prev.Data, en_vertexes.Current.Next.Data) <= 2 * circles[current_index].R); else if (MonotonCheck(en_vertexes.Current, circles[current_index])) // Проверка монотонности функции. !!!Дописать!!! is_exist = false; else is_exist = (ModelExtending.ED(en_vertexes.Current.Prev.Data, en_vertexes.Current.Next.Data) <= 2 * circles[current_index].R); #region Шаг 5.3.1.1.2. Поиск точки плотного размещения для двух объектов. if (is_exist) { point_temp = ModelExtending.PP(en_vertexes.Current.Prev.Data, en_vertexes.Current.Next.Data, circles[current_index]); // !!!Дописать!!! #region Шаг 5.3.1.1.3. Если точка даёт меньшее приращение функции цели, то сохраняем вершину и точку размещения. if (point_temp.X < point_global.X) { point_global = point_temp; vertex_global = en_vertexes.Current; } #endregion } #endregion #endregion #region !Шаг 5.3.1.1.4. Если точка не даёт приращение выйти из 5.3. Необязательно! #endregion } while (en_vertexes.MoveNextInTriple()); #endregion } #endregion } while (en_triples.MoveNext()); #endregion #region Шаг 5.4. Устанавливаем объект в найденную точку размещения. circles[current_index].Center = point_global; #endregion #region Шаг 5.5. Вставляем объект в ребро напротив найденной вершины. vertex_global.BreakCrosBy(circles[current_index]); #endregion #region Шаг 5.6. Создаём для новых троек Triple и добавляем их в список. triple.Add(new TripleClass(vertex_global.Cros)); triple.Add(new TripleClass(vertex_global.Cros.Next.Cros)); #endregion #region Шаг 5.7. Проверяем и переразбиваем модель вокруг вершины, связанной со вставленным объектом. VertexClass.Enumerator en_checking_vertexes = vertex_global.Cros.GetEnumerator(); while (en_checking_vertexes.MoveNextInNode(ChBF, ChVF)) ; // !!!Не работает пока ещё!!! #endregion #region Шаг 5.8. Пересчёт ширины занятой части полосы. length = Math.Max(length, circles[current_index].X + circles[current_index].R); #endregion return true; }
/// <summary> /// Проверка на попадание круга в полосу. /// </summary> /// <param name="point">Вектор размещения круга.</param> /// <param name="circle">Круг.</param> /// <param name="height">Высота полосы.</param> /// <returns>Возвращает True, если круг полностью лежит внутри полосы. False - в противном случае.</returns> protected bool IsCheckedStrip(Point2d point, Circle circle, double height) { return (point.Y + circle.Scalar <= height) && (point.X - circle.Scalar >= 0) && (point.Y - circle.Scalar >= 0); //!!! Необходимо учитывать погрешность. }
/// <summary> /// Поиск локального минимума с использованием метода последовательного одиночного размещения. /// </summary> protected override void Calculate() { #region Шаг 1. Метод последовательного одиночного размещения. Для каждого круга... for (int i = 0; i < circles.Length; i++) { #region Шаг 1.1. Создание списка точек возможных размещений и добавление двух начальных точек. List<Point2d> points = new List<Point2d>(); points.Add(new Point2d { X = circles[i].Scalar, Y = circles[i].Scalar }); points.Add(new Point2d { X = circles[i].Scalar, Y = height - circles[i].Scalar }); #endregion #region Шаг 1.2. Создание и заполнение списка годографов. Circle[] godographs = new Circle[i]; for (int j = 0; j < i; j++) godographs[j] = Circle2dExt.Годограф_функции_плотного_размещения(circles[j], circles[i]); #endregion #region Шаг 1.3. Поиск точек пересечения круга с полосой. for (int j = 0; j < godographs.Length; j++) { #region Шаг 1.3.1. Поиск точек пересечения круга с левой границей полосы. if (godographs[j].Pole.X - godographs[j].Scalar < circles[i].Scalar) { double x = circles[i].Scalar - godographs[j].Pole.X; double y = Math.Sqrt(godographs[j].Scalar * godographs[j].Scalar - x * x); Point2d point; point = new Point2d { X = circles[i].Scalar, Y = godographs[j].Pole.Y - y }; if (IsCheckedStrip(point, circles[i], height)) points.Add(point); point = new Point2d { X = circles[i].Scalar, Y = godographs[j].Pole.Y + y }; if (IsCheckedStrip(point, circles[i], height)) points.Add(point); } #endregion #region Шаг 1.3.2. Поиск точек пересечения круга с нижней границей полосы. if (godographs[j].Pole.Y - godographs[j].Scalar < circles[i].Scalar) { double y = circles[i].Scalar - godographs[j].Pole.Y; double x = Math.Sqrt(godographs[j].Scalar * godographs[j].Scalar - y * y); Point2d point; point = new Point2d { X = godographs[j].Pole.X - x, Y = circles[i].Scalar }; if (IsCheckedStrip(point, circles[i], height)) points.Add(point); point = new Point2d { X = godographs[j].Pole.X + x, Y = circles[i].Scalar }; if (IsCheckedStrip(point, circles[i], height)) points.Add(point); } #endregion #region Шаг 1.3.3. Поиск точек пересечения круга с верхней границей полосы. if (godographs[j].Pole.Y + godographs[j].Scalar > height - circles[i].Scalar) { double y = height - circles[i].Scalar - godographs[j].Pole.Y; double x = Math.Sqrt(godographs[j].Scalar * godographs[j].Scalar - y * y); Point2d point; point = new Point2d { X = godographs[j].Pole.X - x, Y = height - circles[i].Scalar }; if (IsCheckedStrip(point, circles[i], height)) points.Add(point); point = new Point2d { X = godographs[j].Pole.X + x, Y = height - circles[i].Scalar }; if (IsCheckedStrip(point, circles[i], height)) points.Add(point); } #endregion } #endregion #region Шаг 1.4. Поиск точек пересечения годографов. for (int j = 0; j < godographs.Length - 1; j++) for (int k = j + 1; k < godographs.Length; k++) { Point2d point; point = Circle2dExt.Точка_пересечения_границ(godographs[j], godographs[k]); if (point != null && IsCheckedStrip(point, circles[i], height)) points.Add(point); // Заменить на "Добавить в отсортированный набор данных". Лучше всего использовать бинарное взвешенное дерево. point = Circle2dExt.Точка_пересечения_границ(godographs[k], godographs[j]); if (point != null && IsCheckedStrip(point, circles[i], height)) points.Add(point); // Заменить на "Добавить в отсортированный набор данных". Лучше всего использовать бинарное взвешенное дерево. } #endregion #region Шаг 1.5. Сортировка набора точек возможного размещения.!!! Данная часть не нужна, если использовать сортировку при вставке точек в набор данных. for (int j = 0; j < points.Count - 1; j++) for (int k = j + 1; k < points.Count; k++) if (points[j].X > points[k].X || (points[j].X == points[k].X && points[j].Y > points[k].Y)) { Point2d temp_point = points[j]; points[j] = points[k]; points[k] = temp_point; } #endregion #region Шаг 1.6. Выбор наилучшей точки размещения, при которой не возникает пересечение кругов и размещение круга. int p = -1; do { p++; circles[i].Pole.Copy = points[p]; } while (!IsCheckedCircles(circles[i], circles, i, eps)); #endregion #region Шаг 1.7. Пересчёт ширины занятой части полосы. length = Math.Max(length, circles[i].Pole.X + circles[i].Scalar); #endregion } #endregion }
public static bool IsContain(this Polygon2d polygon, Point2d point) { if (polygon.Count <= 1) return false; bool is_contain = true; Polygon2d.Iterator iterator = new Polygon2d.Iterator(0, polygon, 0); for (int i = 0; i < iterator.Polygon.Count && is_contain; i++) is_contain = Plane2dExt.Расширенное_расстояние(iterator.Plane(i), point) <= 0; return is_contain; }
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; }
/// <summary> /// Получить расширенное расстояние от круга до точки. /// </summary> /// <param name="circle_this">Круг.</param> /// <param name="point">Точка.</param> /// <returns>Расширенное расстояние.</returns> public static double Расширенное_расстояние(Geometric2dWithPointScalar circle_this, Point2d point) { return Point2dExt.Расширенное_расстояние(circle_this.Pole, point) - circle_this.Scalar; }
} // Кузовлев. private bool Точка_принадлежит_многоугольнику(Point2d point, Polygon2d polygon) { throw new NotImplementedException(); } // Харин, Пудло
public static void FillAndDraw(this Graphics graphics, Brush brush, Pen pen, Point2d point, float halfSize = 2) { graphics.FillEllipse(brush, (float)point.X - 1, (float)point.Y - 1, halfSize, halfSize); graphics.DrawEllipse(pen, (float)point.X - 1, (float)point.Y - 1, halfSize, halfSize); }
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; }
public void Calculate() { #region Создание списка точек размещения и добавление первой точки. List<Point2d> point_of_placement = new List<Point2d>(); point_of_placement.Add(new Point2d()); #endregion objects_busy_square = 0; #region Для каждого объекта размещения... for (int i = 0; i < sort.Count; i++) { Vector2d size = objects_sizes[sort[i]]; #region Определение начального значения точки размещения текущего объекта размещения и соответствующих ей занятой части области размещения и её площади (используется для определения лучшей точки размещения). Point2d point = new Point2d { X = double.PositiveInfinity, Y = double.PositiveInfinity }; double width = Math.Max(region_size.X, point.X + size.X); double height = Math.Max(region_size.Y, point.Y + size.Y); double object_function = width * height; #endregion #region Для каждой точки размещения... for (int j = 0; j < point_of_placement.Count; j++) { Point2d point_temp = point_of_placement[j]; #region Проверка попадания текущего объекта размещения в текущей точке размещения в область размещения. if (CheckIntersectWithRegion(point_temp, size)) #region Проверка непересечения текущего объекта размещения в текущей точке размещения со всеми размещёнными объектами. if (CheckIntersectWithRectangles(point_temp, size)) { #region Определение занятой части области размещения и её площади при размещении текущего объекта размещения в текущей точке размещения. double width_temp = Math.Max(region_size.X, point_temp.X + size.X); double height_temp = Math.Max(region_size.Y, point_temp.Y + size.Y); double object_function_temp = width_temp * height_temp; #endregion #region Определение того, является ли текущая точка размещения лучше сохранённой (оптимальной). bool is_change = object_function > object_function_temp || object_function == object_function_temp && point.X > point_temp.X || object_function == object_function_temp && point.X == point_temp.X && point.Y >= point_temp.Y; #endregion #region Сохранение лучшей точки размещения и значения функции цели. if (is_change) { point = point_temp; object_function = object_function_temp; } #endregion } #endregion #endregion } #endregion #region Проверка существования точки размещения для текущего объекта размещения. if (!double.IsPositiveInfinity(point.X) && !double.IsPositiveInfinity(point.Y)) { #region Сохранение точки размещения текущего объетка. objects_busy_points.Add(point); #endregion #region Добавление номера объекта в список размещённых объектов. objects_busy_numbers.Add(sort[i]); #endregion #region Определение площади размещённых объектов (используется для расчёта функции цели при размещении в прямоугольнике). objects_busy_square += size.X * size.Y; #endregion #region Сохранение предыдущего значения функции цели. double object_function_old = region_size.X * region_size.Y; #endregion #region Определение размеров новой занятой части области размещения. region_size.X = Math.Max(region_size.X, point.X + size.X); region_size.Y = Math.Max(region_size.Y, point.Y + size.Y); #endregion #region Оперделение и добавление новых точек размещения. point_of_placement.Add(new Point2d { X = 0, Y = point.Y + size.Y }); point_of_placement.Add(new Point2d { X = point.X + size.X, Y = 0 }); for (int j = 0; j < objects_busy_numbers.Count - 1; j++) { point_of_placement.Add(new Point2d { X = point.X + size.X, Y = objects_busy_points[j].Y + objects_sizes[sort[j]].Y }); point_of_placement.Add(new Point2d { X = objects_busy_points[j].X + objects_sizes[sort[j]].X, Y = point.Y + size.Y }); } #endregion } else #region Добавление номера объекта в список неразмещённых объектов. objects_free_numbers.Add(sort[i]); #endregion #endregion } #endregion ObjectFunctionCalculate(); }
/// <summary> /// Поиск локального минимума с использованием метода последовательного одиночного размещения. /// </summary> protected override void Calculate() { #region Шаг 1. Метод последовательного одиночного размещения. Для каждого круга... for (int i = 0; i < circles.Length; i++) { System.Threading.Thread.Sleep(100); #region Шаг 1.1. Устанавливаем начальное значение для точки размещения текущего объекта и связанной с ней вершиной. Point2d point_global = new Point2d { X = double.PositiveInfinity }; Vertex<Geometric2d> vertex_global = null; #endregion #region Шаг 1.2. Для каждой тройки выполняем следующее... for (int j = 0; j < triples.Count; j++) { #region Шаг 1.2.1. Для каждой вершины выполняем следующее... Vertex<Geometric2d> vertex_local = triples[j]; do { #region Шаг 1.2.1.1. Если выполняются все условия существования точки плотного размещения второго рода, то находим её. if (Существует_точка_плотного_размещения_второго_рода(circles[i], vertex_local)) { #region Шаг 1.2.1.1.1. Поиск точки близости второго рода. Point2d point_temp = circles[i].Точка_близости_второго_рода(vertex_local.Next.DataInVertex, vertex_local.Prev.DataInVertex); #endregion #region Шаг 1.2.1.1.2. Если точка даёт меньшее приращение функции цели, то сохраняем вершину и точку размещения. if (point_temp.X < point_global.X) { point_global = point_temp; vertex_global = vertex_local; } #endregion } #endregion vertex_local = vertex_local.Next; } while (vertex_local != triples[j]); #endregion } #endregion #region Шаг 1.3. Устанавливаем объект в найденную точку размещения. circles[i].Pole.Copy = point_global; #endregion #region Шаг 1.4. Вставляем объект в ребро напротив найденной вершины. vertex_global.BreakCrosBy(circles[i]); vertex_global = vertex_global.Cros; #endregion #region Шаг 1.5. Проверяем и переразбиваем модель вокруг вершины, связанной со вставленным объектом. Vertex<Geometric2d> vertex_temp = vertex_global; do { while (Circle2dExt.Расширенное_расстояние(vertex_temp.DataInVertex as Circle, vertex_temp.Cros.Somes.CircleDelone) < 0) vertex_temp.Rebuild(); vertex_temp.SetCircleDelone(Geometric2dExt.Круг_Делоне(vertex_temp.Prev.DataInVertex, vertex_temp.DataInVertex, vertex_temp.Next.DataInVertex)); vertex_temp = vertex_temp.Next.Cros.Next; } while (vertex_temp != vertex_global); #endregion #region Шаг 1.6. Находим список всех троек. !Можно уменьшить сложность данного пункта, если использовать только новые полученные тройки! triples = this.vertex.GetTriples(); #endregion #region Шаг 1.7. Пересчёт ширины занятой части полосы. length = Math.Max(length, circles[i].Pole.X + circles[i].Scalar); if (((Plane2d)(this.vertex.DataInVertex)).Pole.X < length + 2 * height) { (this.vertex.DataInVertex as Plane2d).Pole.X = length + 2 * height; this.vertex.Next.Cros.Next.Somes.CircleDelone.Pole.X = length + 2 * height - height / 2; } #endregion } #endregion #region Шаг 2. Изменение расположения полуплоскости, которая определяет правую границу полосы. (this.vertex.DataInVertex as Plane2d).Pole.X = length; this.vertex.Next.Cros.Next.Somes.CircleDelone.Pole.X = length - height / 2; Vertex<Geometric2d> vertex_t = this.vertex; do { while (Geometric2dExt.Расширенное_расстояние(vertex_t.DataInVertex, vertex_t.Cros.Somes.CircleDelone) < 0) { vertex_t.Rebuild(); vertex_t.SetCircleDelone(Geometric2dExt.Круг_Делоне(vertex_t.Prev.DataInVertex, vertex_t.DataInVertex, vertex_t.Next.DataInVertex)); vertex_t.Next.Cros.SetCircleDelone(Geometric2dExt.Круг_Делоне(vertex_t.Next.Cros.Prev.DataInVertex, vertex_t.Next.Cros.DataInVertex, vertex_t.Next.Cros.Next.DataInVertex)); } vertex_t = vertex_t.Next.Cros.Next; } while (vertex_t != this.vertex); #endregion }
private bool Step() { #region Шаг-1. Проверка размера круга относительно полосы. if (2 * circles[current_index].R > height) return false; #endregion #region Шаг-2. Создание списка точек возможных размещений и добавление двух начальных точек. List<Point2d> points = new List<Point2d>(); points.Add(new Point2d() { X = circles[current_index].R, Y = circles[current_index].R }); points.Add(new Point2d() { X = circles[current_index].R, Y = height - circles[current_index].R }); #endregion #region Шаг-3. Создание и заполнение списка годографов. List<Circle> godographs = new List<Circle>(circles.Count); for (int i = 0; i < placed_circles.Count; i++) godographs.Add(new Circle() { R = placed_circles[i].R + circles[current_index].R, X = placed_circles[i].X, Y = placed_circles[i].Y }); #endregion #region Шаг-4. Поиск точек пересечения круга с полосой. for (int i = 0; i < godographs.Count; i++) { #region Шаг-4.1. Поиск точек пересечения круга с левой границей полосы. if (godographs[i].X - godographs[i].R < circles[current_index].R) { double x = circles[current_index].R - godographs[i].X; double y = Math.Sqrt(godographs[i].R * godographs[i].R - x * x); Point2d point; point = new Point2d() { X = circles[current_index].R, Y = godographs[i].Y - y }; if (IsCheckedStrip(point, circles[current_index], height)) points.Add(point); point = new Point2d() { X = circles[current_index].R, Y = godographs[i].Y + y }; if (IsCheckedStrip(point, circles[current_index], height)) points.Add(point); } #endregion #region Шаг-4.2. Поиск точек пересечения круга с нижней границей полосы. if (godographs[i].Y - godographs[i].R < circles[current_index].R) { double y = circles[current_index].R - godographs[i].Y; double x = Math.Sqrt(godographs[i].R * godographs[i].R - y * y); Point2d point; point = new Point2d() { X = godographs[i].X - x, Y = circles[current_index].R }; if (IsCheckedStrip(point, circles[current_index], height)) points.Add(point); point = new Point2d() { X = godographs[i].X + x, Y = circles[current_index].R }; if (IsCheckedStrip(point, circles[current_index], height)) points.Add(point); } #endregion #region Шаг-4.3. Поиск точек пересечения круга с верхней границей полосы. if (godographs[i].Y + godographs[i].R > height - circles[current_index].R) { double y = height - circles[current_index].R - godographs[i].Y; double x = Math.Sqrt(godographs[i].R * godographs[i].R - y * y); Point2d point; point = new Point2d() { X = godographs[i].X - x, Y = height - circles[current_index].R }; if (IsCheckedStrip(point, circles[current_index], height)) points.Add(point); point = new Point2d() { X = godographs[i].X + x, Y = height - circles[current_index].R }; if (IsCheckedStrip(point, circles[current_index], height)) points.Add(point); } #endregion } #endregion #region Шаг-5. Поиск точек пересечения годографов. for (int i = 0; i < godographs.Count - 1; i++) for (int j = i + 1; j < godographs.Count; j++) { Point2d point; point = PlacingPoint.Calc(godographs[i], godographs[j]); if (point != null && IsCheckedStrip(point, circles[current_index], height)) points.Add(point); // Заменить на "Добавить в отсортированный набор данных". Лучше всего использовать бинарное взвешенное дерево. point = PlacingPoint.Calc(godographs[j], godographs[i]); if (point != null && IsCheckedStrip(point, circles[current_index], height)) points.Add(point); // Заменить на "Добавить в отсортированный набор данных". Лучше всего использовать бинарное взвешенное дерево. } #endregion #region Шаг-6. Сортировка набора точек возможного размещения.!!! Данная часть не нужна, если использовать сортировку при вставке точек в набор данных. for (int i = 0; i < points.Count - 1; i++) for (int j = i + 1; j < points.Count; j++) if (points[i].X > points[j].X || (points[i].X == points[j].X && points[i].Y > points[j].Y)) { Point2d temp_point = points[i]; points[i] = points[j]; points[j] = temp_point; } #endregion #region Шаг-7. Выбор наилучшей точки размещения, при которой не возникает пересечение кругов и размещение круга. int p = -1; do { p++; circles[current_index].Pole.Copy = points[p]; } while (!ModelExtending.IsCheckedCircles(circles[current_index], placed_circles, 0.0001)); #endregion #region Шаг-8. Пересчёт ширины занятой части полосы. length = Math.Max(length, circles[current_index].X + circles[current_index].R); #endregion return true; }
/// <summary> /// Переопределение метода добавления точки. /// </summary> /// <param name="point">Точка.</param> public new void Add(Point2d point) { base.Add(point); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, point)); }
/// <summary> /// Получить расширенное расстояние от полуплоскости до точки. /// </summary> /// <param name="plane_this">Полуплоскость.</param> /// <param name="point">Точка.</param> /// <returns>Расширенное расстояние.</returns> public static double Расширенное_расстояние(Plane2d plane_this, Point2d point) { return (point - plane_this.Pole) * plane_this.Normal; }