3 つの点 (A、B、X) と距離 (d) があります。点 X が距離 d より線分 AB 上の任意の点に近いかどうかをテストする関数を作成する必要があります。
問題は、まず、私の解決策が正しいかどうか、そしてより良い (より速い) 解決策を考え出すことです。
私の最初のパスは次のとおりです
AX = X-A
BX = X-B
AB = A-B
// closer than d to A (done squared to avoid needing to compute the sqrt in mag)
If d^2 > AX.mag^2 return true
// closer than d to B
If d^2 > BX.mag^2 return true
// "beyond" B
If (dot(BX,AB) < 0) return false
// "beyond" A
If (dot(AX,AB) > 0) return false
// find component of BX perpendicular to AB
Return (BX.mag)^2 - (dot(AB,BX)/AB.mag)^2 < d^2
このコードは、少なくとも 1 つの A/B/d に合格するすべての P を見つけることを目的として、P の大規模なセットと A/B/d トリプレットの大規模なセットに対して実行されることになるため、方法があると思われます。それに基づいて全体的なコストを削減しますが、まだ調べていません。
(ところで:いくつかの並べ替え、いくつかの一時的な値、およびいくつかの代数恒等式が上記のコストを削減できることを認識しています。明確にするためにそれらを省略しました。)
編集: これは 2D の問題です (ただし、3D に一般化するソリューションはクールです
編集: さらに考えてみると、ヒット率は約 50% になると予想しています。X ポイントはネストされた階層で形成できるため、大きなサブツリーをすべてパスおよびすべて失敗としてプルーニングできると期待しています。トリプレットを制限する A/B/d は、より多くのトリックになります。
編集:dはABと同じ大きさのオーダーです。
編集: Artelius がすばらしい解決策を投稿しました。私が完全に理解する前に接線を外れてしまったので、彼が何をしようとしているのか正確に理解しているかどうかはわかりません. とにかく、結果として別の考えが頭に浮かびました:
- 最初の Artelius のビットは、AB を原点の中心に配置し、X 軸に合わせて配置する行列を事前に計算します。(2回追加、4回追加、2回追加)
- すべてを第 1 象限 (2 つの腹筋) に折りたたむ
- ゾーンの中央部分を単位正方形 (2 mul) にするために X&Y でスケーリングします。
- ポイントがその正方形にあるかどうかをテストする (2 テスト)
- エンド キャップをテストします (スケーリングされていない値に戻ります
- 端を原点に配置するために x に変換します (1 追加)
- 2 乗して加算 (2 mul、1 加算)
- d^2 (1 cmp) と比較
これが私のソリューションよりも優れていると確信しています。
(これ以上のものがなければ、アルテリウスが「賞」を獲得します:)