【问题标题】:How do I calculate a point on a circle’s circumference?如何计算圆周上的一点?
【发布时间】:2009-05-08 13:57:13
【问题描述】:

以下功能如何用各种语言实现?

给定输入值,计算圆周上的(x,y) 点:

  • 半径
  • 角度
  • 来源(可选参数,如果语言支持)

【问题讨论】:

    标签: algorithm math trigonometry


    【解决方案1】:

    parametric equation for a circle 是

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

    其中r是半径,cx,cy是原点,a是角度。

    这很容易适应任何具有基本三角函数的语言。 请注意,大多数语言将使用radians 作为三角函数中的角度,因此不是循环通过 0..360 度,而是循环通过 0..2PI 弧度。

    【讨论】:

    • 请注意,a 必须以弧度表示——这对我这个初学者来说真的很难理解。
    • 我已经尝试推导这个方程一个小时了。谢谢。谁知道你在高中学到的三角恒等式会很有帮助。
    • @Dean 由于运算符优先级,不需要额外的括号。当您在这两个等式中有+ 和* 并且没有任何括号时,您总是先选择*,然后再选择+。
    • @IsiomaNnodum 如果我们都回到这里只是为了记住方程式是什么,那就不可能有那么大的帮助了。
    【解决方案2】:

    这是我在 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);
        }
    

    【讨论】:

    • 预先计算转换系数,这样您使用硬编码数字输入转换错误的机会就会减少。
    【解决方案3】:

    当你有complex numbers时谁需要触发:

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

    【讨论】:

    • 这是如何工作的?它如何比较速度?为什么不更常用?
    • @MarkA.Ropper 复数是如何工作的? - 如果您已经知道复数是什么,请查看数学教程或从en.wikipedia.org/wiki/Euler%27s_identity 前往。与将 sin 实现为查找表相比,它的速度可能没有那么高效,但有时您会使用复数来表示整个点以利用它们的其他属性。与使用四元数进行 3D 旋转类似,这并不是真正的速度,而是它们赋予您的能力。
    【解决方案4】:

    在 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>

    【讨论】:

      【解决方案5】:

      在给定距离的圆周上计算点。
      为了比较... 这在游戏 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}");
          }
      }
      

      【讨论】:

        【解决方案6】:
        int x = (int)(radius * Math.Cos(degree * Math.PI / 180F)) + cCenterX;
        int y = (int)(radius * Math.Sin(degree * Math.PI / 180F)) + cCenterY;
        

        cCenterX 和 cCenterY 是圆的中心点

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-05
          相关资源
          最近更新 更多