LoginSignup
2
1

More than 3 years have passed since last update.

点と(直線 or 線分)の距離の2乗 JavaScriptでの実装

Last updated at Posted at 2020-04-04

いろいろやり方はありますが、この記事では一次式の連立方程式を使って考えます。

点と直線の場合

o と p を通る直線に q からおろした垂線の距離の2乗を求めます。

o を p と q からあらかじめ引いておいてやると、計算が楽です。
image.png

以下のように求められます。

const
_Dist2 = ( px, py, qx, qy ) => {
    const num = px * qy - py * qx
    return num * num / ( px * px + py * py )
}
const
Dist2 = ( ox, oy, px, py, qx, qy ) => _Dist2( px - ox, py - oy, qx - ox, qy - oy )

注)o と p が同じ場合 0 / 0 になるので NaN を返します。

参考:点と直線の距離公式の3通りの証明@高校数学の美しい物語

点と線分の場合

交点(X,Y)を求めてそれが線分の内に入っているかどうかチェックします。
X,Y は以下のように求められます。

const den = px * px + py * py
const _ = ( py * qy + px * qx ) / den
const X = px * _
const Y = py * _ 

これの説明は文末につけておきます。

これの X が 0 から px, Y が 0 から py の中に入っていればよさそうです。
ただ、符号の判断が面倒になるので、計算の最初に p が第一象限にあるように鏡像を作ってから考えます。

const
_SegDist2 = ( px, py, qx, qy ) => {
    const den = px * px + py * py
    if ( den == 0 ) return NaN
    if ( px < 0 ) {
        px = -px
        qx = -qx
    }
    if ( py < 0 ) {
        py = -py
        qy = -qy
    }
    const _ = ( py * qy + px * qx ) / den
    const X = px * _
    if ( X < 0 || px < X ) return NaN
    const Y = py * _
    if ( Y < 0 || py < Y ) return NaN
    const num = px * qy - py * qx
    return num * num / den
}
const
SegDist2 = ( ox, oy, px, py, qx, qy ) => _SegDist2( px - ox, py - oy, qx - ox, qy - oy )

q から op に降ろせる点がない場合 NaN を返しているので、Number.isNaN() で判定してください。

交点の求め方

プログラムっぽく書いてみました。

    直線

        py  
    Y = -- X
        px  

    に直行する直線は

          px  
    Y = - -- X + c 
          py  

    これが、qx, qy を通るから

           px  
    qy = - -- qx + c 
           py  

    すなわち

          px          px  
    Y = - -- X + qy + -- qx
          py          py  

    なので交点は

    py       px          px  
    -- X = - -- X + qy + -- qx
    px       py          py  

        px * ( px * qx + py * qy )
    X = --------------------------
            px * px + py * py

        py * ( px * qx + py * qy )
    Y = --------------------------
            px * px + py * py
2
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1