Znajdź punkt na okręgu o podanym punkcie środkowym, promieniu i stopniu

84

Minęło 10 lat, odkąd zrobiłem taką matematykę ... Programuję grę w 2D i przenoszę gracza. Kiedy poruszam odtwarzaczem, próbuję obliczyć punkt na okręgu 200 pikseli od pozycji gracza, biorąc pod uwagę dodatni LUB ujemny kąt (stopnie) między -360 a 360. Ekran ma wymiary 1280x720, gdzie 0,0 jest punktem środkowym ekranu. Gracz porusza się po całym kartezjańskim układzie współrzędnych. Punkt, który próbuję znaleźć, może znajdować się poza ekranem.

Wypróbowałem formuły w artykule Znajdź punkt za pomocą promienia i kąta, ale nie wierzę, że rozumiem, co to jest „kąt”, ponieważ otrzymuję dziwne wyniki, gdy przechodzę kąt od -360 do 360 do cos (kąta) lub grzechu (kąt).

Na przykład mam ...

  • 1280x720 na płaszczyźnie kartezjańskiej
  • Punkt środkowy (pozycja gracza):
    • niech x = liczba od minimum -640 do maksimum 640
    • let y = liczba od minimum -360 do maksimum 360
  • Promień okręgu wokół gracza: niech r zawsze = 200
  • Kąt: niech a = liczba podana w przedziale od -360 do 360 (pozwól, aby wartość ujemna wskazywała w dół lub dodatnia, aby wskazywała w górę, aby -10 i 350 dały tę samą odpowiedź)

Jaka jest formuła zwracania X w okręgu?

Jaka jest formuła zwracania Y na okręgu?

wprowadź opis obrazu tutaj wprowadź opis obrazu tutaj

Kyle Anderson
źródło
16
To jest DOBRE pytanie !!! +1
FrostyFire
1
Pytanie: Czy w większości gier nie ma kordynatów w lewym górnym rogu do 0,0? i oś y idzie w dół, a nie w górę?
Persijn

Odpowiedzi:

74

Proste równania z twojego łącza podają współrzędne X i Y punktu na okręgu w stosunku do środka okręgu .

X = r * cosine(angle)  
Y = r * sine(angle)

To mówi, jak daleko punkt jest odsunięty od środka koła. Ponieważ masz współrzędne środka (Cx, Cy), po prostu dodaj obliczone przesunięcie.

Współrzędne punktu na okręgu to:

X = Cx + (r * cosine(angle))  
Y = Cy + (r * sine(angle))
yoozer8
źródło
1
Najpierw pomyliłem się z różnicą między ANGLE i DEGREE. Myślałem, że to to samo. Potem pomyślałem, że dostaję punkt (x, y) na płaszczyźnie, ale tak naprawdę otrzymałem długość boków x i y. Narysowałem go na papierze, a następnie umieściłem go w programie Excel, aby objąć zakres stopni, aby sprawdzić formuły. Teraz działa w moim kodzie.
Kyle Anderson
3
Nie powinno X = xcircle + (r * sine(angle))być X = xcircle + (r * cosine(angle))(i odwrotnie Y)?
txtechhelp
4
Zauważ, że kąt powinien być wartością w radianach!
Roman M
17

Powinieneś wysłać kod, którego używasz. Pomogłoby to dokładnie zidentyfikować problem.

Ponieważ jednak wspomniałeś o mierzeniu kąta w zakresie od -360 do 360, prawdopodobnie używasz nieprawidłowych jednostek dla swojej biblioteki matematycznej. Większość implementacji funkcji trygonometrycznych używa radianów jako danych wejściowych. A jeśli zamiast tego użyjesz stopni ... Twoje odpowiedzi będą dziwnie błędne.

x_oncircle = x_origin + 200 * cos (degrees * pi / 180)
y_oncircle = y_origin + 200 * sin (degrees * pi / 180)

Zwróć uwagę, że możesz również napotkać okoliczności, w których kwadrant nie jest taki, jakiego oczekujesz. Można to naprawić, ostrożnie wybierając miejsce, w którym znajduje się kąt zerowy, lub ręcznie sprawdzając kwadrant, którego oczekujesz i stosując własne znaki do wartości wyników.

Seth Battin
źródło
1
Powinien to być raczej komentarz niż odpowiedź. Jednak niezły chwyt na radianach w funkcji stopni.
yoozer8
Pytanie o post zombie: w parens, czy to jest (deg * (pi / 180))czy inaczej ((deg * pi) / 180)? Dziękuję również za określenie różnicy między rad vs deg.
monsto
Zombie @monsto nadal wysyłają powiadomienia. :). Wewnętrzne pareny nie mają znaczenia, ponieważ mnożenie i dzielenie są przemienne demonstracjami.wolfram.com/… . Od dawna jestem winny umieszczania nadmiernych parens w moim kodzie. Udaję, że to dla jasności, ale najwyraźniej nie jest to do końca prawdą, inaczej nie przeszkadzałoby ci to.
Seth Battin
6

Gorąco polecam używanie matryc do tego typu manipulacji. Jest to najbardziej ogólne podejście, patrz przykład poniżej:

// The center point of rotation
var centerPoint = new Point(0, 0);
// Factory method creating the matrix                                        
var matrix = new RotateTransform(angleInDegrees, centerPoint.X, centerPoint.Y).Value;
// The point to rotate
var point = new Point(100, 0);
// Applying the transform that results in a rotated point                                      
Point rotated = Point.Multiply(point, matrix); 
  • Uwaga dodatkowa, konwencja polega na mierzeniu kąta w kierunku przeciwnym do ruchu wskazówek zegara, zaczynając od (dodatniej) osi X.
Johan Larsson
źródło
5

Otrzymuję dziwne wyniki, gdy przechodzę kąt od -360 do 360 do Cos (kąt) lub Sin (kąt).

Myślę, że powodem, dla którego twoja próba się nie powiodła, jest to, że przechodzisz przez kąty w stopniach. Funkcje trygonometryczne sini cosoczekują kątów wyrażonych w radianach, więc liczby powinny wynosić od 0do 2*M_PI. Za dstopnie, które zdajesz M_PI*d/180.0. M_PIjest stałą zdefiniowaną w math.hnagłówku.

Sergey Kalinichenko
źródło
Doszedłem do wniosku, że kąt i stopień prawdopodobnie nie są tym samym, więc czy mam rację, mówiąc Kąt = M_PI * d / 180.0, gdzie d może być liczbą od -360 do 360, czy potrzebuję kolejnego kroku?
Kyle Anderson
1
@Kyle djest od 0do 360lub od -180do 180(pełne koło), a nie od -360do 360(dwa pełne koła).
Sergey Kalinichenko
4

Potrzebowałem tego również do ukształtowania ruchu wskazówek zegara w kodzie. Wypróbowałem kilka formuł, ale nie zadziałały, więc wymyśliłem to:

  • ruch - zgodnie z ruchem wskazówek zegara
  • punktów - co 6 stopni (ponieważ 360 stopni podzielone przez 60 minuitów to 6 stopni)
  • długość dłoni - 65 pikseli
  • środek - x = 75, y = 75

Więc formuła byłaby taka

x=Cx+(r*cos(d/(180/PI))
y=Cy+(r*sin(d/(180/PI))

gdzie x i y to punkty na obwodzie koła, Cx i Cy to współrzędne x, y środka, r to promień, ad to liczba stopni.

Upiorny
źródło
2

Oto implementacja C #. Sposób powraca okrągłe punkty, które trwa radius, centeri angle intervaljako parametru. Kąt jest podawany jako Radian.

public static List<PointF> getCircularPoints(double radius, PointF center, double angleInterval)
        {
            List<PointF> points = new List<PointF>();

            for (double interval = angleInterval; interval < 2 * Math.PI; interval += angleInterval)
            {
                double X = center.X + (radius * Math.Cos(interval));
                double Y = center.Y + (radius * Math.Sin(interval));

                points.Add(new PointF((float)X, (float)Y));
            }

            return points;
        }

i przykład wywołujący:

List<PointF> LEPoints = getCircularPoints(10.0f, new PointF(100.0f, 100.0f), Math.PI / 6.0f);
MD. Nazmul Kibria
źródło
UWAŻAJ, że może to zwrócić o 1 pozycję mniej niż oczekiwano z powodu błędów zaokrąglania! w związku z tym dodałem trochę marnowania, aby na końcu uzyskać poprawną liczbę elementów (mój przykład ma liczby zmiennoprzecinkowe zamiast podwójnych); for (float interval = angleInterval; interwał <2 * Math.PI + 0,0000099f; interwał + = angleInterval)
sommmen
1

Chciałem podzielić się tym, w jaki sposób Twój wkład powyżej pomógł mi w stworzeniu kompasu Arduino LCD. Mam nadzieję, że to właściwa etykieta ... Właśnie dołączyłem do stackoverflow, aby podziękować wam, fajni ludzie.

Stojąc na ramionach gigantów geometrii powyżej, byłem w stanie wyprodukować ten przykładowy kompas: kompas Arduino TFT z wieloma łożyskami

Kod funkcji, którą wielokrotnie wywoływałem (dla różnych łożysk, które widzisz małym żółtym tekstem) jest napisany w Arduino (coś w rodzaju "C") ... i można go łatwo przetłumaczyć:

void PaintCompassNeedle( int pBearingInDegrees, int pRadius, TSPoint pCentrePt ) {
    // ******************************************************************************
    // * Formula for finding pointX on the circle based on degrees around the circle:
    // * x_oncircle = x_origin + radius * cos (degrees * pi / 180)  
    // * y_oncircle = y_origin - radius * sin (degrees * pi / 180) //minus explained
    // * Thanks to folks at stackoverflow...standing on the shoulders of giants. :) 

    float bearingInRads = (pBearingInDegrees) * PI / 180; 
    // Degrees vs Rads...The math folks use Rads in their formulas

    // *******************************************************************
    // * bearingPt is the point on the circle that we are trying to find
    TSPoint bearingPt;
    // Find the X on the circle starting with orgin (centre)
    bearingPt.x = pCentrePt.x + pRadius * sin(bearingInRads); 
    // Notice the "minus" R * cos()...because TFT the y is upside down bearingPt.y = 
    pCentrePt.y - pRadius * cos(bearingInRads); 
    // * Extra Explanation: The TFT is the graphical display I'm using and it
    // * calculates x & y from the top left of screen (portrait mode) as (0,0)
    // * ...so by Subtracting from the Y orgin...I flip it vertically
    // * Other folks using x,y as increasing to the right and up respectively
    // * would keep the plus sign after the pCentrePt.y
    // *************************************************************************

    // ***************************************************************
    // * This part will change for the final product...but leaving
    // * it because when call numerous times it shows it working for
    // * a number of different quadrants (displaying yellow degrees text)
    tft.fillCircle( bearingPt.x, bearingPt.y, 5, RED); 
    tft.setCursor( bearingPt.x, bearingPt.y );
    tft.setTextSize( 1 );
    tft.setTextColor( YELLOW );
    tft.print( pBearingInDegrees );

    TSPoint innerPt;
    innerPt.x = pCentrePt.x + pRadius/2 * sin(bearingInRads);
    innerPt.y = pCentrePt.y - pRadius/2 * cos(bearingInRads);
    tft.drawLine(innerPt.x, innerPt.y, bearingPt.x, bearingPt.y, RED);

}
TomOfMilton
źródło
0

Odpowiedź powinna być dokładnie odwrotna.

X = Xc + rSin (kąt)

Y = Yc + rCos (kąt)

gdzie Xc i Yc są współrzędnymi środka okręgu, a r jest promieniem.

Aditya Aggarwal
źródło
0

Polecić:

 public static Vector3 RotatePointAroundPivot(Vector3 point, Vector3 
pivot, Vector3 angles)
    {
	    return Quaternion.Euler(angles) * (point - pivot) + pivot;
    }

dziecko
źródło
-3

Możesz użyć tego:

Równanie okręgu gdzie

(xk) 2 + (yv) 2 = R 2

gdzie k i v są stałe, a R jest promieniem

Jaehoon
źródło