Wektor
Transkrypt
Wektor
Przykład implementacji przeciaże ˛ ń operatorów – problem kolizji Bogdan Kreczmer ZPCiR IIAiR PWr pokój 307 budynek C3 [email protected] c 2005–2008 Bogdan Kreczmer⋆ Copyright ⋆ Niniejszy dokument zawiera materiały do wykładu na temat programowania obiektowego. Jest on udostepniony ˛ pod warun- kiem wykorzystania wyłacznie ˛ do własnych prywatnych potrzeb i może on być kopiowany wyłacznie ˛ w całości, razem z niniejsza˛ strona˛ tytułowa. ˛ Opis problemu: Zaimplementować procedure˛ obliczeniowa˛ umożliwiajac ˛ a˛ stwierdzenie, czy dla dwóch platform mobilnych poruszajacych ˛ sie˛ wzdłuż prostej ruchem jednostajnym zachodzi kolizja. Zakładamy, że kolizja zachodzi jeśli jakaś przeszkoda znajdzie sie˛ w obrebie ˛ okregu ˛ opisanego na rzucie pionowym korpusu platformy. Platforma mobilna 1 Platforma mobilna 2 1 Analiza problemu Zaimplementować procedure˛ obliczeniowa˛ umożliwiajac ˛ a˛ stwierdzenie, czy dla dwóch platform mobilnych poruszajacych ˛ sie˛ wzdłuż prostej ruchem jednostajnym zachodzi kolizja. Zakładamy, że kolizja zachodzi jeśli jakaś przeszkoda znajdzie sie˛ w obrebie ˛ okregu ˛ opisanego na rzucie pionowym korpusu platformy. Kluczowe rzeczowniki: Własności: Relacje: • platforma ( mobilna ) • ruch • kolizyjność • położenie • rozmiar 2 Rozwiazanie ˛ w globalnym układzie współrzednych ˛ Rozwiazaniem ˛ problemu jest wyznaczenie najmniejszej odległości na jaka˛ zbliża˛ sie˛ do siebie platformy. Kolizja nie nastapi ˛ jeżeli odległość ta bedzie ˛ wieksza ˛ niż suma promieni okregów ˛ opisanych na korpusach obu platform. p d(t) = (x1 − x2)2 + (y1 − y2)2 x1(t) = vx,1t + x0,1 y1(t) = vy,1t + y0,1 x2(t) = vx,2t + x0,2 y2(t) = vy,2t + y0,2 ⇓ d(t) = q ((vx,1 − vx,2 )t + (x0,1 − x0,2))2 + ((vy,1 − vy,2 )t + (y0,1 − y0,2))2 3 Rozwiazanie ˛ w globalnym układzie współrzednych ˛ d(t) = q ((vx,1 − vx,2 )t + (x0,1 − x0,2))2 + ((vy,1 − vy,2 )t + (y0,1 − y0,2))2 ⇓ q d(t) = (vx,12t + x0,12)2 + (vy,12t + y0,12)2 gdzie vx,12 = vx,1 − vx,2 analogicznie x0,12, vy,12, y0,12. Szukamy wartość t , dla której funkcja d(.) osiaga ˛ minimum: dd(t) dt =0 −→ vx,12 (vx,12t + x0,12) + vy,12 (vy,12t + y0,12) = 0 vx,12x0,12 + vy,12y0,12 t= v2x,12 + v2y,12 4 Rozwiazanie ˛ w lokalnym układzie współrzednych ˛ Transformacja do lokalnego układu współrz˛ednych platformy nr 2 zwiazanego ˛ ze środkiem okregu ˛ opisanego na obrysie jej korpusu. xL(t) = x1 (t) − x2(t) yL(t) = y1 (t) − y2(t) vx,L (t) = vx,1 (t) − vx,2(t) vy,L (t) = vy,1 (t) − vy,2(t) Dzieki ˛ zastosowanej transformacji rozwiazanie ˛ problemu znacznie sie˛ upraszcza. Nie trzeba liczyć pochodnej, gdyż w tym przypadku problem jest natury geometrycznej. 5 Rozwiazanie ˛ w lokalnym układzie współrzednych ˛ W lokalnym układzie współrz˛ednych jednej z platform problem sprowadza sie˛ do wyznaczenia odległości prostej od poczatku ˛ układu współrz˛ednych. e V er VL α r d d =| r sin α | | (r × VL )z | VL )z | = d = | r sin α | = | r(er × eV ) | = | (r × eV )z | = | (r × || VL || || VL || 6 d = |(r×VL)z| ||VL|| 7 Rozwiazanie ˛ w lokalnym układzie współrzednych ˛ W lokalnym układzie współrz˛ednych jednej z platform problem sprowadza sie˛ do wyznaczenia odległości prostej od poczatku ˛ układu współrz˛ednych. e V er VL α r d d =| r sin α | Kolizja zachodzi gdy: 8 |(r×VL)z| ||VL|| < R1 + R2 9 Implementacja w C (beznadziejna !!!) float Vx1, Vy1, Px1, Py1, R1; float Vx2, Vy2, Px2, Py2, R2; ... int CzyKolizja() { float Vx, Vy, Px, Py; /∗ . . . . . . . . . . . . . . . . . . . . Stan platformy nr 2 w układzie lokalnym platformy nr 1 ∗/ float d; /∗ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obliczana odległość miniecia ˛ sie˛ platformy nr 1 i 2 ∗/ Vx = Vx1 - Vx2; /∗ . . . . . . . . . . . . . Vy = Vy1 - Vy2; Obliczanie predkości ˛ platformy nr 2 w układzie lokalnym platformy nr 1 ∗/ Px = Px1 - Px2; /∗ . . . . . . . . . . . . . Obliczanie położenia platformy nr 2 w układzie lokalnym platformy nr 1 ∗/ Py = Py1 - Py2; d = fabs(Px∗Vy - Py∗Vx)/sqrt(Vx∗Vx+Vy∗Vy); /∗ . . . . . . . . . . . . . . . Obliczanie odległości miniecia ˛ sie˛ ∗/ return d < R1+R2; } Stosowanie zmiennych globalnym w tym przypadku nie jest uzasadnione. 10 Implementacja w C (Sposób zdecydowanie lepszy) /∗ Vx1, Vy1, Px1, Py1 – predkość ˛ i położenie platformy nr 1, R1 – promień okregu ˛ obrysowujacego ˛ pionowy rzut korpusu platformy, Vx2, Vy2, Px2, Py2 – predkość ˛ i położenie platformy nr 2, R2 – promień okregu ˛ obrysowujacego ˛ pionowy rzut korpusu platformy, ∗/ int CzyKolizja( float Vx1, float Vy1, float Px1, float Py1, float R1, float Vx2, float Vy2, float Px2, float Py2, float R2 ) { float Vx, Vy, Px, Py, /∗ . . . . . . . . . . . . . . . . . . . . . Stan platformy nr 2 w układzie lokalnym platformy nr 1 ∗/ float d; /∗ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obliczana odległość miniecia ˛ sie˛ platformy nr 1 i 2 ∗/ Vx = Vx1 - Vx2; /∗ . . . . . . . . . . . . . Vy = Vy1 - Vy2; Px = Px1 - Px2; Py = Py1 - Py2; Obliczanie predkości ˛ platformy nr 2 w układzie lokalnym platformy nr 1 ∗/ /∗ . . . . . . . . . . . . . Obliczanie położenia platformy nr 2 w układzie lokalnym platformy nr 1 ∗/ d = fabs(Px∗Vy - Py∗Vx)/sqrt(Vx∗Vx+Vy∗Vy); /∗ . . . . . . . . . . . . . . . . Obliczenie Odległości miniecia ˛ sie˛ ∗/ return d < R1+R2; } 11 Implementacja w C (Sposób obiektowo zorientowany) typedef struct Wektor { float x, y; } Wektor; typedef struct PlatformaMobilna { Wektor Pos; /∗ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Położenie platformy ∗/ Wektor V; /∗ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Wektor predkości ˛ platformy ∗/ float R; /∗ . . . . . . . . . . . . . . Promień obrysu pionowego rzutu korpusu platformy ∗/ } PlatformaMobilna; 12 Implementacja w C (Sposób obiektowo zorientowany) int CzyKolizja( PlatformaMobilna PM1, PlatformaMobilna PM2 ) { Wektor V, P; /∗ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Stan platformy nr 2 w układzie lokalnym platformy nr 1 ∗/ float d; /∗ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obliczana odległość miniecia ˛ sie˛ platformy nr 1 i 2 ∗/ V.x = PM1.Vel.x - PM2.Vel.x; /∗ . . Obliczanie predkości ˛ platformy nr 2 w układzie lokalnym platformy nr 1 ∗/ V.y = PM1.Vel.y - PM2.Vel.y; P.x = PM1.Pos.x - PM2.Pos.x; P.y = PM1.Pos.y - PM2.Pos.y; /∗ Obliczanie położenia platformy nr 2 w układzie lokalnym platformy nr 1 ∗/ d = fabs(P.x∗V.y - P.y∗V.x)/sqrt(V.x∗V.x+V.y∗V.y); /∗ . . . . . . . . . . . . . . Obliczenie Odległości miniecia ˛ sie˛ ∗/ return d < PM1.R+PM2.R; } 13 Implementacja w C++ (bez operatorów) class Wektor { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . public: float x, y; Wektor Odejmij(Wektor) const; float IloczynWekZ(const Wektor & V) const { return x∗V. y – y∗V. x; } float IloczynSkal(const Wektor & V) const { return x∗V. x + y∗V. y; } }; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . class PlatformaMobilna { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . public: Wektor Pozycja; Wektor WPredkosci; float R; bool CzyKolizja( const PlatformaMobilna & V) const; }; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Implementacja w C++ (bez operatorów) Wektor Wektor::Odejmij( Wektor W ) const { W. x = x – W. x; W. y = y – W. y; return W; } bool PlatformaMobilna::CzyKolizja( const PlatformaMobilna & PM ) const { Wektor V d = PM. WPredkosci.Odejmij( WPredkosci); Wektor P d = PM. Pozycja.Odejmij( Pozycja); float d = fabs(P d.IloczynWektZ(V))/sqrt(V.IloczynSkal(V)); return d < PM. R+ R; } 15 Implementacja w C++ class Wektor { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . public: float x, y; Wektor operator – (Wektor) const; float operator ∗ (const Wektor & V) const { return x∗V. y – y∗V. x; } float operator & (const Wektor & V) const { return x∗V. x + y∗V. y; } }; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . class PlatformaMobilna { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . public: Wektor Pozycja; Wektor WPredkosci; float R; bool CzyKolizja( const PlatformaMobilna & PM) const; }; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Implementacja w C++ Wektor Wektor::operator − ( Wektor W ) const { W. x = x − W. x; W. y = y − W. y; return W; } bool PlatformaMobilna::CzyKolizja( const PlatformaMobilna & PM ) const { Wektor V = PM. WPredkosci − WPredkosci; Wektor r = PM. Pozycja − Pozycja; return fabs(r∗V)/sqrt(V & V) < PM. R+ R; } |(r×VL)z| ||VL|| < R1 + R2 17 Implementacja w C++ Wektor Wektor::operator − ( Wektor W ) const { W. x = x − W. x; W. y = y − W. y; return W; } bool PlatformaMobilna::CzyKolizja( const PlatformaMobilna & PM ) const { Wektor V = PM. WPredkosci − WPredkosci; return fabs((PM. Pozycja− Pozycja)∗V)/sqrt(V & V) < PM. R+ R; } |(r×VL)z| ||VL|| < R1 + R2 18 Diagramy klas w UML Rysunek 1: Diagram klas dla problemu wykrywania kolizji. 19 Pytania i ćwiczenia 1. Dany jest definicja klasy Wektor: struct Wektor { float x, y; Wektor operator – ( Wektor W ) { W. x = x – W. x; W. y = y – W. y; return W; } float operator ∗ (Wektor V) { return x∗V. y – y∗V. x; } float operator & (Wektor V) { return x∗V. x + y∗V. y; } }; (a) Czy dla powyższej definicji poprawny jest poniższy zapis? Jeżeli tak, to jaki bedzie ˛ wynik? Jeżeli nie, to co trzeba zrobić aby zapis ten był poprawny? Wektor W; W. x = W. y = 1; cout << (W & W ∗ W); (b) Czy dla powyższej definicji poprawny jest poniższy zapis? Jeżeli tak, to jaki bedzie ˛ wynik? Jeżeli nie, to co trzeba zrobić aby zapis ten był poprawny? Wektor W; W. x = W. y = 1; cout << (W & W – W ∗ W); 20