寻找给定圆心、半径和角度的圆上的点

104

距离玩家位置200像素的圆上给定一个-360到360度之间的正或负角度,计算圆上点的位置。屏幕大小为1280x720,其中0,0为屏幕中心点。玩家在整个笛卡尔坐标系中移动。要查找的点可能在屏幕外。

我尝试了文章“查找半径和角度的点”中的公式,但我认为我没有理解“角度”是什么意思,因为当我将角度作为-360到360传递给Cos(angle)或Sin(angle)时,结果很奇怪。

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

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

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

enter image description here enter image description here


1
问题:大多数游戏的坐标不是在左上角为0,0吗?y轴向下,而不是向上? - Persijn
2
对于通过搜索找到这篇文章的任何人:它取决于游戏引擎。不仅如此,在某些引擎中,Y轴是向上的,而在其他引擎中,Z轴是向上的。 - Sven Viking
9个回答

93

你提供链接中的简单方程式给出了圆上点的 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中,以覆盖度数范围以检查公式。现在我的代码可以正常工作了。 - Kyle Anderson
4
“X=xcircle + (r * sine(angle))” 应该改为 “X=xcircle + (r * cosine(angle))”,反之亦然(对于“Y”变量也是如此)。 - txtechhelp
6
请注意,角度应该是一个弧度值! - Roman M

21

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

但是,由于你提到用-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
@monsto 僵尸仍在发送通知。: )。内部括号无所谓,因为乘法和除法是可交换的http://demonstrations.wolfram.com/TheCommutativePropertyOfMultiplication/。我长期以来一直在我的代码中使用过多的括号。我假装这是为了清晰度,但显然这并不严格正确,否则你就不会被它困扰了。 - Seth Battin

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轴开始测量角度

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是角度数。


谢谢!那给了我缺失的部分。应用cos|sin决定方向,而180则表示整个圆。 - AdamsTips

6
当我将角度作为-360到360传递给Cos(angle)或Sin(angle)时,我得到了奇怪的结果。
我认为你尝试失败的原因是你传递的是以度为单位的角度。sin和cos三角函数期望以弧度表示的角度,所以数字应该在0到2 * M_PI之间。对于d度,您传递M_PI * d / 180.0。M_PI是在math.h头文件中定义的常量。

我想角度和度数可能不是同一件事,所以我说角度 = M_PI*d/180.0是否正确,其中d可以是从-360到360的数字,或者我需要另一个步骤? - Kyle Anderson
2
@Kyle d 的取值范围是从 0360 或者从 -180180(一个完整的圆),而不是从 -360360(两个完整的圆)。 - Sergey Kalinichenko

3

这里是C#实现。该方法将返回圆形点,需要 半径中心点角度间隔 作为参数。角度以弧度传递。

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个项!因此,我添加了一些余量,以便最终获得正确数量的项目(我的示例中使用浮点数而不是双精度);for (float interval = angleInterval; interval < 2 * Math.PI + 0.0000099f; interval += angleInterval) - sommmen

1
答案应该完全相反。
X = Xc + rSin(angle)
Y = Yc + rCos(angle)
其中,Xc和Yc是圆的中心坐标,r是半径。

-1

推荐:

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

-5
你可以使用以下公式:
圆的方程为:
(x-k)²+(y-v)²=R²
其中,k和v是常数,R是半径。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接