Example #1
0
        public bool ContainInArea(myVertex vertex)
        {
            if (ContainVertex(vertex,0) != -1)
                return true;

            double x_max = vertexes[0].X;
            for (int i = 1; i < vertexes.Count - 1; i++)
                if (vertexes[i].X > x_max)
                    x_max = vertexes[i].X;

            x_max += 10;
            mySection luch = new mySection(vertex, new myVertex(x_max,vertex.Y));
            int k = 0;
            for (int i = 0; i < vertexes.Count - 1; i++ )
            {
                mySection section = new mySection(vertexes[i], vertexes[i + 1]);
                myVertex intersection = luch.Intersect(section);
                if (intersection != null)
                {
                    k++;
                    if (this.ContainVertex(intersection,0) != -1)
                        i++;
                }
            }

            if (k>0 && k % 2 == 1)
                return true;
            else
                return false;
        }
Example #2
0
        public myVertex Intersect(mySection section)
        {
            myVertex result = null;
            //если вектора не коллинеарны - просто найдем координаты точки пересечения
            double dx = right.X - left.X;
            double dy = right.Y - left.Y;
            double sdx = section.right.X - section.left.X;
            double sdy = section.right.Y - section.left.Y;
            //проверяем вектора на коллинеарность
            if (dx * sdy - dy * sdx != 0)
            {
                /*
                 * если они не коллинеарны, тогда точки пересечения отрезков либо нет, либо она одна
                 *
                 * x_l + a * dx = s_x_l + b * sdx       | * sdy
                 * y_l + a * dy = s_y_l + b * sdy       | * sdx
                 *
                 * sdy*x_l + sdy*a*dx = sdy*s_x_l + sdy*b*sdx   (1)
                 * sdx*y_l + sdx*a*dy = sdx*s_y_l + sdx*b*sdy   (2)
                 *
                 * (1)-(2) = sdy*(x_l-y_l) + a*(sdy*dx - sdx*dy) = sdy*s_x_l - sdx*s_y_l;
                 * a = ( sdy*s_x_l - sdx*s_y_l - sdy*(x_l-y_l) )/(sdy*dx - sdx*dy);
                 * таким образом вычислим параметр а
                 *
                 */
                double a = (sdy * section.left.X - sdx * section.left.Y - (sdy * left.X - sdx * left.Y)) / (sdy * dx - sdx * dy);

                /*
                 * x_l + a * dx = s_x_l + b * sdx       | * dy
                 * y_l + a * dy = s_y_l + b * sdy       | * dx
                 *
                 * dy*x_l + dy*a*dx = dy*s_x_l + dy*b*sdx   (1)
                 * dx*y_l + dx*a*dy = dx*s_y_l + dx*b*sdy   (2)
                 *
                 * (1)-(2) = dy*x_l - dx*y_l = b * (dy*sdx - dx*sdy) + (dy*s_x_l - dx*s_y_l)
                 * b = (dy*x_l - dx*y_l - (dy*s_x_l - dx*s_y_l))/(dy*sdx - dx*sdy)
                 * таким образом вычислим параметр b
                 */
                double b = (dy * left.X - dx * left.Y - (dy * section.left.X - dx * section.left.Y)) / (dy * sdx - dx * sdy);
                //если оба параметра лежат на [0;1], тогда точка пересечения отрезков - лежит на отрезков (!)
                if (a >= 0 && a <= 1 && b >= 0 && b <= 1)
                    result = new myVertex(left.X + a * dx, left.Y + a * dy);
            }
            else
            {
                /*
                 * теперь рассмоотрим случай с коллинеарными векторами
                 * 1) dx != 0
                 * 2) dy != 0
                 * 3) а если и то и то 0, тогда это не отрезок, а точка - таких в данном случае сработает алгоритм заполнения полигона
                 *
                 * суть метода:
                 * найдем какая точка из концов отсекающего отрезка наиболее приближена к правой границе со стороны левой
                 * она и будет результатом (если конечно она попадает на [0;1]
                 */
                if (dx != 0)
                {
                    double t_left = (section.left.X - left.X) / (dx);
                    double t_right = (section.right.X - left.X) / (dx);
                    double result_t = -1;
                    if (t_left <= 1 && t_left > result_t) result_t = t_left;
                    if (t_right <= 1 && t_right > result_t) result_t = t_right;
                    //теперь проверим, а точно ли точка лежит на отрезке
                    if (result_t != -1 && (left.Y + result_t * dy == section.left.Y || left.Y + t_right * dy == section.right.Y))
                        result = new myVertex(left.X + result_t * dx, left.Y + result_t * dy);
                }
                else
                    if (dy != 0)
                    {
                        //всё то же, что и в предыдущем пункте, но с dy
                        double t_left = (section.left.Y - left.Y) / (dy);
                        double t_right = (section.right.Y - left.Y) / (dy);
                        double result_t = -1;
                        if (t_left <= 1 && t_left > result_t) result_t = t_left;
                        if (t_right <= 1 && t_right > result_t) result_t = t_right;
                        //теперь проверим, а точно ли точка лежит на отрезке
                        if (result_t != -1 && (left.X + result_t * dx == section.left.X || left.X + t_right * dx == section.right.X))
                            result = new myVertex(left.X + result_t * dx, left.Y + result_t * dy);
                    }
                    else
                        throw new Exception("Ошибка при поиске пересечения отрезков:\ndx == dy == 0");
            }

            return result;
        }
Example #3
0
 public bool Intersect(mySection section)
 {
     for (int i = 1; i < vertexes.Count; i++)
     {
         myVertex intersection = new mySection(vertexes[i - 1], vertexes[i]).Intersect(section);
         if ( intersection != null)
         {
             if (!intersection.Equals(section.Left))
                 return true;
             else
                 continue;
         }
     }
     return false;
 }
Example #4
0
        private myPolygon GetIntersectionWith(myPolygon polygon)
        {
            //создадим результирующий многоугольник
            myPolygon result = new myPolygon();

            for (int i = 0; i < vertexes.Count - 1; i++)
            {
                //добавим в него текущую вершину
                result.vertexes.Add(vertexes[i]);
                //создадим ребро, из текущей и следующей вершины
                mySection i_section = new mySection(vertexes[i], vertexes[i + 1]);

                //а так же список добавляемых вершин
                List<myVertex> vertexes_to_add = new List<myVertex>();

                //будем искать пересечения
                for (int j = 0; j < polygon.vertexes.Count - 1; j++)
                {
                    //текущее ребро во втором многоугольнике
                    mySection j_section = new mySection(polygon.vertexes[j], polygon.vertexes[j + 1]);

                    //если есть пересечение - добавим в список
                    myVertex intersection = i_section.Intersect(j_section);
                    if (intersection != null && result.ContainVertex(intersection,0) == -1 && !vertexes_to_add.Contains(intersection))
                        vertexes_to_add.Add(intersection);
                }

                //теперь нужно отсортировать список по удалению от начала отрезка
                //параллельно добавляя их в многоугольник-результат
                for (int j = 0; j < vertexes_to_add.Count; j++)
                {
                    double min_distance = result.vertexes[result.vertexes.Count - 1].DistanceTo(vertexes_to_add[j]);
                    for (int k = j + 1; k < vertexes_to_add.Count; k++)
                    {
                        double distance = result.vertexes[result.vertexes.Count - 1].DistanceTo(vertexes_to_add[k]);
                        if (distance < min_distance)
                        {
                            myVertex temp = vertexes_to_add[j];
                            vertexes_to_add[j] = vertexes_to_add[k];
                            vertexes_to_add[k] = temp;
                            min_distance = distance;
                        }
                    }
                    result.vertexes.Add(vertexes_to_add[j]);
                }
            }

            //не забудем добавить самую первую точку
            result.vertexes.Add(result.vertexes[0]);

            return result;
        }
Example #5
0
        private void MainForm_MouseDown(object sender, MouseEventArgs e)
        {
            button1.Enabled = true;
            if (painted)
            {
                graphics.Clear(Color.White);
                first_ended = second_ended = painted = false;
                first = null;
                second = null;

                checkBox1.Checked = false;
                checkBox2.Checked = false;
                checkBox4.Checked = false;
            }
            if (!first_ended && e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                if (first == null)
                    first = new myPolygon(new myVertex(e.X, e.Y), graphics, new Pen(Color.Red, 2));
                else
                {
                    mySection attention = new mySection(first.GetLastVertex(), new myVertex(e.X, e.Y));
                    if (first.Intersect(attention))
                        MessageBox.Show("Самопересечения не допускаются. Будьте внимательнее!");
                    else
                        if (!first.AddVertex(new myVertex(e.X, e.Y), graphics, new Pen(Color.Red, 2)))
                        {
                            first_ended = true;
                            checkBox1.Checked = true;
                        }
                }
            }
            else
                if (!second_ended && e.Button == System.Windows.Forms.MouseButtons.Right)
                {

                    if (second == null)
                        second = new myPolygon(new myVertex(e.X, e.Y), graphics, new Pen(Color.Green, 2));
                    else
                    {
                        mySection attention = new mySection(second.GetLastVertex(), new myVertex(e.X, e.Y));
                        if (second.Intersect(attention))
                            MessageBox.Show("Самопересечения не допускаются. Будьте внимательнее!");
                        else
                            if (!second.AddVertex(new myVertex(e.X, e.Y), graphics, new Pen(Color.Green, 2)))
                            {
                                second_ended = true;
                                checkBox2.Checked = true;
                            }
                    }
                }
                else
                {
                    graphics.Clear(Color.White);
                    if (first_ended && second_ended)
                        first.GetUnionWith(second, graphics, new Pen(Color.Brown,3), checkBox4.Checked);
                    painted = true;
                    MessageBox.Show("Для того, чтобы выполнить процедуру с новыми многоугольниками\n кликните мышкой по введенным многоугольникам.");
                }
        }