実際のユークリッド角度は必要ないが、角度比較のベースとして使用できるものは必要ない場合は、タクシー ジオメトリに変更することをお勧めします。これは、三角法を削除でき、精度を維持しながら速度が低下するためです (または少なくとも精度がわずかに失われます。以下を参照してください)。
最新の主なブラウザ エンジンでは、高速化係数は 1.44 ~ 15.2 で、精度は atan2 とほぼ同じです。ひし形の角度の計算は、atan2 よりも平均 5.01 倍速く、Firefox 18 でインライン コードを使用すると、速度は 15.2 倍に達します。速度比較: http://jsperf.com/diamond-angle-vs-atan2/2 .
コードは非常に単純です。
function DiamondAngle(y, x)
{
if (y >= 0)
return (x >= 0 ? y/(x+y) : 1-x/(-x+y));
else
return (x < 0 ? 2-y/(-x-y) : 3+x/(x-y));
}
次の表に示すように、上記のコードは 0 から 4 の間の角度を提供しますが、atan2 は -PI と PI の間の角度を提供します。

ひし形の角度は常に正で、0 ~ 4 の範囲であることに注意してください。一方、atan2 は負のラジアンも与えます。そのため、ダイヤモンドの角度はより正規化されています。また、atan2 では、範囲の長さが 2*pi (つまり、6.283185307179586) であるのに対し、ダイヤモンドの角度では 4 であるため、もう少し正確な結果が得られることに注意してください。実際には、これはあまり重要ではありません。rad 2.3000000000000001 と 2.3000000000000002 はどちらもダイヤモンド角度 1.4718731421442295 ですが、0 を 1 つ削除して精度を下げると、rad 2.30000000000001 と 2.300000000000002 は両方とも異なるダイヤモンド角度になります。このダイヤモンド角度の「精度の低下」は非常に小さいため、距離が大きい場合にのみ大きな影響を与えます。http://jsbin.com/bewodonase/1/edit?outputで変換を試すことができます(旧バージョン:http://jsbin.com/idoyon/1 ):

上記のコードは角度をすばやく比較するには十分ですが、多くの場合、ダイヤモンドの角度をラジアンに、またはその逆に変換する必要があります。あなたが例えば。ラジアン角度としてある程度の許容範囲があり、この許容範囲が他の角度と比較される 100,000 回のループがある場合、atan2 を使用して比較を行うのは賢明ではありません。代わりに、ループする前に、ラジアン許容値をタクシー (ダイヤモンド角度) 許容値に変更し、ダイヤモンド許容値を使用してループ内比較を行います。このようにして、コードの速度が重要な部分で低速の三角関数を使用する必要がなくなります ( = inループ)。
この変換を行うコードは次のとおりです。
function RadiansToDiamondAngle(rad)
{
var P = {"x": Math.cos(rad), "y": Math.sin(rad) };
return DiamondAngle(P.y, P.x);
}
お気づきのように と がcos
ありsin
ます。ご存知のように、それらは遅いですが、ループ内で変換を行う必要はありませんが、ループする前に行うと、速度が大幅に向上します。
何らかの理由で、ダイヤモンドの角度をラジアンに変換する必要がある場合。ループして角度比較を行った後、たとえば返されます。比較の最小角度またはラジアンなど、コードは次のとおりです。
function DiamondAngleToRadians(dia)
{
var P = DiamondAngleToPoint(dia);
return Math.atan2(P.y,P.x);
}
function DiamondAngleToPoint(dia)
{
return {"x": (dia < 2 ? 1-dia : dia-3),
"y": (dia < 3 ? ((dia > 1) ? 2-dia : dia) : dia-4)};
}
ここでは を使用していますがatan2
、これは遅いですが、ループの外側でこれを使用することをお勧めします。単純に何らかの係数を掛けてダイアモンド角度をラジアンに変換することはできませんが、代わりに、その点と正の X 軸の間のダイアモンド角度が問題のダイアモンド角度であるタクシー ジオメトリの点を見つけ、atan2 を使用してこの点をラジアンに変換します。
これは、迅速な角度比較には十分なはずです。
もちろん、他のatan2高速化技術(CORDICやルックアップテーブルなど)がありますが、知る限り、それらはすべて精度を失い、atan2よりも遅い場合があります。
背景: 内積、内積、コサインの法則、単位円、ルックアップ テーブルなど、いくつかの手法をテストしましたが、速度と精度の両方が重要な場合には十分ではありませんでした。最後に、http://www.freesteel.co.uk/wpblog/2009/06/encoding-2d-angles-without-trigonometry/で、目的の機能と原理を備えたページを見つけました。
最初に、ユークリッドの距離が大きいほどタクシーでも距離が大きくなるため、タクシーの距離も正確かつ迅速な距離比較に使用できると想定しました。ユークリッド距離とは逆に、始点と終点の間の角度がタクシーの距離に影響を与えることに気付きました。ユークリッドとタクシーの間で簡単かつ迅速に変換できるのは、垂直方向と水平方向のベクトルの長さだけですが、それ以外の場合は角度を考慮する必要があり、プロセスが遅すぎます (?)。
結論として、角度および/または距離のいくつかの比較のループまたは再帰である速度が重要なアプリケーションでは、角度はタクシー空間で比較し、距離はユークリッド (平方、平方根を使用せずに) 空間で比較する方が速いと考えています。