Найдите точку на окружности с заданными центром, радиусом и градусом

84

Прошло 10 лет с тех пор, как я занимался подобной математикой ... Я программирую игру в 2D и перемещаю игрока. Когда я перемещаю игрока, я пытаюсь вычислить точку на окружности на расстоянии 200 пикселей от позиции игрока, учитывая положительный ИЛИ отрицательный угол (градус) от -360 до 360. Экран - 1280x720, где 0,0 - центральная точка. экрана. Игрок перемещается по всей этой декартовой системе координат. То, что я пытаюсь найти, может быть за кадром.

Я пробовал формулы в статье Найдите точку с радиусом и углом, но я не думаю, что понимаю, что такое «Угол», потому что я получаю странные результаты, когда передаю Угол от -360 до 360 в Cos (угол) или Sin (угол).

Так, например, у меня есть ...

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

Какая формула возвращает X на круге?

Какая формула возвращает 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))
yoozer8
источник
1
Сначала меня смущала разница между УГОЛОМ и СТЕПЕНЬЮ. Я думал, это одно и то же. Тогда я подумал, что получаю точку (x, y) на плоскости, но на самом деле я получил длину сторон x и y. Я нарисовал его на бумаге, затем поместил в Excel, чтобы охватить диапазон градусов, чтобы проверить формулы. Теперь он работает в моем коде.
Кайл Андерсон
3
Не должно X = xcircle + (r * sine(angle))быть X = xcircle + (r * cosine(angle))(и наоборот Y)?
txtechhelp
4
Обратите внимание, что значение угла должно быть выражено в радианах!
Roman M
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)? Также спасибо за указание разницы между рад и градусом.
monsto 03
Зомби @monsto по-прежнему отправляют уведомления. :). Внутренние скобки не имеют значения, потому что умножение и деление являются коммутативными демонстрациями . 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);
MD. Назмул Кибрия
источник
ОСТОРОЖНО, что из-за ошибок округления это может вернуть на 1 элемент меньше, чем ожидалось! Поэтому я добавил немного маринования, чтобы в итоге получить правильное количество элементов (в моем примере вместо double используются числа с плавающей запятой); for (float interval = angleInterval; interval <2 * Math.PI + 0.0000099f; interval + = angleInterval)
sommmen
1

Я хотел рассказать, как ваш вклад, приведенный выше, помог мне создать ЖК-компас Arduino. Надеюсь, это правильный этикет ... Я только что присоединился к stackoverflow, чтобы поблагодарить вас, прекрасные люди.

Стоя на плечах геометрических гигантов выше, я смог создать этот образец компаса: компас Arduino TFT с несколькими пеленгами.

Код функции, которую я неоднократно вызывала (для разных подшипников вы видите в крошечном желтом тексте), написан на Arduino (вроде как "C") ... и довольно легко переводится:

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
источник
0

Ответ должен быть прямо противоположным.

X = Xc + rSin (угол)

Y = Yc + rCos (угол)

где Xc и Yc - координаты центра круга, а r - радиус.

Адитья Аггарвал
источник
0

Рекомендую:

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

дитя
источник
-3

Вы можете использовать это:

Уравнение круга, где

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

где k и v постоянны, а R - радиус

Джэхун
источник