Upload
andres
View
87
Download
1
Embed Size (px)
DESCRIPTION
Strukture podataka i algoritmi. Elementarne geometrijske metode. (Elementary Geometric Methods). Branimir Sigl. Općenito o geometrijskim algoritmima. rješavaju mnoge probleme iz područja matematike i statistike korišteni za razne druge tipove problema - PowerPoint PPT Presentation
Citation preview
Elementarne geometrijske metode
(Elementary Geometric Methods)
Branimir Sigl
Strukture podataka i algoritmi
Općenito o geometrijskim algoritmima
• rješavaju mnoge probleme iz područja matematike i statistike
• korišteni za razne druge tipove problema• npr. “gerrymandering” - podjela okruga na
dijelove sa jednakom populacijom• problemi se lako se vizualiziraju (nedostatak?)• neki problemi su naizgled laki, ali imaju
komplicirane algoritme za rješavanje• Presijecanje, zatvorena petlja, odnos točke i
poligona
Strukture podataka
• točka, linija, poligon class point, class line, class drawing
vector <point> points
• Polygon ==> set of points• Polygon ==> set of lines• Visual Basic / C++ communication DLL
struct vbPoint, vbLine
Strukture podataka
class point {
public:
long x, y;
point() : x(-1), y(-1) { }
point(vbPoint p): x(p.x), y(p.y) { }
point(const point &p): x(p.x), y(p.y) { }
point(long coordX, long coordY): x(coordX), y(coordY) { }
friend ostream& operator <<(ostream& o, const point& p)
{ return o << "(" << p.x << ", " << p.y << ")"; }
operator vbPoint();
point operator =(const point &p);
bool operator ==(const point &p) const;
bool operator <(const point &p) const;
};
• osnovni problem - presjek linija
Međusobno presijecanje linija
• METODA 1:– pronaći točku presijecanja– provjeriti je li točka između krajnjih točaka linija
• METODA 2:• ccw - counterclockwise
long intersect::ccw (point p0, point p1, point p2) {
Međusobno presijecanje linija (ccw)
• ako je nagib druge linije veći suprotno kazaljci na satu (ccw)
• ako je nagib druge linije manji kao kazaljka na satu (cw)
p0
p2p1
p2’
• vrijednosti funkcije ccw:– true suprotno kazaljci (ccw)– false u smjeru kazaljke (cw)
• problem: linije mogu biti kolinearne• ako su točke kolinearne, onda ne možemo
definirati cw/ccw– 1 1 između 0 i 2– -1 0 između 1 i 2– 0 2 između 0 i 1
Međusobno presijecanje linija (ccw)
long intersect::ccw (point p0, point p1, point p2) {long dx1, dy1, dx2, dy2;
dx1 = p1.x - p0.x; dy1 = p1.y - p0.y;dx2 = p2.x - p0.x; dy2 = p2.y - p0.y;
if (dx1 * dy2 > dy1 * dx2) return 1;if (dx1 * dy2 < dy1 * dx2) return -1;
if ((dx1 * dx2 < 0) || (dy1 * dy2 < 0)) return -1; // 0if ((dx1 * dx1 + dy1 * dy1) < (dx2 * dx2 + dy2 * dy2)) // 1
return 1;return 0; // 2
}
Međusobno presijecanje linija (ccw)
• Numeričke komplikacije:• Umnošci:
long dx1, dx2, dy1, dy2;
dx1 * dy2; dy1 * dx2; dx1 * dx2; dy1 * dy2
• umnožak dvije long varijable je long varijabla - PROBLEM !!• ako je jedan od faktora LONG_MAX tada umnožak nije dobar• problem se pojavljuje kod algoritma ”Odnos točke i poligona”• potrebno je odrediti dovoljno velik broj ?! npr. SHRT_MAX
koji ne stvara preljev kod umnoška dva long broja
Međusobno presijecanje linija (ccw)
• algoritam INTERSECT:
• ako su točke na suprotnim stranama linije, tada se linije sijeku
Međusobno presijecanje linija (intersect)
A D
C B
• algoritam INTERSECT:
• ako su točke na suprotnim stranama linije, tada se linije sijeku
Međusobno presijecanje linija (intersect)
A D
C B
Sedgewick:
bool intersect::operator () (line l1, line l2) {
return ( ( ccw(l1.p1, l1.p2, l2.p1) *
ccw(l1.p1, l1.p2, l2.p2) <= 0 )
&& ( ccw(l2.p1, l2.p2, l1.p1) *
ccw(l2.p1, l2.p2, l1.p2) <= 0 )) ;
Međusobno presijecanje linija
• algoritam nije u potpunosti točan• kada je točka T2 kolinearna sa točkama T0
i T1 rezultat funckije ccw = 0• Potrebne promjene Sedgewick-ovog
algoritma• Dovoljno je da jedna od četiri kombinacije
bude jednaka nuli, tada je sigurno da se linije sijeku
Međusobno presijecanje linija
Nakon izmjena:
bool intersect::operator () (line l1, line l2) {
c11 = ccw(l1.p1, l1.p2, l2.p1);
c12 = ccw(l1.p1, l1.p2, l2.p2);
c21 = ccw(l2.p1, l2.p2, l1.p1);
c22 = ccw(l2.p1, l2.p2, l1.p2);
return (( c11 * c12 < 0 ) && ( c21 * c22 < 0 )) ||
c11 * c12 * c21 * c22 == 0 ;
Međusobno presijecanje linija (promjene)
• PROBLEM: • pronaći put kroz sve točke, bez presijecanja i
vratiti se u početnu točku (Simple Closed Path)• točke = gradovi, kuće?• Travelling Salesman Problem - pronalazak
najboljeg puta - puno kompliciraniji• rješenje našeg problema:
– pronaći “SIDRO”– izračunati kuteve prema ostalim točkama– sortirati niz kuteva
Jednostavna zatvorena petlja
Jednostavna zatvorena petlja
sidro (anchor) ?
• kut koji je potreban za algoritam : tan-1 dy/dx• korištenje funkcije tan-1 nije isplativo:
– dx != 0– ispitivanje kvadranta
• potrebno je pronaći sličnu funkciju• dy / (dx + dy) uz mala poboljšanja• u nekim programskim okruženjima bolje je
koristiti trigonometrijske funkcije
Jednostavna zatvorena petlja
typedef multimap <float, point, less<float> > MAPPOINT;
typedef MAPPOINT::value_type PATHPAIR;
PATHPAIR theta::operator ()( point p2) {
long dx, dy, ax, ay;
float t;
dx = p2.x - p1.x; dy = p2.y - p1.y;
ax = abs(dx); ay = abs(dy);
t = (ax + ay == 0) ? 0. : (float) dy / (ax + ay);
if (dx < 0)
t = 2. - t;
else if (dy < 0)
t = 4. + t;
return PATHPAIR(t * 90., p2);
}
Jednostavna zatvorena petlja
typedef set<point, less<point> > SETPOINT;
vector<vbPoint> drawing::calcPath() {
SETPOINT tmp;
MAPPOINT path;
vector<vbPoint> r ;
. . . .
theta tht(*tmp.begin());
iS = tmp.begin();
while(iS != tmp.end()) {
path.insert( tht(*iS) );
iS++;
}
. . . .
return r;
}
Jednostavna zatvorena petlja
Jednostavna zatvorena petlja
sidro (anchor)
0°
• PROBLEM:• odrediti je li zadana točka izvan ili unutar
poligona?• RJEŠENJE:• povući dovoljno dugačku liniju iz točke u bilo
kojem pravcu• prebrojati linije poligona s kojima se sječe• PARAN BROJ sjecišta - točka IZVAN POLIGONA• NEPARAN BROJ sjecišta - točka UNUTAR
POLIGONA• izgleda jednostavno? nije baš . . . . .
Odnos točke i poligona
• Sjecišta na rubovima• Paralelne linije
Odnos točke i poligona
• algoritam:• putujemo po točkama poligona• inkrementiramo brojač svaki put kada testna
linija presječe liniju poligona• ako je broj presijecanja paran, točka je IZVAN• ako je broj presijecanja neparan, točka je UNUTAR• ignoriramo točke koje padaju na testnu liniju
Odnos točke i poligona
long drawing::inside(point t, vbPoint ap[ARRAYSIZE]) {
line lp, lt(t, t);
lt.p2.x = MAX_SHRT; // problem u ccw algoritmu
. . . .
tmp.insert(tmp.begin(), *tmp.rbegin()); // p[0] = p[N]
tmp.push_back(tmp[1]); // p[N+1] = p[1]
for(i = 1; i <= N; i++) {
lp.p1 = tmp[i]; lp.p2 = tmp[i];
if (!intersection(lp, lt);) {
lp.p2 = tmp[j];
j = i;
if (intersection(lp, lt))
count++;
}
}
return count & 1;
Odnos točke i poligona
• Algoritam nije u potpunosti točan– ako točka leži na bridu, da li je unutar / izvan poligona ?– problem sa ignoriranjem točke na testnoj liniji– problem zbog nekontroliranja nulte (n-te) točke
• Problem 1:• ako se točka nalazi na bridu poligona, točka je UNUTAR
Odnos točke i poligona ( problem 1 )
A B
CDT1
Prema Sedgewickovom algoritmu, točka T1 se nalazi unutar poligona, a točka T2 se ne nalaziT2
• Problem 2:
• algoritam pamti vrijednost j koja se ne nalazi na testnoj liniji i slijedeću točku i koja nije na testnoj liniji
• Ako se točke p[i] i p[j] nalaze sa suprotnih strana testne linije => counter se povećava za jedan
Odnos točke i poligona ( problem 2 )
A = p[i]
B
C = p[j]D
T
Prema Sedgewickovom algoritmu, točka T se ne bi nalazila unutar poligona
• Problem 3:
• algoritam počinje provjeru sa segmentom p[0]p[1], ali ne provjerava da li se točka p[0] nalazi na testnoj liniji
• Točku p[N] algoritam ne tretira jer se nalazi na testnom segmentu ==> potrebno je smanjiti counter za jedan
Odnos točke i poligona ( problem 3 )
A = p[1]
CD = p[0] = p[N]T
Prema Sedgewickovom algoritmu, točka T se ne bi nalazila unutar poligona
. . . .
for(i = 1; i <= N; i++) {
lp.p1 = tmp[i];
/*NEW*/ lp.p2 = tmp[i-1];
/*NEW*/ b = intersect(lv, lp);
/*NEW*/ if (b)
/*NEW*/ return true;
lp.p2 = tmp[i];
b = intersect(lp, lt);
if (!b) {
. . . .
Odnos točke i poligona ( promjena 1 )
. . . .
b = intersect(lp, lt);
if(b) {
count++;
/*NEW*/ } else {
/*NEW*/ if ( (i!=j+1) &&
/*NEW*/ (intersect(lt.p1, lt.p2, tmp[j]) *
/*NEW*/ intersect(lt.p1, lt.p2, tmp[i]) < 1) )
/*NEW*/ count++;
/*NEW*/ }
j = i;
. . . .
Odnos točke i poligona ( promjena 2 )
. . . .
/*NEW*/ if( (j!=N) &&
/*NEW*/ (intersect(lt.p1, lt.p2, tmp[j]) *
/*NEW*/ intersect(lt.p1, lt.p2, tmp[1]) == 1) )
/*NEW*/ count--;
return count & 1;
}
Odnos točke i poligona ( promjena 3 )
Odnos točke i poligona
sidro(anchor)
• podcjenjivanje složenosti geometrijskih algoritama
• koriste se u razne druge svrhe• mnogi geometrijski algoritmi ovdje nisu niti
spomenuti• jednostavan alat, uvod u složenije algoritme• C++ je dobar za ilustraciju danih algoritama,
strukture podataka lako se prikazuju u C++• tekstovi o C++ često se koriste geometrijskim
algoritmima u pokazivanju svojih mogućnosti
Zaključak
• LINKOVI:
http://condor.informatik.uni-oldenburg.de/ ~stueker/graphic/
http://www.enseignement.polytechnique.fr/profs/ informatique/Jean-Jacques.Levy/00/pc10/a10.html
http://www.cs.princeton.edu/courses/archive/ spring02/cs226/lectures/geo.4up.pdf
http://www.cee.hw.ac.uk/~alison/ds98/node111.html
http://m3.polymtl.ca/ele6813/notes/chap7/chap7.html