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

Podobne dokumenty