Nadesłany przez Michał Knasiecki, 03 sierpnia 2005 01:00
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.Pobierz pełne rozwiązanie.
Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.
polygon c++/polygon.cpp:
/*
Algorytm sprawdza, czy punkt p nalezy do wielokata W
Program zostal pobrany ze strony www.algorytm.org
Opracowal: Michal Knasiecki
--------------------------------------------------------
Uwaga:
Daje wejsciowe sa wczytywane z pliku dane.txt
Format zapisu danych wejsciowych znajduje sie w pliku !FormatDatych.txt
*/
#include <conio>
#include <stdio>
#include <stdlib>
//funkcja min
int min(int a, int b)
{
if (a<b) return a;
return b;
}
//funkcja max
int max(int a, int b)
{
if (a>b) return a;
return b;
}
//funkcja signum
int sign(int a)
{
if (a == 0)
return 0;
if (a < 0)
return -1;
return 1;
}
struct vertex //Wierzcholek
{
int x,y;
};
vertex polygon[20]; //Tablica wierzcholow wielokata, max: 20
vertex p; //Dany punkt p
vertex r; //Drugi koniec odcinka |PR|
vertex tmp;
int n=0; //Liczba wierzchalkow wielokata
int k;
//********************************************************
int przynaleznosc(vertex x, vertex y,vertex z)
{
int det;
det=x.x*y.y+y.x*z.y+z.x*x.y-z.x*y.y-x.x*z.y-y.x*x.y;
if (det!=0) return(0); else
{
if ((min(x.x,y.x)<=z.x)&&(z.x<=max(x.x,y.x)) && (min(x.y,y.y)<=z.y)&&(z.y<=max(x.y,y.y)))
return(1); else return(0);
};
};
int det(vertex x,vertex y,vertex z) //Wyznacznik macierzy kwadratowej stopnia 3.
{
return(x.x*y.y+y.x*z.y+z.x*x.y-z.x*y.y-x.x*z.y-y.x*x.y);
}
int przecinanie(vertex a,vertex b)
{
if ((przynaleznosc(p,r,a)==0)&&(przynaleznosc(p,r,b)==0))
{ //pólprosta nie przecina odcinka |AB| w koncach
if ((sign(det(p,r,a)) != sign(det(p,r,b))) &&
(sign(det(a,b,p)) != sign(det(a,b,r)))) return(1); else return(0);
} else //do pólprostej nalezy przynajmniej jeden koniec odcinka |AB|
{
if ((przynaleznosc(p,r,a)==1)&&(przynaleznosc(p,r,b)==1))
{
if ((sign(det(p,r,polygon[(k-1+n)%n])) == sign(det(p,r,polygon[(k+2)%n]))) &&
(sign(det(p,r,polygon[(k-1+n)%n])) != 0)) return(0); else return(1);
} else
if ((przynaleznosc(p,r,polygon[(k-1+n)%n])==1)||(przynaleznosc(p,r,polygon[(k+2)%n])==1)) return(0);
else
{ //polprosta zawiera tylko wierzcholek
if (przynaleznosc(p,r,b)==1)
{
tmp=a;
return(0);
}
if (przynaleznosc(p,r,a)==1)
{
if ((sign(det(p,r,tmp)) == sign(det(p,r,b))) &&
(sign(det(p,r,tmp)) != 0)) return(0); else return(1);
}
}
}
return 0;
}
void oblicz(void)
{
int l=0; //liczba przeciec
int i;
div_t w;
//
for (i=0;i<n;i++)
{
k=i;
if (przynaleznosc(polygon[i], polygon[(i+1)%n], p) == 1)
{
printf("Punkt nalezy do krawedzi wielokata\n");
printf("Dowlony klawisz...");
return;
}
if (przecinanie(polygon[i],polygon[(i+1)%n])==1) l++;
}
printf("Rozwiazanie--------------\n");
printf("Liczba przeciec: %i\n",l);
w=div(l,2);
if (w.rem==0) printf("Punkt p NIE nalezy do wielokata\n"); else
printf("Punkt p nalezy do wielokata\n");
printf("Dowlony klawisz...");
}
void main(void)
{
FILE *plik;
int max_x=0; //Najwieksza rzedna
int j=0; //aktualny index tablicy wierzcholkow
//
clrscr();
printf("Dane wejsciowe:\n");
if ((plik=fopen("dane.txt","r"))==NULL)
{
printf("Plik \"dane.txt\" z danymi wejsciowymi nie istnieje\n");
printf("Dowlony klawisz...");
getch();
} else
{
fscanf(plik,"%i",&p.x);
fscanf(plik,"%i",&p.y);
printf("Punkt p=(%i,%i)\n",p.x,p.y);
do
{
fscanf(plik,"%i",&polygon[j].x);
if (polygon[j].x>max_x) max_x=polygon[j].x;
fscanf(plik,"%i",&polygon[j].y);
j++;
n=j;
printf("Wierzcholek #%i=(%i,%i)\n",j,polygon[j-1].x,polygon[j-1].y);
}
while (!feof(plik));
fclose(plik);
//Wyznaczanie wspólrzednych drugiego konca odcinka
r.x=max_x+1;
r.y=p.y;
//Punkt r na pewno znajduje sie poza wielokatem
printf("Punkt r=(%i,%i)\n",r.x,r.y);
oblicz();
getch();
}
}

