4

タイトルをより説明的にする方法がわからないので、例から始めます。以下のコードを使用して、特定の方向と比較して最小の角度を形成する 4 つの軸に応じて、列挙型から方向を選択します。

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、この種の問題を解決するためのより良いイディオムがあるのではないかと考えていました。 smallest

4

9 に答える 9

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;
于 2012-08-06T18:02:18.797 に答える
1

すべての選択肢を配列に入れて、最小インデックスを見つけます。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];
}
于 2012-08-06T18:09:27.213 に答える
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();
}

リンクのやり方。これはテストされていませんが、取得する必要があります。

于 2012-08-06T18:09:45.093 に答える
1

辞書を<double ,Direction> 並べ替える辞書を作成し、正しい列挙型で最小値を取得して返すことができます。

于 2012-08-06T17:59:55.087 に答える
1

差分とそれに関連付けられた値を含むクラスを定義できます。次に、これらのオブジェクトからコレクションを作成し、差分で並べ替えます。その後、最初の要素に関連付けられた値を返します。

ただし、あなたの場合はそこには行きません。コードはそのまま明確です。可能な値の量がはるかに大きい (または事前にわからない) 場合にのみ、より一般的なソリューションを使用します。

于 2012-08-06T18:03:02.747 に答える
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;

さらにクリーンアップできるかもしれませんが、これは簡単なようです。

于 2012-08-06T18:05:31.197 に答える
0

あなたがやっているので、エラーはないと思います。ただし、将来的にコードをリファクタリングまたは変更すると、いくつかの問題が発生する可能性があります。

安全のために、resharper が提案することを実行してください。

于 2012-08-06T18:01:06.457 に答える
0

不正確な設定

if ((Math.Abs(smallest - upDiff) < 0.00001) return Direction.Up;
于 2012-08-06T17:56:27.133 に答える
0

私は通常、(少なくとも3つの句)switchの代わりに使用しますif-else-やや簡潔で高速です。

switch(smallest) {
  case upDiff: return Direction.Up;
  case downDiff: return Direction.Down;
  case leftDiff: return Direction.Left;
  default: return Direction.Right; 
}
于 2012-08-06T18:03:04.510 に答える