8

以前可能已经回答过,如果有,请见谅。我基本上需要从原点到点的角度。所以可以说Origin 是 (0, 0),我的目标点是 (3, 0)

3 点钟 = 90 度

6 点钟 = 180 度

9 点钟 = 270 度

12 点 = 0 度


不知何故,我得做一些数学魔术,发现角度是 90 度(顶部是 0)。 原点可能会有所不同,因此我需要一个具有两个参数 Origin 和 TargetPoint 的方法,它返回以度为单位的双角度。

是的,我意识到这看起来很短且没有建设性,但我使问题尽可能简单易懂。所有其他问题都已关闭-.-

谢谢

4

5 回答 5

13

两点 A 和 B 之间的向量为 BA = (Bx-Ax, By-Ay)。两个向量之间的角度可以用点积atan2来计算。

var vector2 = Target - Origin;
var vector1 = new Point(0, 1) // 12 o'clock == 0°, assuming that y goes from bottom to top

double angleInRadians = Math.Atan2(vector2.Y, vector2.X) - Math.Atan2(vector1.Y, vector1.X);

另请参见查找向量之间的有符号角

于 2013-07-08T15:16:56.690 回答
2

假设x是积极的,是这样的:

angle = Math.Atan(y / x) * 180 / Math.PI + 90

编辑以允许负值x

如果它可能是负面的,请按情况进行。像这样的东西:

if (x < 0) {
    angle = 270 - (Math.Atan(y / -x) * 180 / Math.PI);
} else {
    angle = 90 + (Math.Atan(y / x) * 180 / Math.PI);
}
于 2013-07-08T15:27:34.697 回答
0
public static double GetAngleDegree(Point origin, Point target) {
    var n = 270 - (Math.Atan2(origin.Y - target.Y, origin.X - target.X)) * 180 / Math.PI;
    return n % 360;
}

static void Main(string[] args)
{
    Console.WriteLine(GetAngleDegree(new Point(0, 0), new Point(0, 3)));//0
    Console.WriteLine(GetAngleDegree(new Point(0, 0), new Point(3, 0)));//90
    Console.WriteLine(GetAngleDegree(new Point(0, 0), new Point(0, -3)));//180
    Console.WriteLine(GetAngleDegree(new Point(0, 0), new Point(-3, 0)));//270 
}
于 2013-07-08T15:37:28.373 回答
0

实际上,由于原点为(0,0),因此无法找出点与原点之间的角度。我们可以计算两点之间的角度,因为它们被视为向量,因此它们具有方向,但原点没有方向。出于这个原因,如果您想使用时钟示例找到角度,您可以计算该点与 (1,0) 之间的角度,例如该点为 0 度。

对不起,我不精通 C#,但你可以看看这个类似的 java 代码:

double getAngle2PointsRad(double p1_x, double p1_y, double p2_x, double p2_y) {
  return Math.acos((((p1_x * p2_x) + (p1_y * p2_y)) / (Math.sqrt(Math.pow(p1_x, 2) + Math.pow(p1_y, 2)) * Math.sqrt(Math.pow(p2_x, 2) + Math.pow(p2_y, 2)))));
}

double getAngle2PointsDeg(double p1_x, double p1_y, double p2_x, double p2_y) {
  return Math.acos((((p1_x * p2_x) + (p1_y * p2_y)) / (Math.sqrt(Math.pow(p1_x, 2) + Math.pow(p1_y, 2)) * Math.sqrt(Math.pow(p2_x, 2) + Math.pow(p2_y, 2))))) * 180 / Math.PI;
}

如果您尝试使用 (0,0) 进行计算,您将得到 NaN,因为它试图除以零。

于 2016-06-14T10:25:33.167 回答
0

对于任何可能仍然来看这篇文章的人来说(它对我来说是谷歌的顶峰),我使用了 Sebastian 的 Atan2 作为我的解决方案,并且效果很好。就我而言,我在 Unity 中以编程方式生成参数化图元,因此无论图元是 2D 还是 3D(为了网格顶点),原点始终是 (0, 0, 0)。因此,对于球体,我需要以特定方式对所有顶点进行排序,以便无论参数如何,都可以为网格所需的三角形正确构建 int[]。

我的排序是使用:

this.vertices = vertList.OrderByDescending(o => o.y)
                        .ThenBy(o => Utilities.GetAngle(o)).ToArray();

GetAngle()方法如下所示:

public static float GetAngle(Vector3 v)
{
    return Mathf.Atan2(0, 0) - Mathf.Atan2(v.z, v.x);
}

它可以从上到下对顶点列表进行排序(因此 1 个单位的球体将在 (0f, 0.5f, 0f) 处有一个“顶部”点,这将是第一个顶点),然后按结果排序从沿 X 和 Z 平面的角度计算中浮动。对于Linq.

另一个注意事项:因为它忽略了 Y 平面,所以每个层/层/顶点带位于 Y 上的不同点并不重要 - 它基本上计算每个点,就好像它们只是在y = 0. 如果您尝试对 X/Y 或 Y/Z 进行排序,您可以做同样的事情,只是省略您想要忽略的平面。

这可能不适用于更复杂的情况,或者您的来源不是 (0, 0, 0),但至少对我的情况有效。

于 2021-09-16T17:00:02.683 回答