11

角度のサイン/コサインを見つける速度を上げるために、その場で計算する代わりに参照テーブルを作成しました。ある点から別の点への角度を見つけることと同じ考えを持っています。

3600 の正規化されたベクトルのテーブルを作成しました (3600 / 10 = 10 分の 1 度の精度)。ある点から次の点までの角度を知る必要があるときはいつでも、テーブルを調べて最適な一致を見つけます。ただし、これは math.atan2() を使用するよりも遅くなる可能性があることを懸念しています。

私が使用しているコードは次のとおりです。

ベクター テーブルを作成します。

// vector to angle table
var vectorToAngleTable = new Array();
for (i = 0; i < 3600; i += 1) {
    vectorToAngleTable[i] = new Vector2();
    vectorToAngleTable[i] = RotatePoint(forwardVector, i / 10);
}

2 点からの角度を求めます。

function NormalizeVector(vector) {
    var toReturn = vector;
    var dist = Math.sqrt(vector.x * vector.x + vector.y * vector.y);
    toReturn.x /= dist.x;
    toReturn.y /= dist.y;
    return toReturn;
}

function PointDirection(position, target) {
    var vector = target;
    var toReturn = 0;
    var smallest = 1.0;
    vector.x -= position.x;
    vector.y -= position.y;
    vector = NormalizeVector(vector);
    for (i = 0; i < 3600; i += 1) {
        if (PointDistance(vectorToAngleTable[i], vector) < smallest) {
            smalllest = PointDistance(vectorToAngleTable[i], vector);
            toReturn = i;
        }
    }
    return toReturn;
}

function PointDistance(point1, point2) {
    return Math.sqrt(((point2.x - point1.x) * (point2.x - point1.x)) + ((point2.y - point1.y) * (point2.y - point1.y)));
}

ご覧のとおり、私の関心事は、それが通過するすべてのコード行と、通過するテーブルにいくつのエントリがあるかです。方法が何であれ、角度を見つけるための最速の方法を知りたいです。

4

2 に答える 2

13

としてangle(v1, v2) = acos( (v1x * v2x + v1y * v2y) / (sqrt(v1x^2+v1y^2) * sqrt(v2x^2+v2y^2)) )、私たちは知っていますv2 = [1, 0]

var v = {x: 0, y: 1},
    angleRad = Math.acos( v.x / Math.sqrt(v.x*v.x + v.y*v.y) ),
    angleDeg = angleRad * 180 / Math.PI;

vベクトルはどこですか[point2.x - point1.x , point2.y - point1.y]


編集-私はあなたが各点をベクトルとして扱うことを意味しているかもしれないことに気づきました、その場合それは

var v1 = {x: 0, y: 1}, v2 = {x: 1, y: 0},
    angleRad = Math.acos( (v1.x * v2.x + v1.y * v2.y) / ( Math.sqrt(v1.x*v1.x + v1.y*v1.y) * Math.sqrt(v2.x*v2.x + v2.y*v2.y) ) ),
    angleDeg = angleRad * 180 / Math.PI;

ここv1で、はベクトル[point1.x , point1.y]でありv2[point2.x , point2.y]


編集2
ベクトルの長さを何度も使用している場合に高速化するには、たとえばv.length = ...、再計算せずに取得できるように保存します。すべてのベクトルで角度を複数回計算する必要があることがわかっている場合は、私が作成した最初の方法を使用してキャッシュしv.angle = ...ます。v2.angle - v1.angle次に、2つの間の角度を見つけるために
行うことができます。

function Vector(x, y){
    this.x = x;
    this.y = y;
    this.length = Math.sqrt(x*x + y*y);
    this.angle = Math.acos( x / this.length );
}

acosを直接3601使用するのではなく、アイテムの配列を事前に計算して検索するjsperf

于 2012-10-15T20:48:09.677 に答える
1

これは の呼び出しよりも確実に小さくなりますatan2。これは、平方根と 3600 の可能性の線形検索であるためです。逆に、多くのプロセッサは atan2 を直接実装しています。Intel ランドでは FPATAN です。

于 2012-10-15T20:42:58.623 に答える