Знайдіть точку на колі з заданою центральною точкою, радіусом та градусом


84

Минуло 10 років з тих пір, як я зробив будь-яку математику, як це ... Я програмую гру в 2D і рухаю гравця. Під час переміщення гравця я намагаюся обчислити точку по колу на 200 пікселів від позиції гравця з позитивним АБО негативним кутом (градусом) від -360 до 360. Екран дорівнює 1280x720, а 0,0 - центральна точка екрана. Гравець рухається по всій цій декартовій системі координат. Справа, яку я намагаюся знайти, може бути поза екраном.

Я спробував формули в статті Знайти точку з радіусом і кутом, але я не вірю, що розумію, що таке "Кут", тому що я отримую дивні результати, коли передаю Angle як -360 до 360 в Cos (кут) або Sin (кут).

Так, наприклад, я маю ...

  • 1280x720 на декартовому літаку
  • Центральна точка (позиція гравця):
    • нехай x = число від мінімального -640 до максимального 640
    • нехай y = число від мінімального -360 до максимального 360
  • Радіус кола навколо гравця: нехай r завжди = 200
  • Кут: нехай a = число, яке дається від -360 до 360 (дозвольте негативному вказувати вниз або позитивному вгору, тому -10 і 350 дадуть однакову відповідь)

Яка формула повернення Х по колу?

Яка формула повернення Y по колу?

введіть тут опис зображення введіть тут опис зображення


16
Це ДОБРЕ питання !!! +1
FrostyFire

1
Запитання: Хіба у більшості ігор немає кординатів вгорі ліворуч до 0,0? а вісь y опускається вниз, а не вгору?
Persijn

Відповіді:


74

Прості рівняння з вашого посилання дають координати X і Y точки на колі відносно центру кола .

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

Це говорить про те, наскільки точка зміщена від центру кола. Оскільки у вас є координати центру (Cx, Cy), просто додайте розрахований зсув.

Координати точки на колі такі:

X = Cx + (r * cosine(angle))  
Y = Cy + (r * sine(angle))

1
Моя плутанина полягала в першу чергу в різниці між ANGLE та DEGREE. Я думав, що це одне й те саме. Тоді я думав, що отримую точку (x, y) на площині, але насправді отримував довжину сторін x і y. Я намалював його на папері, а потім згорнув у Excel, щоб охопити діапазон градусів, щоб перевірити формули. Зараз це працює в моєму коді.
Кайл Андерсон,

3
Не повинно X = xcircle + (r * sine(angle))бути X = xcircle + (r * cosine(angle))(і навпаки Y)?
txtechhelp

4
Зверніть увагу, що кут повинен бути значенням в радіанах!
Роман М

17

Вам слід розмістити код, який ви використовуєте. Це допомогло б точно визначити проблему.

Однак, оскільки ви вже згадали про вимірювання кута в межах від -360 до 360, ви, мабуть, використовуєте неправильні одиниці для вашої математичної бібліотеки. Більшість реалізацій функцій тригонометрії використовують радіани для введення. І якщо ви замість цього використовуєте ступені ... Ваші відповіді будуть дивно неправильними.

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

Зверніть увагу, що ви також можете зіткнутися з обставиною, коли квадрант не є таким, як ви очікуєте. Це можна виправити, ретельно вибравши, де знаходиться кут нуль, або вручну перевіривши очікуваний квадрант і застосувавши власні знаки до значень результату.


1
Це справді має бути коментарем, а не відповіддю. Однак приємний улов на радіани проти градусів.
yoozer8

Запитання про зомбі: в паренсі, це (deg * (pi / 180))чи інший шлях ((deg * pi) / 180)? Також дякую за вказівку різниці між rad та deg.
монсто

@monsto zombies все ще надсилає сповіщення. :). Внутрішні парени не мають значення, оскільки множення та ділення - це комутативні демонстрації . Wolfram.com/… . Я давно винен у тому, що вклав у свій код надмірну кількість парен. Я роблю вигляд, що це для ясності, але очевидно, що це не зовсім точно, інакше вас це б не турбувало.
Сет Баттін,

6

Я настійно рекомендую використовувати матриці для цього типу маніпуляцій. Це найбільш загальний підхід, див. Приклад нижче:

// 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); 
  • Побічна примітка, домовленість полягає у вимірюванні кута проти годинникової стрілки стартової форми (позитивна) вісь X

5

Я отримую дивні результати, коли передаю Angle як -360 до 360 в Cos (кут) або Sin (кут).

Я думаю, причина вашої спроби не спрацювала в тому, що ви проходили кути в градусах. Функції sinі і cosтригонометричні очікують кути, виражені в радіанах, тому числа повинні бути від 0до 2*M_PI. Для dступенів, які ви здаєте M_PI*d/180.0. M_PI- константа, визначена в math.hзаголовку.


Я зрозумів, кут і градус, мабуть, не одне і те ж, тому чи правильно я кажу, кажучи: Angle = M_PI * d / 180.0, де d може бути числом від -360 до 360, чи мені потрібен ще один крок?
Кайл Андерсон,

1
@Kyle d- від 0до 360або від -180до 180(повне коло), а не від -360до 360(два цілі кола).
Сергій Калініченко

4

Мені це також знадобилося, щоб сформувати рух стрілок годинника в коді. Я спробував кілька формул, але вони не працювали, тому ось що я придумав:

  • рух - за годинниковою стрілкою
  • бали - кожні 6 градусів (оскільки 360 градусів, розділених на 60 мінутів, це 6 градусів)
  • довжина руки - 65 пікселів
  • центр - x = 75, y = 75

Тож формула буде

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

де x і y - точки на окружності кола, Cx і Cy - координати x, y центру, r - радіус, d - кількість градусів.


2

Ось реалізація c #. Метод повертає кругові точки, які приймає radius, centerі angle intervalяк параметр. Кут передається як радіан.

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;
        }

та приклад виклику:

List<PointF> LEPoints = getCircularPoints(10.0f, new PointF(100.0f, 100.0f), Math.PI / 6.0f);

ОСТЕРЕЖАЙТЕСЯ, що це може повернути на 1 елемент менше, ніж очікувалося, через помилки округлення! Тому я додав трохи маркування, щоб у підсумку отримати правильну кількість предметів (у моєму прикладі є плаваючі замість подвійних); для (інтервал поплавка = кутовий інтервал; інтервал <2 * Math.PI + 0,0000099f; інтервал + = кутовий інтервал)
соммен

1

Я хотів поділитися з тим, як ваші внески вище допомогли мені виготовити РК-компас Arduino. Сподіваюся, це правильний етикет ... Я щойно приєднався до stackoverflow, щоб я міг подякувати вам, чудові люди.

Стоячи на плечах геометрів-гігантів вище, я зміг виготовити цей зразок компаса: Arduino TFT-компас з кількома підшипниками

Код функції, яку я неодноразово викликав (для різних підшипників, які ви бачите у крихітному жовтому тексті), написаний на Arduino (приблизно як "С") ... і досить перекладний:

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);

}

0

Відповідь повинна бути прямо протилежною.

X = Xc + rSin (кут)

Y = Yc + rCos (кут)

де Xc та Yc - центральні координати кола, а r - радіус.



-3

Ви можете використовувати це:

Рівняння кола де

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

де k і v - постійні, а R - радіус

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.