Elementarne geometrijske metode

Preview:

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)

• 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