2012-01-26 12 views
5

Obracam punkty wokół punktu środkowego w przestrzeni 2D. Punkty są punktem środkowym, starą pozycją myszy i nową pozycją myszy. Moja funkcja obrotu działa dobrze i mogę idealnie obliczyć kąt. Ale chcę obliczyć kąt ujemny, jeśli użytkownik porusza myszą w kierunku, który powinien być interpretowany jako przeciwny do ruchu wskazówek zegara.Odzyskaj kąt dodatni lub ujemny z 3 punktów

Na przykład, przesuwanie myszy w prawo (dodatnia oś x) powinno obracać się zgodnie z ruchem wskazówek zegara, jeśli jesteś powyżej (mniej niż) wartości y punktu środkowego, ale powinno ono obracać się przeciwnie do ruchu wskazówek zegara, jeśli faktycznie znajdujesz się poniżej (większa niż) wartość y punktu środkowego.

Oto co mam:

PointF centerPoint; 
PointF oldPoint; 
PointF newPoint; 

double Xc = centerPoint.X; 
double Yc = centerPoint.Y; 
double Xb = oldPoint.X; 
double Yb = oldPoint.Y; 
double Xa = newPoint.X; 
double Ya = newPoint.Y; 

double c2 = (Math.Pow(Xb - Xa, 2) + Math.Pow(Yb - Ya, 2)); 
double a2 = (Math.Pow(Xb - Xc, 2) + Math.Pow(Yb - Yc, 2)); 
double b2 = (Math.Pow(Xa - Xc, 2) + Math.Pow(Ya - Yc, 2)); 

double a = Math.Sqrt(a2); 
double b = Math.Sqrt(b2); 

double val = (a2 + b2 - c2)/(2 * a * b); 
double angle = Math.Acos(val); 

Więc potrzebny jest sposób, aby kąt ujemny, kiedy to musi być, więc punkty obracać w prawo lub w lewo, aby śledzić pozycję myszy.

Odpowiedz

7

Spróbuj tego, ale nie jestem pewien:

double v1x = Xb - Xc; 
double v1y = Yb - Yc; 
double v2x = Xa - Xc; 
double v2y = Ya - Yc; 

double angle = Math.Atan2(v1x, v1y) - Math.Atan2(v2x, v2y); 
+0

To wydaje się działać. Wychodzi przeciwnie do ruchu wskazówek zegara, kiedy ma. –

0

Wydaje się, że wszystko, co trzeba zrobić, to

angle = angle > Math.PI ? angle - 2*Math.PI : angle; 

na końcu kodu. To da ci obrót w prawo na prawo od linii zdefiniowanej przez centerPoint i oldPoint, i przeciwnie do ruchu wskazówek zegara po lewej stronie, niezależnie od orientacji.

+0

kąt nigdy nie jest większa niż Math.PI. –

+0

Hmmm. Może być konieczne ponowne sformułowanie obliczenia kąta, aby zastosować Math.atan2(), aby uzyskać kąt we właściwym kwadrancie. –

0

Podane wektory (x1, y1) i (x2, y2), proponuję obliczenie iloczynu krzyżowego i iloczynu punktowego, a następnie użycie Atan2() na nich. Będzie to działać we wszystkich przypadkach, w których oba wektory są niezerowe, a długości wektorów są "rozsądne".

3
private double AngleFrom3PointsInDegrees(double x1, double y1, double x2, double y2, double x3, double y3) 
{ 
    double a = x2 - x1; 
    double b = y2 - y1; 
    double c = x3 - x2; 
    double d = y3 - y2; 

    double atanA = Math.Atan2(a, b); 
    double atanB = Math.Atan2(c, d); 

    return (atanA - atanB) * (-180/Math.PI); 
    // if Second line is counterclockwise from 1st line angle is 
    // positive, else negative 
} 
+0

Musiałem dodać ujemne wartości X, aby uruchomić je dla mnie (obliczenia są teraz zgodne z AutoCAD) – DarkPh03n1X