#include <graphics.h>
#include <conio.h>
#include <math.h>
#include <stdio.h>
#include <iostreame.h>
#include <mmouse.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <dos.h>
struct coor
{int x,y;}
*m;
void initmouse(void)
{
asm xor ax,ax
asm xor bx,bx
asm int 0x33
}
void show_cur(int i)
{
union REGS r;
r.h.ah=0;
r.h.al=i;
int86(0x33,&r,&r);
}
int mouse_mode(void)
{
asm mov ax,3
asm int 0x33
return _BL;
}
void get_xy(void)
{
asm mov ax,3
asm int 0x33
m->x=_CX;
m->y=_DX;
}
#define PI 3.14159
struct Point // класс точки
{
double x,y; // координаты точки
int code(Point q); // код четверти, в которой лежит точка q
double operator*(Point q);// векторное произведение
Point operator-(Point q); // разность векторов
};
Point ctop(void)//преобразование координаты мыши в координаты точки
{
Point p;
p.x=m->x-250;
p.y=m->y-250;
return p;
}
int Point::code(Point q) // код четверти, в которой лежит точка q
{ // начало координат находится в точке (x,y)
if (q.x-x>=0 && q.y-y>=0) return 0;
if (q.x-x< 0 && q.y-y>=0) return 1;
if (q.x-x>=0 && q.y-y< 0) return 3;
if (q.x-x< 0 && q.y-y< 0) return 2;
}
double Point::operator*(Point q)
{
return x*q.y-y*q.x; // векторное произведение
}
Point Point::operator-(Point q) // разность векторов
{
Point t; t.x=x-q.x; t.y=y-q.y; return t;
}
int operator <(Point p, Point q)
{
Point t; // сравнение углов радиус-векторов p и q
t.x=0; t.y=0; // коды четвертей вычисляются относительно (0,0)
if(t.code(p)<t.code(q)) return 1;
if(t.code(p)>t.code(q)) return 0;
return (p*q>0); // вращение от p к q направлено против часовой стрелки
}
class Domain // абстрактный класс области
{
protected:
int color; // цвет области
int n; // количество сторон
public:
virtual int isin(Point p)=0; // функция принадлежности
Domain(int c=15): color(c){} // конструктор
void show();// функция вывода области
void change(int k, int l);//функция преобразования
};
void Domain::show()
{
int ix, iy; Point q;Point g;Point f;
for (iy=0; iy<=getmaxy(); iy++)
for (ix=0; ix<=getmaxx(); ix++)
{
q.x = ix-250;
q.y = iy-250;
if (isin(q)) putpixel(ix,iy, color);
}
}
void Domain::change(int k, int l)
{
int ix, iy; Point q;
for (iy=0; iy<=getmaxy(); iy++)
for (ix=0; ix<=getmaxx(); ix++)
{
q.x = (ix-250)-k;
q.y = (iy-250)+l;
if (isin(q)) putpixel(ix,iy, color);
}
}
//класс многоугольника
class Polygon: virtual public Domain
{
protected:
Point *p;
public:
Polygon(){n=0;}
Polygon(double *x, double *y, int num, int cl);
int isin(Point t);
};
Polygon::Polygon(double *x, double *y, int num, int cl):Domain(cl)
{
int i; n = num; p= new Point [num];
for (i=0; i<n; i++)
{
p[i].x=x[i]; p[i].y=y[i];
}
}
int Polygon::isin(Point t) // тест на принадлежность методом углов
{
int i, ind=0;
Point q = p[n-1];
for (i=0; i<n; i++)
{
if (t.code(q)==t.code(p[i]));
else if ((t.code(p[i])-t.code(q)-1)%4==0) ind++;
else if ((t.code(p[i])-t.code(q)+1)%4==0) ind--;
else if ((p[i]-q)*(t-q)>0) ind+=2;
else ind-=2;
q = p[i];
}
ind = ind/4;
if (ind==0) return 0; else return 1;
}
//класс звездчатого полигона
class SPolygon: public Polygon
{
protected:
Point pC;
public:
SPolygon(){} // конструктор по умолчанию
SPolygon(double *x, double *y, int m, int cl);
};
SPolygon::SPolygon(double *x, double *y, int m, int cl):Domain(cl)
{
int i,j;
Point t;
p= new Point [m]; n=m;
pC.x=0; pC.y=0;
for(i=0;i<m;i++)
{
pC.x+=x[i]; pC.y+=y[i];
}
pC.x= pC.x/m; pC.y= pC.y/m;
setcolor(YELLOW);
for(i=0;i<m;i++)
{
p[i].x=x[i]; p[i].y=y[i];
circle(p[i].x+250,p[i].y+250,2);
}
//Сортируем точки по возрастанию угла вокруг центра тяжести методом вставок
for(i=1; i<m; i++)
{
t = p[i];
for (j=i-1; (j>=0) && ((t-pC)<(p[j]-pC)); j--)
p[j+1] = p[j];
p[j+1]=t;
}
for (i=0;i<m-1;i++)
{
line(p[i].x+250, p[i].y+250,p[i+1].x+250, p[i+1].y+250);
line(p[m-1].x+250, p[m-1].y+250,p[0].x+250, p[0].y+250 );
}
}
Point tt;
int main()
{
double rad=150, x[10], y[10];//радиус окружности и вершины пятиугольник
int i,n;
clrscr();
cout<<"Введите количество углов (от 3 до 15) ";
cin>>n;
if(n<3||n>15) exit(1);
for(i=0;i<5;i++)
{
// вершины большого пятиугольник
x[i] = rad*cos(2*PI*i/5);
y[i] = rad*sin(2*PI*i/5);
// вершины маленького пятиугольник
x[i+5] = rad*cos(2*PI*i/5+PI/5)/2;
y[i+5] = rad*sin(2*PI*i/5+PI/5)/2;
}
randomize();
for(i=0;i<10;i++)
{x[i]+=(random(100));}
int gm, gd=DETECT;
initgraph(&gd, &gm, "..\\bgi"); // инициализация графики
SPolygon dom(x,y,n,LIGHTRED); // построение звездчатого по-лигон
dom.show(); // вывод звездчатого полигон
initmouse();
show_cur(1);
int key;
int k=0,l=0;
while(1)
{
get_xy();
if(kbhit()!=0)//если нажата клавиша - Выход
{
key=getch();
if(key==13||key==27)
{
show_cur(2);
cleardevice();
closegraph();
exit(1);
show_cur(1);
}
}
if(mouse_mode()==2) //если нажата левая кнопка - ввод вектора
{
show_cur(2);
gotoxy(1,1);
cout<<"Vector (X,Y)\n";
cout<<"X=";
cin>>k;
cout<<"Y=";
cin>>l;
cleardevice();
SPolygon dom(x,y,n,LIGHTRED); // построение звездчатого по-лигона
dom.change(k,l);
show_cur(1);
}
get_xy();//получаем координаты
if(mouse_mode()==1)//если нажата правая - проверка на попадание точки
{
get_xy();//получаем координаты
Point q;
tt=ctop();
show_cur(2);
q.x = tt.x-k;
q.y = tt.y+l;
gotoxy(1,1);
if(!dom.isin(q)) {cout<<"Point out Polygon";gotoxy(1,1);}
else {cout<<"Point in Polygon ";gotoxy(1,1);}
show_cur(1);
}
}
getch(); closegraph();
return 0;
}