Example #1
0
        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
        }
Example #2
0
        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;
        }
Example #3
0
 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();
 }
Example #4
0
        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();
        }
Example #5
0
        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);
        }
Example #6
0
 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;
 }
Example #7
0
 /// <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); //!!! Необходимо учитывать погрешность.
 }
Example #8
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);
 }
Example #9
0
        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;
        }
Example #10
0
 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
        }
Example #13
0
 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;
 }
Example #14
0
 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;
 }
Example #15
0
 /// <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;
 }
Example #16
0
 } // Кузовлев.
 private bool Точка_принадлежит_многоугольнику(Point2d point, Polygon2d polygon)
 {
     throw new NotImplementedException();
 } // Харин, Пудло
Example #17
0
 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);
 }
Example #18
0
 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;
 }
Example #19
0
        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
        }
Example #21
0
            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;
            }
Example #22
0
 /// <summary>
 /// Переопределение метода добавления точки.
 /// </summary>
 /// <param name="point">Точка.</param>
 public new void Add(Point2d point)
 {
     base.Add(point);
     OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, point));
 }
Example #23
0
 /// <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;
 }