不确定如何使标题更具描述性,所以我将从一个例子开始。我正在使用下面的代码,从枚举中选择一个方向,这取决于四个轴中哪一个与给定方向相比形成最小角度。
static Direction VectorToDirection(Vector2 direction)
{
double upDiff = System.Math.Acos(Vector2.Dot(direction, -Vector2.UnitY));
double downDiff = System.Math.Acos(Vector2.Dot(direction, Vector2.UnitY));
double leftDiff = System.Math.Acos(Vector2.Dot(direction, -Vector2.UnitX));
double rightDiff = System.Math.Acos(Vector2.Dot(direction, Vector2.UnitX));
double smallest = System.Math.Min(System.Math.Min(upDiff, downDiff), System.Math.Min(leftDiff, rightDiff));
// This is the part I'm unsure about i.e.
// Comparing smallest with each value in turn
// To find out which of the four was "selected"
if (smallest == upDiff) return Direction.Up;
if (smallest == downDiff) return Direction.Down;
if (smallest == leftDiff) return Direction.Left;
return Direction.Right;
}
但是我在最后得到了关于浮点平等的Resharper警告。由于Min
的实现,我猜它不应该是一个问题,但是想知道是否有更好的习惯用来解决这类问题除了比较 {{1}与每个原始值。
答案 0 :(得分:2)
此代码可以为您提供所需的结果。
if ((Math.Abs(direction.x) >= Math.Abs(direction.y))
return direction.x >= 0 ? Direction.Right : Direction.Left;
return direction.y >= 0 ? Direction.Up : Direction.Down;
答案 1 :(得分:1)
您可以制作<double ,Direction>
sort the dictionary 字典,并使用正确的枚举获取最小值。
答案 2 :(得分:1)
你可以定义一个包含diff和与之关联的值的类。 然后从这些对象中创建一个集合,并按差异对它们进行排序。之后 返回与第一个元素关联的值。
但是,在你的情况下,我不会去那里,代码很清楚。如果可能值的数量要大得多(或者事先不知道),那么我才会寻求更通用的解决方案。
答案 3 :(得分:1)
你能写一些if语句吗?
if (upDiff < leftDiff && upDiff < downDiff && upDiff < rightDiff) return Direction.Up;
if (leftDiff < upDiff && leftDiff < downDiff && leftDiff < rightDiff) return Direction.Left;
if (rightDiff < leftDiff && rightDiff < upDiff && rightDiff < downDiff) return Direction.Right;
return Direction.Down;
也许它可以进一步清理,但这似乎是直截了当的。
答案 4 :(得分:1)
我会将所有选项放在一个数组中并找到min index。对于4种选择,排序可能是过度杀伤。如果此代码的执行很重要 - 请确保测量不同变体的时间。
以下未编译的代码:
static Direction VectorToDirection(Vector2 direction)
{
var directions = new Direction[]{
Direction.Up, Direction.Down, Direction.Right, Direction.Left };
var unit = new Vector2[] {
-Vector2.UnitY, Vector2.UnitY, Vector2.UnitX,-Vector2.UnitY};
var minAngle = 10;
var minIndex = -1;
for(var index = 0; index < directions.length; index++)
{
double diff = System.Math.Acos(Vector2.Dot(direction, unit[index]));
if (diff < minAngle)
{
minAngle = diff;
minIndex = index;
}
return directions[minIndex];
}
答案 5 :(得分:1)
static Direction VectorToDirection(Vector2 direction)
{
var mappings = new[]
{
new { Direction = Direction.Up, Axis = -Vector2.UnitY },
new { Direction = Direction.Down, Axis = Vector2.UnitY },
new { Direction = Direction.Left, Axis = -Vector2.UnitX },
new { Direction = Direction.Right, Axis = Vector2.UnitX }
};
return mappings.OrderBy(m => Math.Acos(Vector2.Dot(direction, m.Axis))).Select(m => m.Direction).First();
}
Linq方式。这没有经过测试,但你应该得到它。
答案 6 :(得分:0)
设置不准确
if ((Math.Abs(smallest - upDiff) < 0.00001) return Direction.Up;
答案 7 :(得分:0)
你正在做,我认为不会有任何错误。但是,如果您将来最终重构或更改代码,则可能会遇到一些问题。
为了安全起见,只需做一下resharper的建议。
答案 8 :(得分:0)
我通常使用switch
代替if-else
(至少3条款) - 有点简洁和快捷。
switch(smallest) {
case upDiff: return Direction.Up;
case downDiff: return Direction.Down;
case leftDiff: return Direction.Left;
default: return Direction.Right;
}