点と直線の距離を求める

HOME>>メモ>>図形処理の基礎>>点と直線の距離を求める

陰関数で表わす

距離を求める

直線の表し方にはいろいろありますが、ここでは最初に陰関数表示で考えてみます。 陰関数表示というのはこんな感じ表示方法です。 \[ ax + by + c = 0 \] わかっているとは思いますが、$a$,$b$,$c$が直線を表わすパラメータです。 この直線と、点P$(x_\mathrm{P}$,$y_\mathrm{P})$との距離を考えてみます。

と、言ってもいきなりこの直線との距離を考えるのは面倒なので、次のような原点を通る直線との距離を考えましょう。 \[ ax + by = 0 \] さて、この距離を考える問題ですが、ベクトルの内積を使うと簡単に解けてしまいます。 ベクトル$\overrightarrow{v}=(a,b)$、直線上の位置ベクトルを$\overrightarrow{r}=(x,y)$、 点Pの位置ベクトルを$\overrightarrow{p}=(x_\mathrm{P},y_\mathrm{P})$としましょう。 そしてこの直線の方程式をよく見ると、内積の形をしており、次のように書き直せます。

\[ \overrightarrow{v} \cdot \overrightarrow{r} = 0 \]

ベクトルの内積=0と言うことは2つのベクトルが直交していることを意味します。 したがって、この直線は原点を通りベクトル$\overrightarrow{v}$に直交する直線を表わしています。 図にすると下のようになります。

陰関数表示の直線の図

図から、ベクトル$\overrightarrow{v}$$\overrightarrow{p}$の角度を$\theta$とすると、 点と直線の距離$d$は次のようにかけます。 \[ d = |\overrightarrow{p}||\cos\theta| \] 内積の定義を思い出すとさらに \[ d = \frac{|\overrightarrow{v}\cdot\overrightarrow{p}|}{|\overrightarrow{v}|} = \frac{|ax_\mathrm{P}+by_\mathrm{P}|}{\sqrt{a^2+b^2}} \] と変形できます。

ここまでの導出は、原点を通る直線限定だったので、任意の直線について考えて見ます。 平行移動し、点$\mathrm{P_0}$位置ベクトル$\overrightarrow{p_0}=(x_0, y_0)$を通るように直線の式を書き直します。 \begin{eqnarray*} \overrightarrow{v} \cdot (\overrightarrow{r}-\overrightarrow{p_0}) &=& \overrightarrow{v} \cdot \overrightarrow{r}- \overrightarrow{v} \cdot \overrightarrow{p_0} \\ &=& ax + by - (ax_0 + by_0) = 0 \end{eqnarray*} ここで、$c=-\overrightarrow{v} \cdot \overrightarrow{p_0}=-(ax_0 + by_0)$とおけば、一番初めの方程式になります。 同様に距離の式も書き直してみます。$c$の定義に注意すれば、 \begin{eqnarray*} d &=& \frac{|\overrightarrow{v}\cdot(\overrightarrow{p}-\overrightarrow{p_0})|}{|\overrightarrow{v}|} \\ &=& \frac{|\overrightarrow{v}\cdot\overrightarrow{p}-\overrightarrow{v}\overrightarrow{p_0}|}{|\overrightarrow{v}|} \\ &=& \frac{|ax_\mathrm{P}+by_\mathrm{P}+c|}{\sqrt{a^2+b^2}} \end{eqnarray*} となります。これで、よく教科書に出てくる点と直線の距離の公式が導き出せました。

ちなみに、絶対値をとる前の$d$の符号は、点が直線のどちら側にあるかを表わします。 符号が正なら$\overrightarrow{v}$と同じ側、負なら反対側にあるとわかります。

一番近い点を求める

距離が求まると直線上でもっとも近い点を求めることができます。 求める点を点Hとすると、PHと向きが同じ単位ベクトルは$-\overrightarrow{v}/|\overrightarrow{v}|$とかけます。 このベクトルに点Pと直線の距離を書けると、PHベクトルとなります。これから、点Hの位置ベクトルは \[ \overrightarrow{p}-\frac{ax_\mathrm{P}+by_\mathrm{P}+c}{\sqrt{a^2+b^2}}\frac{\overrightarrow{v}}{|\overrightarrow{v}|} =\overrightarrow{p}-\frac{ax_\mathrm{P}+by_\mathrm{P}+c}{a^2+b^2}\overrightarrow{v} \] となります。これを成分表示すると、次のようになります。 \begin{eqnarray*} x &=& x_\mathrm{p} - a\frac{ax_\mathrm{P}+by_\mathrm{P}+c}{a^2+b^2} \\ y &=& y_\mathrm{p} - b\frac{ax_\mathrm{P}+by_\mathrm{P}+c}{a^2+b^2} \end{eqnarray*}

媒介変数表示で表わす

距離を求める

さて、ここまでは陰関数表示で直線の式を表したわけですが、次に、 媒介変数を使ったパラメトリックな表現方法を考えてみます。 \begin{eqnarray*} x &=& at + x_0\\ y &=& bt + y_0 \end{eqnarray*} ベクトル表現を使うと次のように表現できます。 \[ \overrightarrow{r} = \overrightarrow{v}t + \overrightarrow{p_0} \] この表現方法なら$t$の範囲を指定することによって、線分を作ることができるのでいろいろと便利そうです。

この直線と点の距離を考えてみましょう。 直線と点の関係を図にすると次のようになります。

媒介変数表示の直線の図

二次元ベクトルの外積の定義$\overrightarrow{a}\times\overrightarrow{b}=|\overrightarrow{a}||\overrightarrow{b}|\sin\theta=x_ay_b-y_ax_b$ を使うと、距離$d$は次式のようになります。 \begin{eqnarray*} d &=& |\overrightarrow{p}-\overrightarrow{p_0}||\sin\theta| \\ &=& \frac{|\overrightarrow{v}\times(\overrightarrow{p}-\overrightarrow{p_0})|}{|\overrightarrow{v}|} \\ &=& \frac{|a(y_\mathrm{P}-y_0)-b(x_\mathrm{P}-x_0)|}{\sqrt{a^2+b^2}} \end{eqnarray*}

一番近い点を求める

直線上で点Pもっとも近い点を求めることも簡単にできます。 \begin{eqnarray*} |\overrightarrow{v}|t &=& |\overrightarrow{p}-\overrightarrow{p_0}|\cos\theta \\ &=& \frac{\overrightarrow{v}\cdot(\overrightarrow{p}-\overrightarrow{p_0})}{|\overrightarrow{v}|} \\ &=& \frac{a(x_\mathrm{P}-x_0)+b(y_\mathrm{P}-y_0)}{\sqrt{a^2+b^2}} \end{eqnarray*} これから、 \[ t=\frac{a(x_\mathrm{P}-x_0)+b(y_\mathrm{P}-y_0)}{a^2+b^2} \] の点が直線上で点Pもっとも近い点になります。 この点と点Pを結べば垂線を引くこともできます。

実際にやってみよう

実際にやってみました。 SVGにJavascriptを埋め込んで簡単なアニメーションを作ってみました。 黒の直線とバツが与えられた直線と点、赤い円が半径=dの円、青い線分が垂線です。
SVGファイルをダウンロードする

残念ながら現在使用しているブラウザでは表示できません。 IE以外のブラウザの最新版をダウンロードしてください。