我将如何计算两个角度之间的差异(以度为单位)?
这对大多数人来说很简单,因为我只是使用:
var difference = Math.Abs(direction1 - direction2);
然而,当方向 2 为北(0 度)且方向 1 为西北(例如 318 度)时,显然这是出路。
计算超过北 (0) 边界的差异的正确方法是什么?
答案 0 :(得分:2)
编辑:这个答案假设方向是向量而不是角度。有关角度,请参阅 Mindswipes answer
一般情况下,您取点积,使用反余弦得到角度,然后乘以 180d / Math.PI
转换为度数。这假设方向是标准化的。
var angleInDegrees = Math.ACos(direction1.Dot(direction2)) * 180d / Math.PI;
这总是在 [0, 180] 范围内产生一个正角。这适用于 2D 和 3D 向量。
如果您使用 2D 向量并且想要在 [0, 360] 中的角度,您可以通过将向量之一旋转 90 度来检查最近的旋转是顺时针还是逆时针,并检查它与另一个的角度是否为小于或大于 90 度:
var isClockwise = direction1.Dot(new Vector(direction2.Y, -direction2.X)) > 0;
如果是顺时针,则结果加上 180 度。反之亦然,具体取决于您的坐标系。
答案 1 :(得分:2)
这很简单,您只需添加一个检查以查看方向(航向)是否大于 180,如果是,则从 360 中减去差值。就像这样:
static int GetHeadingDifference(int heading1, int heading2)
{
var difference = Math.Abs(heading1 - heading2);
if (difference > 180)
return 360 - difference;
return difference;
}
这将返回正确的标题。 Here 演示。
但是您可能希望将其包装在一个自定义对象中,以便为您处理所有事情。你可以这样做:
struct Heading
{
private const float MaxDegrees = 360;
// Use a float for more accurate heading
public float Degree {get; set;}
public Heading(float heading)
{
Degree = heading;
}
// Override addition to wrap around
public static Heading operator +(Heading a, Heading b)
{
var val = (a.Degree + b.Degree) % MaxDegrees;
return new Heading(val);
}
// Override subtraction to always result in a number <= 180
public static Heading operator -(Heading a, Heading b)
{
var difference = Math.Abs(a.Degree - b.Degree);
if (difference > 180)
return new Heading(MaxDegrees - difference);
return new Heading(difference);
}
// Override equality to check the actual degree value
public static bool operator ==(Heading a, Heading b)
{
return a.Degree == b.Degree;
}
// Overriding equality requires overriding inequality
public static bool operator !=(Heading a, Heading b)
{
return !(a == b);
}
// Override Equals to catch explicit a.Equals(b) calls
public override bool Equals(object other)
{
if (other is not Heading)
return false;
return ((Heading) other).Degree == Degree;
}
// When overriding equality you must implement GetHashCode
public override int GetHashCode()
{
// Oerflow is ok here, just wrap
unchecked
{
var hash = 17;
hash = hash * 23 + Degree.GetHashCode();
return hash;
}
}
}
它的工作演示here
P.S 如果您只想拥有一个数字,请使用它,如果您确实有向量,请使用 JonasH's answer