Программирование решения задач о пересечении двухвыпуклым многоугольником
Задача: Найти пересечение и объединение двух выпуклым многоугольником. Многоугольники задаются координатами вершин в порядке обхода по контуру. В процессе решения поставленных задач курсовой работы использовались прикладные системы программирования и необходимые методы решения заданий. Ребром называется направленный отрезок или кривая. Ребро, начинающееся в точка a и заканчивающееся в точке… Читать ещё >
Программирование решения задач о пересечении двухвыпуклым многоугольником (реферат, курсовая, диплом, контрольная)
Учреждение образования
«Белорусский государственный педагогический университет имени Максима Танка»
Физико-математический факультет Кафедра информатики и методики преподавания информатики Программирование решения задач о пересечении двух выпуклым многоугольником Допущена к защите Заведующий кафедрой_______Зенько С.И.
Курсовая работа студентки 302 группы 3 курса специальности «Математика. Информатика»
дневной формы получения образования
_______________ Витько Марии Игоревны Научный руководитель, доктор физико-математических наук, профессор _________В.М. Котов Минск, 2015
В процессе развития вычислительной техники было создано множество языков и технологий программирования, практически несовместимых между собой. Конечно, при разработке программ, работающих автономно, можно обойтись одним языком, одной технологией программирования и не иметь никаких проблем с совместимостью, но приложения для Интернета требуют использования разных языков и разных технологий.
В этой курсовой работе я покажу как решения геометрической задачи на языке С#, использующим объектно-ориентированный подход. В настоящее время этот подход является основным для различных языков программирования.
Цель моей работы заключаеться в том, чтобы показать как решить геометрическую задачу «О пересечеии двух выпуклым многоугольников» на языке программирования С#.
Курсовая работа состоит из четырех глав. В первой главе рассказываеться про алгоритм решения задач, во-второй реализация алгоритма на языке программирования, в-третей представлены тесты для проверки и в четветой графическое представление решение задачи.
ГЛАВА 1. Разработка алгоритма решения задачи
Ребром называется направленный отрезок или кривая. Ребро, начинающееся в точка a и заканчивающееся в точке b обозначается как E (a, b).
Контуром называется множество ребер, такое, что и каждые два последовательных ребра в списке являются смежными, т. е.. (В контуре может быть два ребра, если хотя бы одно из них — кривая, иначе ребер должно быть не менее трех). Точка, для которой ребра и являются соответственно входящим и выходящим, считается i-й вершиной контура. Последнее ребро контура является смежным с первым ребром. Порядок обхода ребер контура с увеличением индекса i будем считать прямым направлением обхода, противоположный ему — обратным Полигоном в данной случае считается набор не пересекающихся контуров. (Касание контуров в одной точке не считается пересечением). Контуры заданы так, что области, включаемые в полигон, всегда лежат слева от контура при прямом порядке обхода ребер.
Входными данными для алгоритма являются два полигона. Каждый из них — набор не пересекающихся контуров. Включение или исключение внутренней части контура задается направлением обхода его ребер (по часовой — исключение, против часовой — включение).
Наложим исходные полигоны друг на друга. Форма исходных полигонов и способ наложения подобраны так, чтобы отразить большую часть возможных вариантов взаимного расположения ребер двух полигонов.
Найдем все точки пересечения и объединения двух полигонов.
ГЛАВА 2. Реализация разработанного алгоритма на языке программирования
Задача: Найти пересечение и объединение двух выпуклым многоугольником. Многоугольники задаются координатами вершин в порядке обхода по контуру.
Класс Polygon
using System;
using System.Collections.Generic;
using System. Linq;
using System. Text;
using System.Threading.Tasks;
namespace Планиметрия
{
class Polygon
{
Point[] mas;
int size;
public Polygon (int size)
{
mas = new Point[size];
this.size = size;
}
public Point this[int i]
{
get
{
return mas[i];
}
set
{
mas[i] = value;
}
}
public void Input_peaks ()
{
for (int i = 0; i < size; i++)
{
mas[i] = new Point ();
Console.WriteLine («Введите координаты {0} вершины: «, i+1);
mas[i]. Input_Point ();
}
}
public void List_Input_peaks (List list)
{
for (int i = 0; i < list. Count; i++)
{
mas[i] = list[i];
}
}
public void Show_peaks ()
{
for (int i = 0; i < size; i++)
{
Console.Write («Вершина {0}: «,(i + 1));
mas[i]. Show ();
}
}
public static bool Is_convex (Polygon Ob)
{
double D = 0;
int count1 = 0, count2 = 0;
int j = 0;
for (int i = 0; i
{
j = i + 1;
for (int k = 0; k < Ob. size; k++)
{
if (k≠i && k≠j)
{
D = (Ob.mas[k]. koord_x — Ob. mas[i]. koord_x) * (Ob.mas[j]. koord_y — Ob. mas[i]. koord_y) — (Ob.mas[k]. koord_y — Ob. mas[i]. koord_y) * (Ob.mas[j]. koord_x — Ob. mas[i]. koord_x);
if (D == 0)
return false;
else
if (D < 0)
count1++;
else
count2++;
}
}
if (count1 ≠ 0 && count2 ≠ 0)
return false;
}
return true;
}
public static bool Intersection1(Polygon Ob1, Polygon Ob2) // true — пересекаются, false — не пересекаются
{
int j = 0, n = 0;
for (int i = 0; i < Ob1.size; i++)
{
j = i == Ob1.size — 1? 0: i + 1;
Otrezok Otr = new Otrezok (Ob1[i], Ob1[j]);
for (int k = 0; k < Ob2.size — 1; k++)
{
n = k == Ob2.size — 1? 0: k + 1;
if (Otrezok.Intersection (Otr, new Otrezok (Ob2[k], Ob2[n])))
return true;
}
}
return false;
}
public static Polygon Intersection (Polygon Ob1, Polygon Ob2)
{
List mas_T1 = Polygon. Contains_T (Ob1, Ob2);
List mas_T2 = Polygon. Intersection_T (Ob1, Ob2);
List mas_T3 = Polygon. Contains_T (Ob2, Ob1);
var mas_T = mas_T1.Concat (mas_T2);
mas_T = mas_T.Concat (mas_T3);
List result_mas = mas_T.ToList ();
result_mas = Polygon. List_Unique (result_mas);
Polygon P = new Polygon (result_mas.Count);
P.List_Input_peaks (result_mas);
return P;
}
public static Polygon Union (Polygon Ob1, Polygon Ob2)
{
List mas_T1 = new List ();
List mas_T2 = new List ();
for (int i = 0; i < Ob1.size; i++)
mas_T1.Add (Ob1[i]);
for (int i = 0; i < Ob2.size; i++)
mas_T2.Add (Ob2[i]);
List mas_T3 = Polygon. Intersection_T (Ob1, Ob2);
var mas_T = mas_T1.Concat (mas_T2);
mas_T = mas_T.Concat (mas_T3);
List mas_T_result = mas_T.ToList ();
List mas_remove1 = Polygon. Contains_T (Ob1, Ob2);
List mas_remove2 = Polygon. Contains_T (Ob2, Ob1);
var mas_remove = mas_remove1.Concat (mas_remove2);
List mas_remove_result = mas_remove.ToList ();
for (int i = 0; i < mas_remove_result.Count; i++)
mas_T_result.Remove (mas_remove_result[i]);
mas_T_result = Polygon. List_Unique (mas_T_result);
Polygon P = new Polygon (mas_T_result.Count);
P.List_Input_peaks (mas_T_result);
return P;
}
public static List Contains_T (Polygon Ob1, Polygon Ob2) // возвращает вершины многоугольника Ob1, которые лежат в Ob2
{
List mas_T = new List ();
int count_tmp = 0, k = 0;
for (int i = 0; i < Ob1.size; i++)
{
count_tmp = 0;
double max_x = Polygon. max_abs (Ob2).koord_x;
Point T1 = Ob1[i];
Point T2;
for (int j = 0; j < Ob2.size; j++)
{
k = j == Ob2.size — 1? 0: j + 1;
Otrezok Otr2 = new Otrezok (Ob2[j], Ob2[k]);
if (T1.koord_y == Otr2.Get_A.koord_y)
T2 = new Point (max_x + 1, Otr2.Get_A.koord_y — 1);
else
if (T1.koord_y == Otr2.Get_B.koord_y)
T2 = new Point (max_x + 1, Otr2.Get_B.koord_y — 1);
else
T2 = new Point (max_x + 1, T1.koord_y);
Otrezok Otr1 = new Otrezok (T1, T2);
if (Otrezok.Intersection (Otr1, Otr2))
count_tmp++;
}
if (count_tmp % 2 ≠ 0)
mas_T.Add (T1);
}
return mas_T;
}
public static List Intersection_T (Polygon Ob1, Polygon Ob2)
{
List mas_T = new List ();
int j = 0, n = 0;
double x, y;
double A1, B1, C1, A2, B2, C2;
for (int i = 0; i < Ob1.size; i++)
{
j = i == Ob1.size — 1? 0: i + 1;
Otrezok Otr = new Otrezok (Ob1[i], Ob1[j]);
for (int k = 0; k < Ob2.size; k++)
{
n = k == Ob2.size — 1? 0: k + 1;
if (Otrezok.Intersection (Otr, new Otrezok (Ob2[k], Ob2[n])))
{
Prjamaja Pr1 = new Prjamaja (Otr.Get_A, Otr. Get_B);
Prjamaja Pr2 = new Prjamaja (Ob2[k], Ob2[n]);
A1 = Pr1.koef_a;
B1 = Pr1.koef_b;
C1 = Pr1.koef_c;
A2 = Pr2.koef_a;
B2 = Pr2.koef_b;
C2 = Pr2.koef_c;
x = (C2 * B1 — C1 * B2) / (A1 * B2 — B1 * A2);
y = (C1 * A2 — A1 * C2) / (A1 * B2 — B1 * A2);
mas_T.Add (new Point (x, y));
}
}
}
return mas_T;
}
public static bool Contains (Polygon Ob1, Polygon Ob2) // true — Ob1 содержится в Ob2, false — Ob1 не содержится в Ob2
{
if (Polygon.Intersection1(Ob1, Ob2))
return false;
int count_tmp = 0, k = 0, count = 0;
for (int i = 0; i < Ob1.size; i++)
{
count_tmp = 0;
double max_y = Polygon. max_abs (Ob2).koord_y;
double max_x = Polygon. max_abs (Ob2).koord_x;
Point T1 = Ob1[i];
Point T2;
if (T1.koord_y == max_y)
T2 = new Point (max_x + 1, max_y — 1);
else
T2 = new Point (max_x + 1, max_y);
Otrezok Otr1 = new Otrezok (T1, T2);
for (int j = 0; j < Ob2.size — 1; j++)
{
k = j + 1;
Otrezok Otr2 = new Otrezok (Ob2[j], Ob2[k]);
if (Otrezok.Intersection (Otr1, Otr2))
count_tmp++;
}
if (count_tmp % 2 ≠ 0)
count++;
}
if (count == Ob1.size)
return true;
else
return false;
}
private static Point max_abs (Polygon P)
{
double max = P[0]. koord_x;
int index = 0;
for (int i = 1; i < P. size; i++)
{
if (P[i]. koord_x > max)
{
max = P[i]. koord_x;
index = i;
}
}
return P[index];
}
private static List List_Unique (List temp_list)
{
List list = new List ();
list.Add (temp_list[0]);
bool flag = true;
for (int i = 1; i < temp_list.Count; i++)
{
flag = true;
for (int j = 0; j < list. Count; j++)
{
if (list[j]. koord_x == temp_list[i]. koord_x && list[j]. koord_y == temp_list[i]. koord_y)
{
flag = false;
break;
}
}
if (flag)
list.Add (temp_list[i]);
}
return list;
}
}
}
Класс Triangle
using System;
using System.Collections.Generic;
using System. Text;
namespace Планиметрия
{
class Triangle: Point
{
Point B = new Point ();
Point C = new Point ();
// Конструкторы:
public Triangle ()
{
//Console.WriteLine («Работает конструктор класса Triangle без параметров»);
reality = false;
///////reality отвечает за существование объекта
}
public Triangle (Point T1, Point T2, Point T3)
: base (T1)
{
//Console.WriteLine («Работает конструктор класса Triangle с 3-мя параметрами»);
B = T2;
C = T3;
if (T1 ≠ T2 && T2 ≠ T3 && T1 ≠ T3 && Storona_a + Storona_b > Storona_c && Storona_a + Storona_c > Storona_b && Storona_b + Storona_c > Storona_a)
reality = true;
else
reality = false;
}
// Конструктор копирования
public Triangle (Triangle Ob)
{
//Console.WriteLine («Работает конструктор-копировщик класса Triangle»);
this.FigureSizes[0] = Ob. FigureSizes[0];
this.FigureSizes[1] = Ob. FigureSizes[1];
///// FigureSizes[0] берется из базового класса, т. к тут только 2е точки есть
B = Ob. B;
C = Ob. C;
reality = Ob. reality;
}
// переопределение методов базового класса
// Безопасный код! Если треугольник не существует, его периметр и площадь равны 0.
public override double Perimetr ()
{
if (this.reality == false) return 0;
return Storona_a + Storona_b + Storona_c;
}
public override double area ()
{
if (this.reality == false) return 0;
double p = this. Perimetr () / 2;
return Math. Sqrt (p * (p — Storona_a) * (p — Storona_b) * (p — Storona_c));
}
public string Style1()
{
if ((Storona_a ≠ Storona_b) && (Storona_b ≠ Storona_c) && (Storona_a ≠ Storona_c))
return «Разносторонний» ;
else
if ((Storona_a == Storona_b) && (Storona_b == Storona_c))
return «Равностороний» ;
else
return «Равнобедренный» ;
}
public string Style2()
double a = Storona_a;
double b = Storona_b;
double c = Storona_c;
if ((Math.Pow (a, 2) + Math. Pow (b, 2) > Math. Pow (c, 2) — 0.001 && Math. Pow (a, 2) + Math. Pow (b, 2) < Math. Pow (c, 2) + 0.001)
public bool Is_Triangle
{
get
{
return reality;
}
}
public void Show_Triangle ()
{
Console.WriteLine («Сторона a={0:#.##}, сторона b={1:#.##}, сторона c={2:#.##}», Storona_a, Storona_b, Storona_c);
}
public double Storona_a
{
get
{
Point A = new Point (FigureSizes[0], FigureSizes[1]);
return new Otrezok (A, B).Perimetr ();
}
/////set нету т. к фигуру изсенить нельзя
}
public double Storona_b
{
get { return new Otrezok (C, B).Perimetr (); }
}
public double Storona_c
{
get
{
Point A = new Point (FigureSizes[0], FigureSizes[1]);
return new Otrezok (A, C).Perimetr ();
}
}
}
}
Класс Program
using System;
using System.Collections.Generic;
using System. Text;
namespace Планиметрия
{
class Program
{
static void Main (string[] args)
{
int size1, size2;
Console.WriteLine («Введите количество вершин в первом многоугольнике:»);
size1 = Convert. ToInt32(Console.ReadLine ());
Console.WriteLine («Введите количество вершин во втором многоугольнике:»);
size2 = Convert. ToInt32(Console.ReadLine ());
Polygon P1 = new Polygon (size1);
Polygon P2 = new Polygon (size2);
Console.WriteLine («Введите координаты вершин первого многоугольника:»);
P1.Input_peaks ();
Console.WriteLine («Введите координаты вершин второго многоугольника:»);
P2.Input_peaks ();
Console.Clear ();
Console.WriteLine («Координаты вершин первого многоугольника:»);
P1.Show_peaks ();
Console.WriteLine («Координаты вершин второго многоугольника:»);
P2.Show_peaks ();
if (!Polygon.Is_convex (P1) || !Polygon.Is_convex (P2))
{
Console.WriteLine («Один из многоугольников не является выпуклым!»);
}
else
{
Polygon P_I = Polygon. Intersection (P1, P2);
Console.WriteLine («Пересечение:»);
P_I.Show_peaks ();
Polygon P_U = Polygon. Union (P1, P2);
Console.WriteLine («Объединение:»);
P_U.Show_peaks ();
}
Console.ReadKey ();
}
}
}
Класс Prjamaja
using System;
using System.Collections.Generic;
using System. Text;
namespace Планиметрия
{
class Prjamaja: Figure
{
///Конструкторы////
public Prjamaja ()
{
FigureSizes = new double[3];
reality = false;
FigureSizes[0] = 0;
FigureSizes[1] = 0;
FigureSizes[2] = 0;
}
public Prjamaja (Point A, Point B)
{
FigureSizes = new double[3];
if (A == B)
{
reality = false;
FigureSizes[0] = 0;
FigureSizes[1] = 0;
FigureSizes[2] = 0;
}
else
{
reality = true;
FigureSizes[0] = B. koord_y — A. koord_y;
FigureSizes[1] = A. koord_x — B. koord_x;
FigureSizes[2] = B. koord_x * A. koord_y — A. koord_x * B. koord_y;
}
}
///////Свойства/////////
public double koef_a
{
get { return FigureSizes[0]; }
}
public double koef_b
{
get { return FigureSizes[1]; }
}
public double koef_c
{
get { return FigureSizes[2]; }
}
public bool Is_prjamaja
{
get { return reality; }
}
}
}
Класс Point
using System;
using System.Collections.Generic;
using System. Text;
namespace Планиметрия
{
class Point: Figure
{
// Конструкторы:
public Point ()
{
reality = true;
FigureSizes = new double[2];
FigureSizes[0] = 0;
FigureSizes[1] = 0;
}
public Point (Point Ob)
{
reality = true;
FigureSizes = new double[2];
FigureSizes[0] = Ob. FigureSizes[0];
FigureSizes[1] = Ob. FigureSizes[1];
}
public Point (double x, double y)
{
reality = true;
FigureSizes = new double[2];
FigureSizes[0] = x;
FigureSizes[1] = y;
}
// Свойства:
public double koord_x
{
get
{
return FigureSizes[0];
}
set
{
FigureSizes[0] = value;
}
}
public double koord_y
{
get
{
return FigureSizes[1];
}
set
{
FigureSizes[1] = value;
}
}
public void Show ()
{
Console.WriteLine («x = {0:0.##}, y = {1:0.##}» ,
FigureSizes[0], FigureSizes[1]);
}
public void Input_Point ()
{
Console.Write («Координата x = «);
FigureSizes[0] = Double. Parse (Console.ReadLine ());
Console.Write («Координата y = «);
FigureSizes[1] = Double. Parse (Console.ReadLine ());
}
}
}
Класс Otrezok
using System;
using System.Collections.Generic;
using System. Text;
namespace Планиметрия
{
class Otrezok: Point
{
Point B = new Point ();
public Otrezok ()
{
reality = false;
}
public Otrezok (Point Ob1, Point Ob2):base (Ob1)
{
if (Ob1 ≠ Ob2)
reality = true;
else reality = false;
B = Ob2;
}
public Point Get_A
{
get { return this; }
}
public Point Get_B
{
get { return B; }
}
//Свойство
public bool Is_Otrezok
{
get { return reality; }
}
public override double Perimetr ()
{
return Math. Sqrt (Math.Pow (B.koord_x — this. koord_x, 2) + Math. Pow (B.koord_y — this. koord_y, 2));
}
public static bool Intersection (Otrezok Otr1, Otrezok Otr2)
{
bool flag = true;
double x1, y1, x2, y2, x3, y3, x4, y4;
x1 = Otr1.Get_A.koord_x;
y1 = Otr1.Get_A.koord_y;
x2 = Otr1.Get_B.koord_x;
y2 = Otr1.Get_B.koord_y;
x3 = Otr2.Get_A.koord_x;
y3 = Otr2.Get_A.koord_y;
x4 = Otr2.Get_B.koord_x;
y4 = Otr2.Get_B.koord_y;
double Z1 = (x3 — x1) * (y2 — y1) — (y3 — y1) * (x2 — x1);
double Z2 = (x4 — x1) * (y2 — y1) — (y4 — y1) * (x2 — x1);
if (Z1 * Z2 > 0)
flag = false;
double Z3 = (x1 — x3) * (y4 — y3) — (y1 — y3) * (x4 — x3);
double Z4 = (x2 — x3) * (y4 — y3) — (y2 — y3) * (x4 — x3);
if (Z3 * Z4 > 0)
flag = false;
if (Z1 == 0 && Z2 == 0)
{
flag = false;
if (y1 == y3 && y2 == y4)
{
double k1 = Otrezok. min (x1, x2);
double k2 = Otrezok. max (x1, x2);
double k3 = Otrezok. min (x3, x4);
double k4 = Otrezok. max (x3, x4);
double L_x = Otrezok. max (k1, k3);
double R_x = Otrezok. min (k2, k4);
if (L_x <= R_x)
flag = true;
}
else
{
double k5 = Otrezok. min (y1, y2);
double k6 = Otrezok. max (y1, y2);
double k7 = Otrezok. min (y3, y4);
double k8 = Otrezok. max (y3, y4);
double L_y = Otrezok. max (k5, k7);
double R_y = Otrezok. min (k6, k8);
if (L_y <= R_y)
flag = true;
}
}
return flag;
}
private static double min (double x, double y)
{
return x < y? x: y;
}
private static double max (double x, double y)
{
return x > y? x: y;
}
}
}
Класс Figure
using System;
using System.Collections.Generic;
using System. Text;
namespace Планиметрия
{
abstract class Figure
{
protected double [] FigureSizes;
protected bool reality;
public virtual double area ()
{
return 0.0;
}
public virtual double Perimetr ()
{
return 0.0;
}
}
}
ГЛАВА 3. Тесты для проверки работы программы
1). Проверить, если первый многоугольник находиться внутри второго многоугольника и его вершины принадлежат сторонам второго.
В B1 С
A1 C1
А D1 D
A (2,2); B (2,6); C (6,6); D (6,2); A1(2,4); B1(4,6); C1(6,4); D1(4,2)
2). Проверить, если один многоугольник находится внутри другого.
С D
В E
А F
Q G
A (2,4); B (2,6); C (4,8); D (6,8); E (8,6); F (8,4); G (6,2); Q (4,2); A1(4,4);B1(4,6);C1(6,6);D1(6,4).
3). Проверить, если они не пересекаются.
B1 C1
B C
A D A1 D1
A (1,1); B (1,3); C (3,3); D (3,1), A1(4,1); B1(4,4); C1(6,4);D1(6,1)
ГЛАВА 4. Графическая иллюстрация решения задачи
C1
B D1
D
C1
B D1
D
ЗАКЛЮЧЕНИЕ
программа решение задача многоугольник При выполнении настоящей курсовой работы были освоены основные принципы разработки алгоритмов и программ. При написании перед нами была поставлена цель: изучить основы вычислительной геометрии и разработать программу решения задачи с геометрическим содержанием.
Чтобы реализовать цель, мы выбрали задачу «О пересечении выпуклых многоугольников» и изучили суть вычислительной геометрии и способы алгоритмизации.
В процессе решения поставленных задач курсовой работы использовались прикладные системы программирования и необходимые методы решения заданий.
Иинструментальной средой разработки программ стала MS Visual Studio 2010.
СПИСОК ИСПОЛЬЗУЕМОЙ ЛИТЕРАТУРЫ
1. Котов В. М. Информатика. алгоритмизации. Учебное пособие 9 класса.
2.Андреева Е. В. Вычислительная геометрия на плоскости.
3. Голицина О. Л., Попов И. И. Основы алгоритмизации и программирования: Учебное пособие.