Как рассчитать точку на окружности круга?

Как можно реализовать следующую функцию на разных языках?

Вычислите точку (x,y) на окружности круга, учитывая входные значения:

  • Радиус
  • Угол
  • Происхождение (необязательный параметр, если поддерживается языком)

person Community    schedule 08.05.2009    source источник


Ответы (5)


параметрическое уравнение для круга:

x = cx + r * cos(a)
y = cy + r * sin(a)

Где r - радиус, cx, cy - начало координат, а a - угол.

Это довольно легко адаптировать к любому языку с помощью основных триггерных функций. Обратите внимание, что большинство языков будут использовать радианы для угла в триггерных функциях, поэтому вместо циклического через 0..360 градусов вы проходите через 0..2PI радиан.

person Paul Dixon    schedule 08.05.2009
comment
Обратите внимание, что a должен быть в радианах - мне, как новичку, было очень трудно это понять. - person ioan; 03.06.2013
comment
Я уже час пытаюсь вывести это уравнение. Спасибо. Кто знает, что триггерные личности, которые вы выучили в старшей школе, были бы очень полезны. - person Isioma Nnodum; 29.05.2014
comment
@Dean Нет необходимости в дополнительных скобках из-за приоритета оператора. Когда у вас есть + и *, как в этих двух уравнениях, и без скобок, вы всегда сначала выбираете *, а затем +. - person rbaleksandar; 30.10.2015
comment
@IsiomaNnodum Не могло бы быть так полезно, если бы мы все возвращались сюда, чтобы вспомнить, что это за уравнение. - person b1nary.atr0phy; 08.08.2016

Вот моя реализация на C #:

    public static PointF PointOnCircle(float radius, float angleInDegrees, PointF origin)
    {
        // Convert from degrees to radians via multiplication by PI/180        
        float x = (float)(radius * Math.Cos(angleInDegrees * Math.PI / 180F)) + origin.X;
        float y = (float)(radius * Math.Sin(angleInDegrees * Math.PI / 180F)) + origin.Y;

        return new PointF(x, y);
    }
person Justin Ethier    schedule 08.05.2009
comment
Предварительно вычислите коэффициент преобразования, чтобы уменьшить вероятность того, что вы неправильно введете преобразование, используя жестко запрограммированные числа. - person Scottie T; 08.05.2009

Кому нужен триггер, если у вас есть комплексные числа:

#include <complex.h>
#include <math.h>

#define PI      3.14159265358979323846

typedef complex double Point;

Point point_on_circle ( double radius, double angle_in_degrees, Point centre )
{
    return centre + radius * cexp ( PI * I * ( angle_in_degrees  / 180.0 ) );
}
person Pete Kirkham    schedule 08.05.2009
comment
Как это работает? Как это сравнить по скорости? Почему это не используется чаще? - person Mark A. Ropper; 16.02.2018
comment
@ MarkA.Ropper как работают комплексные числа? - найдите учебник по математике или перейдите на страницу en.wikipedia.org/wiki/Euler%27s_identity если вы уже знаете, что такое комплексное число. Вероятно, это не так эффективно по скорости, как, скажем, реализация sin в качестве справочной таблицы, но иногда вы используете комплексные числа для представления точек повсюду, чтобы использовать другие их свойства. Подобно использованию кватернионов для трехмерного вращения, дело не в скорости, а в возможностях, которые они вам дают. - person Pete Kirkham; 19.02.2018

Реализовано в JavaScript (ES6):

/**
    * Calculate x and y in circle's circumference
    * @param {Object} input - The input parameters
    * @param {number} input.radius - The circle's radius
    * @param {number} input.angle - The angle in degrees
    * @param {number} input.cx - The circle's origin x
    * @param {number} input.cy - The circle's origin y
    * @returns {Array[number,number]} The calculated x and y
*/
function pointsOnCircle({ radius, angle, cx, cy }){

    angle = angle * ( Math.PI / 180 ); // Convert from Degrees to Radians
    const x = cx + radius * Math.sin(angle);
    const y = cy + radius * Math.cos(angle);
    return [ x, y ];

}

Использование:

const [ x, y ] = pointsOnCircle({ radius: 100, angle: 180, cx: 150, cy: 150 });
console.log( x, y );

Codepen

/**
 * Calculate x and y in circle's circumference
 * @param {Object} input - The input parameters
 * @param {number} input.radius - The circle's radius
 * @param {number} input.angle - The angle in degrees
 * @param {number} input.cx - The circle's origin x
 * @param {number} input.cy - The circle's origin y
 * @returns {Array[number,number]} The calculated x and y
 */
function pointsOnCircle({ radius, angle, cx, cy }){
  angle = angle * ( Math.PI / 180 ); // Convert from Degrees to Radians
  const x = cx + radius * Math.sin(angle);
  const y = cy + radius * Math.cos(angle);
  return [ x, y ];
}

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");

function draw( x, y ){

  ctx.clearRect( 0, 0, canvas.width, canvas.height );
  ctx.beginPath();
  ctx.strokeStyle = "orange";
  ctx.arc( 100, 100, 80, 0, 2 * Math.PI);
  ctx.lineWidth = 3;
  ctx.stroke();
  ctx.closePath();

  ctx.beginPath();
  ctx.fillStyle = "indigo";
  ctx.arc( x, y, 6, 0, 2 * Math.PI);
  ctx.fill();
  ctx.closePath();
  
}

let angle = 0;  // In degrees
setInterval(function(){

  const [ x, y ] = pointsOnCircle({ radius: 80, angle: angle++, cx: 100, cy: 100 });
  console.log( x, y );
  draw( x, y );
  document.querySelector("#degrees").innerHTML = angle + "&deg;";
  document.querySelector("#points").textContent = x.toFixed() + "," + y.toFixed();

}, 100 );
<p>Degrees: <span id="degrees">0</span></p>
<p>Points on Circle (x,y): <span id="points">0,0</span></p>
<canvas width="200" height="200" style="border: 1px solid"></canvas>

person Community    schedule 27.02.2020

Вычисление точки по окружности круга с учетом пройденного расстояния.
Для сравнения ... Это может быть полезно в Game AI при движении вокруг твердого объекта по прямому пути.

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

public static Point DestinationCoordinatesArc(Int32 startingPointX, Int32 startingPointY,
    Int32 circleOriginX, Int32 circleOriginY, float distanceToMove,
    ClockDirection clockDirection, float radius)
{
    // Note: distanceToMove and radius parameters are float type to avoid integer division
    // which will discard remainder

    var theta = (distanceToMove / radius) * (clockDirection == ClockDirection.Clockwise ? 1 : -1);
    var destinationX = circleOriginX + (startingPointX - circleOriginX) * Math.Cos(theta) - (startingPointY - circleOriginY) * Math.Sin(theta);
    var destinationY = circleOriginY + (startingPointX - circleOriginX) * Math.Sin(theta) + (startingPointY - circleOriginY) * Math.Cos(theta);

    // Round to avoid integer conversion truncation
    return new Point((Int32)Math.Round(destinationX), (Int32)Math.Round(destinationY));
}

/// <summary>
/// Possible clock directions.
/// </summary>
public enum ClockDirection
{
    [Description("Time moving forwards.")]
    Clockwise,
    [Description("Time moving moving backwards.")]
    CounterClockwise
}

private void ButtonArcDemo_Click(object sender, EventArgs e)
{
    Brush aBrush = (Brush)Brushes.Black;
    Graphics g = this.CreateGraphics();

    var startingPointX = 125;
    var startingPointY = 75;
    for (var count = 0; count < 62; count++)
    {
        var point = DestinationCoordinatesArc(
            startingPointX: startingPointX, startingPointY: startingPointY,
            circleOriginX: 75, circleOriginY: 75,
            distanceToMove: 5,
            clockDirection: ClockDirection.Clockwise, radius: 50);
        g.FillRectangle(aBrush, point.X, point.Y, 1, 1);

        startingPointX = point.X;
        startingPointY = point.Y;

        // Pause to visually observe/confirm clock direction
        System.Threading.Thread.Sleep(35);

        Debug.WriteLine($"DestinationCoordinatesArc({point.X}, {point.Y}");
    }
}
person Community    schedule 24.01.2021