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?
Odpowiedzi:
Proste równania z twojego łącza podają współrzędne X i Y punktu na okręgu w stosunku do środka okręgu .
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:
źródło
X = xcircle + (r * sine(angle))
byćX = xcircle + (r * cosine(angle))
(i odwrotnieY
)?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.
źródło
(deg * (pi / 180))
czy inaczej((deg * pi) / 180)
? Dziękuję również za określenie różnicy między rad vs deg.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);
źródło
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
sin
icos
oczekują kątów wyrażonych w radianach, więc liczby powinny wynosić od0
do2*M_PI
. Zad
stopnie, które zdajeszM_PI*d/180.0
.M_PI
jest stałą zdefiniowaną wmath.h
nagłówku.źródło
d
jest od0
do360
lub od-180
do180
(pełne koło), a nie od-360
do360
(dwa pełne koła).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:
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.
źródło
Oto implementacja C #. Sposób powraca okrągłe punkty, które trwa
radius
,center
iangle interval
jako 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);
źródło
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); }
źródło
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.
źródło
Polecić:
źródło
Możesz użyć tego:
Równanie okręgu gdzie
gdzie k i v są stałe, a R jest promieniem
źródło