94

自从我做这样的数学运算以来已经 10 年了……我正在编写 2D 游戏并移动玩家。当我移动玩家时,我试图计算距离玩家位置 200 像素的圆上的点,给定 -360 到 360 之间的正或负角度(度)。屏幕为 1280x720,0,0 为中心点的屏幕。玩家在整个笛卡尔坐标系中移动。我试图找到的点可能不在屏幕上。

我尝试了文章Find the point with radius and angle上的公式,但我不相信我理解“角度”是什么,因为当我将角度作为 -360 到 360 传递给 Cos(angle) 或 Sin 时,我得到了奇怪的结果(角度)。

所以例如我有...

  • 1280x720 在笛卡尔平面上
  • 中心点(球员的位置):
    • 让 x = 最小值 -640 到最大值 640 之间的数字
    • 让 y = 最小值 -360 到最大值 360 之间的数字
  • 玩家周围的圆半径:让 r 始终 = 200
  • 角度:让 a = 一个介于 -360 到 360 之间的数字(允许负数表示向下或正数表示向上,因此 -10 和 350 会给出相同的答案)

在圆上返回 X 的公式是什么?

在圆上返回 Y 的公式是什么?

在此处输入图像描述 在此处输入图像描述

4

10 回答 10

83

链接中的简单方程给出了圆上点相对于圆心的 X 和 Y 坐标。

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

这告诉您该点偏离圆心的距离。由于您有中心的坐标(Cx,Cy),因此只需添加计算出的偏移量。

圆上点的坐标为:

X = Cx + (r * cosine(angle))  
Y = Cy + (r * sine(angle))
于 2012-12-31T00:28:31.687 回答
20

您应该发布您正在使用的代码。这将有助于准确识别问题。

但是,由于您提到用 -360 到 360 来测量角度,因此您的数学库可能使用了不正确的单位。大多数三角函数的实现都使用弧度作为输入。如果你改用度数......你的答案将是奇怪的错误。

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

请注意,您可能还会遇到象限不是您所期望的情况。这可以通过仔细选择角度零的位置来解决,或者通过手动检查您期望的象限并将您自己的符号应用于结果值来解决。

于 2012-12-31T00:27:48.190 回答
7

我强烈建议使用矩阵进行此类操作。这是最通用的方法,请参见下面的示例:

// 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轴
于 2013-01-02T18:34:12.797 回答
6

我还需要它来形成代码中时钟指针的运动。我尝试了几个公式,但它们都不起作用,所以这就是我想出的:

  • 运动 - 顺时针
  • 积分 - 每 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 是度数。

于 2014-12-14T06:45:50.327 回答
5

当我将角度作为 -360 到 360 传递给 Cos(角度)或 Sin(角度)时,我得到了奇怪的结果。

我认为您的尝试无效的原因是您以度数传递角度。sincos三角函数期望以弧度表示的角度,所以数字应该是从02*M_PI。对于d你通过的学位M_PI*d/180.0。是在header 中M_PI定义的常量。math.h

于 2012-12-31T00:28:41.213 回答
3

这是c#实现。该方法将返回以 和 作为参数的radius圆形点centerangle 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);
于 2018-04-19T05:17:04.977 回答
1

我想分享您的上述贡献如何帮助我制作 Arduino LCD 指南针。我希望这是正确的礼仪......我刚刚加入了stackoverflow,所以我要感谢你们这些好人。

当我站在几何巨人的肩膀上时,我能够制作出这个指南针样本: Arduino TFT compass with multiple bearing

我反复调用的函数的代码(对于您在黄色小文本中看到的不同方位)是用 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);

}
于 2018-12-30T19:54:04.577 回答
0

推荐:

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

于 2017-08-15T06:25:13.873 回答
0

答案应该正好相反。

X = Xc + rSin(角度)

Y = Yc + rCos(角度)

其中 Xc 和 Yc 是圆的中心坐标,r 是半径。

于 2017-01-08T03:57:14.000 回答
-3

你可以使用这个:

圆方程

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

其中 k 和 v 是常数,R 是半径

于 2019-08-18T22:57:59.593 回答