Jak obliczyć kąt pomiędzy punktami.

0

Witam!

y|
 |
 |                  0 c
 |     0 b
 |
 |         0 a
 |
 |
 ----------------------------------->
                               x

Mam pytanie dotyczące metody Math.Atan2. Metoda z tego co rozumiem liczy tangens kąta utworzonego przez wektor (o początku [0,0] i końcu danego punku, którego współrzędne podajemy jako paramer metody)i oś x. Mi zależy na tym, aby liczyć kąty z danego punktu, czyli z punktu a o współrzędnych [x1,y1] chcę policzyć kąt pomiędzy tym punktem, a punktem b o współrzędnych [x1,y2], czy można to zrobić za pomocą tej metody, czy do rozwiązania tego problemu muszę użyć czegoś innego?
Dzięki z góry za odpowiedzi.

0

Tak, wystarczy. Mając X1, Y1, X2, Y2 kreślisz prostą, obliczasz jej współczynniki a i b gdzie arctan(a) daje właśnie kąt nachylenia prostej do osi x. Pamiętaj tylko, że dostaniesz wynik w radianach a nie w stopniach.

0

Mozesz tez tak przekszalcic uklad, ze punkt a bedzie srodkiem ukladu(punktem 0,0) i wtedy podawac wspolrzedne dowolnego innego punktu. Wystarczy odjac od wspolrzednych podawanego punktu wspolrzedne punktu a.

0

Przez chwilkę myślałem nad przyrównaniem początku wektora do zera, ale jakoś mi ten pomysł lepiej wpadł.

0

Obydwa sa wlasciwe, ale skoro ta metoda juz liczy kat, to latwiej przeksztalcic dane tak, by pasowaly ;)

@__krzysiek85 - to juz latwiej iloczyn skalarny chyba (z wektorowego trzeba jeszcze wyznacznik policzyc zdaje sie), ale to jest pewnie wlasnie to co robi metoda podana przez autora...

0

Metoda Atan2(y,x) zwraca faktycznie kąt między wektorem [x,y] a osią Ox. Aby uzyskać kąt między wektorami ab i ac wystaczy policzyć współrzędne tych wektorów ( tzn. ab=[xb-xa,yb-ya]=[xab,yab] ac=[xc-xa,yc-ya]=[xac,yac]), a potem liczymy kąt między nimi
angle=Atan2(yac,xac)-Atan(yab,xab).

Należy jednak pamiętać, że Atan2 zwróci nam wartość z przedziału (-Pi/2,Pi/2), więc jeśli kąty będą spoza przedziału, to dostaniemy fałszywe wartości. Można temu łatwo zapobiec sprawdzając znaki współrzędnych wektorów ab i ac, następnie sprowadzając wektory do I i IV ćwiartki układu, licząc kąty między nimi a osią Ox a następnie dodając odpowiednie wartości (Pi/2 lub -Pi/2).

Iloczyn skalarny dzielony przez iloczyn długości też jest dobrą metodą (dokładniej arccos z tego) - tutaj dostajemy wartości z przedziału [0,Pi], więc i tak nie unikniesz kombinowania. ;-P

Pozdrawiam. Piotr.

0

Iloczyn skalarny to najprostsza metoda. Kąt wklęsły pomiędzy wektorami U i V to:
alfa=arccos(<U,V>) / sqrt(<U,U>*<V,V>) , gdzie <X,Y> to iloczyn skalarny X i Y.

Dla kąta BAC wektory to U=B-A, V=C-A. Licząc te wektory to tak jakbyśmy przesuwali układ współrzędnych tak, aby początek znajdował się w punkcie A.

elis napisał(a)

tutaj dostajemy wartości z przedziału [0,Pi], więc i tak nie unikniesz kombinowania. ;-P
Ale co tu kombinować, skoro między dwoma wektorami są 2 kąty - wypukły i wklęsły, gdzie ich suma to 2pi.

Jednak jeśli kierunek kąta ma znaczenie, to trzeba policzyć również sinus z iloczynu wektorowego.
sin= U[x]V / sqrt(<U,U>*<V,V>), gdzie X[x]Y to iloczyn wektorowy X i Y.
Dalej trzeba policzyć tangesn
tan=sin/cos
Policzyć kąt
alfa=arctan(tan).
Dodać do kąta 1pi, jeśli sin<0
W powyższy sposób otrzymasz lewoskrętny kąt od wektora U do wektora V

Dla 2-wymiarowej przestrzeni euklidesowej:
<U,V> = UxVx+UyVy
U[x]V = UxVy-UyVx

Ku ścisłości, iloczyn wektorowy nie istnieje w przestrzeniach 2-wymiarowych. Powyższy operator U[x]V to długość iloczynu wektorowego wektorów (Ux, Uy, 0) i (Vx, Vy, 0). Jeśli oznaczyć by K=(Ux, Uy, 0) i L=(Vx, Vy, 0), to
cos(U,V) = cos(K,L) = |K[x]L| / (|K||L|) = U[x]V / (|U||V|) = U[x]V / sqrt(<U,U>*<V,V>)

0

Chodziło mi o kąt skierowany.

0

No to napisz sobie strukturę dla wektora 2D, zdefiniuj operatory odejmowania, mnożenia skalarnego i mnożenia wektorowego. Dalej wg. opisu czyli
U=B-A, V=C-A
dl=sqrt(<U,U>*<V,V>)
jeśi dl==0 to jeden lub obydwa wektory są zerowe (punkt A pokrywa się z punktem B i/lub C) - brak kąta
sin=U[x]V / dl
cos=<U,V> / dl
alfa=arctan(sin/cos)
jeśli sin<0 (III i IV ćwiartka) to alfa+=PI

Tylko przetestuj czy to jest kąt BAC, czy CAB, ale z tego co pamiętam będzie to lewoskrętny kąt BAC

0

adf88 napisał:

cos=<U,V> / dl
alfa=arctan(sin/cos)
jeśli sin<0 (III i IV ćwiartka) to alfa+=PI

Nie łatwiej (nie eliminujemy kątów +-Pi/2) tak:
cos=<U,V> / dl
alfa=arccos(cos)
jeśli sin<0 (III i IV ćwiartka) to alfa=-alfa
?</quote>

0

adf88 napisał:

Źle. Iloczyn skalarny daje moduł.
cos = <U,V>/dl = |cos(alfa)|

Dasz za to głowę?

Np. dla [-1,1] i [1,0] nie dostaniemy wartości nieujemnej.

Chodziło Ci chyba o cos(|alfa|), a to w moim sposobie jest załatwione (przy sin<0).

0

prościej się nie da:

atan2(axbx+ayby,axby-axby);

mogłem tylko pomylić znaki. Czemu tak, sam rozgryź (podpowiedź: [y,-x] jest prodtopadłe do [x,y]).

0

wkradła się literówka, powinno być:

atan2(axbx+ayby,aybx-axby);

0

A gdzie c?

0

a i b powyżej to V i U czyli C-A i B-A

0

Mam kolejne pytanie dotyczące liczenia kątów, tym razem w trzech wymiarach.
Powiedzmy, że mam parę kul, z czego każda jest mniejsza od poprzedniej i wszystkie mają środek w tym samym punkcie. Taką oto figurę przecinam powiedzmy równoległymi płaszczyznami, to jest nie istotne. To do której kuli należy punkt sprawdzę za pomocą nierówności:
(x-x0)^2 + (y-y0)^2 + (z-z0)^2 <= r^2
Jak mam policzyć kąt pomiędzy danym punktem, a środkiem? Znalazłem na CodeProject.com http://www.codeproject.com/KB/graphics/Sphere.aspx artykuł o sferycznych koordynatach, ale nie umię tego zrozumieć za bardzo.

0

mam podobny problem jak moj przedmowca

Jak obliczyc kat pomiedzy dwoma punktami/wektorami w przestrzeni 3D przy pomocy funkcji atan2?

0

Na CodeGuru jest ten sam topik. Sprawdz tamtejsze odpowiedzi. Moze pomoze.

0

Moim zdaniem chyba najprościej z twierdzenia cosinusów.

Oto trochę kodu pochodzącego od jednego z moich projektów.
(komentarze pisałem po angielsku, mam nadzieje ze to nie problem)

 
        /// <summary>
        /// Compute the Euclidean norm
        /// </summary>
        /// <param name="x">x-coordinate of a point</param>
        /// <param name="y">y-coordinate of a point</param>
        /// <returns>Eucli</returns>
        static double hypot(double x, double y)
        {
            return Math.Sqrt(x * x + y * y);
        }
        
        static double RadiansToDegrees(double radians)
        {
            double degree = 180 * radians / Math.PI;
            return degree;
        }
        /// <summary>
        /// Gets the distance between two points.
        /// </summary>
        /// <param name="p1">First of points</param>
        /// <param name="p2">Second of Points</param>
        /// <returns></returns>
        public static double GetDistance(Point p1, Point p2)
        {
            return hypot(p2.X - p1.X, p2.Y - p1.Y);
        }

        /// <summary>
        /// Gets the distance between two points.
        /// </summary>
        /// <param name="x1">x-coordinate of first point</param>
        /// <param name="y1">y-coordinate of first point</param>
        /// <param name="x2">x-coordinate of second point</param>
        /// <param name="y2">y-coordinate of second point</param>
        /// <returns></returns>
        public static double GetDistance(double x1, double y1, double x2, double y2)
        {
            return hypot(x2 - x1, y2 - y1);
        }

        public static double GetAngle(Point p1, Point p2, Point p3)
        {
            double a, b, c, radians;
            a = GetDistance(p3, p2);
            b = GetDistance(p1, p3);
            c = GetDistance(p1, p2);
            // We apply law of cosines
            radians = Math.Acos((a * a + c * c - b * b) / (2 * a * c));
            return RadiansToDegrees(radians);
        }

1 użytkowników online, w tym zalogowanych: 0, gości: 1