点(x, y)と線分(点A(x1, y1)と点B(x2, y2)を結ぶ線分)の最短距離を求めます。いろいろなやり方があるかもしれませんが、鳩は以下のように考えました。
Contents
平行移動と回転移動で最短距離を求める
全体を平行移動させて点Aが原点にくるようにする
原点とX軸の正の部分と移動させた点Bで構成される角の角度を求める
全体をこの角度だけ逆方向に回転させる(これによって点BがX軸上にくる)
直線ABと点の距離であれば回転させた点のY座標の絶対値が距離となる
直線ABではなく線分ABとの距離であれば回転させた点のX座標によって切り分けが必要
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31  | 
						public class Program {     static double Solve(long x, long y, long x1, long y1, long x2, long y2)     {         // 並行移動させる         x -= x1;         y -= y1;         x2 -= x1;         y2 -= y1;         x1 = 0;         y1 = 0;         // 回転させる角度を求める         double angle = Math.Atan2(y2, x2);         angle *= -1; // 逆方向に回転させるので         double rotatedX2 = x2 * Math.Cos(angle) - y2 * Math.Sin(angle);         double rotatedY2 = x2 * Math.Sin(angle) + y2 * Math.Cos(angle);         // rotatedY2 は 0になっているはず         double rotatedX = x * Math.Cos(angle) - y * Math.Sin(angle);         double rotatedY = x * Math.Sin(angle) + y * Math.Cos(angle);         if (rotatedX < 0)             return Math.Sqrt(Math.Pow(rotatedX, 2) + Math.Pow(rotatedY, 2));         else if (rotatedX2 < rotatedX)             return Math.Sqrt(Math.Pow(rotatedX - rotatedX2, 2) + Math.Pow(rotatedY, 2));         else             return Math.Abs(rotatedY);     } }  | 
					
内積を使う方法
他に線分と点の内積を使う方法があります。点Bから点AをベクトルBA、点Bから点CをベクトルBCとしたとき、ベクトルBAとベクトルBCの内積は xa × xc + ya × yc になります。またこの内積は(ベクトルBAの大きさ)×(ベクトルBCの大きさ)×cos∠ABCとなります。内積が負数になる場合は∠ABCが直角より大きくなっているので点Aから線分BCへ垂線を下ろすことができません。
内積が正になる場合

内積が負になる場合(この場合は明らかに点から下ろした垂線は線分と交わらない)

ということはベクトルBAとベクトルBCの内積が負数の場合、点Aからもっとも近いのは点Bということになります。またベクトルCAとベクトルCBの内積が負数の場合は、点Aからもっとも近いのは点Cということになります。それ以外の場合は点Aから線分BCへ垂線を下ろしたときの交点と点Aの距離が求める距離ということになります。
点Aから線分BCへ垂線を下ろした場合、直角三角形ができます。

三角比より垂線の長さは(BAの長さ)×sin∠ABCです。またベクトルBAとベクトルBCの内積は(BAの長さ)×(BCの長さ)×cos∠ABCであり、xa × xc + ya × ycです。双方を二乗するとsinとcosの2乗ができて、sin2乗 + cos2乗 = 1 なので三角関数を消すことができます。垂線の長さは(BAの長さ)と(BCの長さ)と(xa × xc + ya × yc)で表わすことができます。(BAの長さの2乗)- (内積の2乗)/(BCの長さの2乗)の平方根が求める距離となります。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21  | 
						    static double Solve2(long x, long y, long x1, long y1, long x2, long y2)     {         // 並行移動させて点B(x1, y1)を原点にする         x -= x1;         y -= y1;         x2 -= x1;         y2 -= y1;         x1 = 0;         y1 = 0;         double dot = x * x2 + y * y2;         if (dot < 0)             return Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2));         double dot2 = (x - x2) * (0 - x2) + (y - y2) * (0 - y2);         if (dot2 < 0)             return Math.Sqrt(Math.Pow(x - x2, 2) + Math.Pow(y - y2, 2));         double a2 = Math.Pow(x, 2) + Math.Pow(y, 2);         double b2 = Math.Pow(x2, 2) + Math.Pow(y2, 2);         return Math.Sqrt(a2 - Math.Pow(dot, 2) / b2);     }  | 
					
