記錄一下演算法:點到線段的距離計算。
C#版
public double PointLine_Disp(double xx, double yy, double x1, double y1, double x2, double y2)
{
double a, b, c, ang1, ang2, ang, m;
double result = 0;
//分別計算三條邊的長度
a = Math.Sqrt((x1 - xx) * (x1 - xx) + (y1 - yy) * (y1 - yy));
if (a == 0)
return -1;
b = Math.Sqrt((x2 - xx) * (x2 - xx) + (y2 - yy) * (y2 - yy));
if (b == 0)
return -1;
c = Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
//如果線段是一個點則退出函式並返回距離
if (c == 0)
{
result = a;
return result;
}
//如果點(xx,yy到點x1,y1)這條邊短
if (a < b)
{
//如果直線段AB是水平線。得到直線段AB的弧度
if (y1 == y2)
{
if (x1 < x2)
ang1 = 0;
else
ang1 = Math.PI;
}
else
{
m = (x2 - x1) / c;
if (m - 1 > 0.00001)
m = 1;
ang1 = Math.Acos(m);
if (y1 >y2)
ang1 = Math.PI*2 - ang1;//直線(x1,y1)-(x2,y2)與折X軸正向夾角的弧度
}
m = (xx - x1) / a;
if (m - 1 > 0.00001)
m = 1;
ang2 = Math.Acos(m);
if (y1 > yy)
ang2 = Math.PI * 2 - ang2;//直線(x1,y1)-(xx,yy)與折X軸正向夾角的弧度
ang = ang2 - ang1;
if (ang < 0) ang = -ang;
if (ang > Math.PI) ang = Math.PI * 2 - ang;
//如果是鈍角則直接返回距離
if (ang > Math.PI / 2)
return a;
else
return a * Math.Sin(ang);
}
else//如果(xx,yy)到點(x2,y2)這條邊較短
{
//如果兩個點的縱座標相同,則直接得到直線斜率的弧度
if (y1 == y2)
if (x1 < x2)
ang1 = Math.PI;
else
ang1 = 0;
else
{
m = (x1 - x2) / c;
if (m - 1 > 0.00001)
m = 1;
ang1 = Math.Acos(m);
if (y2 > y1)
ang1 = Math.PI * 2 - ang1;
}
m = (xx - x2) / b;
if (m - 1 > 0.00001)
m = 1;
ang2 = Math.Acos(m);//直線(x2-x1)-(xx,yy)斜率的弧度
if (y2 > yy)
ang2 = Math.PI * 2 - ang2;
ang = ang2 - ang1;
if (ang < 0) ang = -ang;
if (ang > Math.PI) ang = Math.PI * 2 - ang;//交角的大小
//如果是對角則直接返回距離
if (ang > Math.PI / 2)
return b;
else
return b * Math.Sin(ang);//如果是銳角,返回計算得到的距離
}
}
JS版
<script type="text/javascript">
function PointLine_Disp(xx, yy, x1, y1, x2, y2)
{
var a, b, c, ang1, ang2, ang, m;
var result = 0;
//分別計算三條邊的長度
a = Math.sqrt((x1 - xx) * (x1 - xx) + (y1 - yy) * (y1 - yy));
if (a == 0)
return -1;
b = Math.sqrt((x2 - xx) * (x2 - xx) + (y2 - yy) * (y2 - yy));
if (b == 0)
return -1;
c = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
//如果線段是一個點則退出函式並返回距離
if (c == 0)
{
result = a;
return result;
}
//如果點(xx,yy到點x1,y1)這條邊短
if (a < b)
{
//如果直線段AB是水平線。得到直線段AB的弧度
if (y1 == y2)
{
if (x1 < x2)
ang1 = 0;
else
ang1 = Math.PI;
}
else
{
m = (x2 - x1) / c;
if (m - 1 > 0.00001)
m = 1;
ang1 = Math.acos(m);
if (y1 >y2)
ang1 = Math.PI*2 - ang1;//直線(x1,y1)-(x2,y2)與折X軸正向夾角的弧度
}
m = (xx - x1) / a;
if (m - 1 > 0.00001)
m = 1;
ang2 = Math.acos(m);
if (y1 > yy)
ang2 = Math.PI * 2 - ang2;//直線(x1,y1)-(xx,yy)與折X軸正向夾角的弧度
ang = ang2 - ang1;
if (ang < 0) ang = -ang;
if (ang > Math.PI) ang = Math.PI * 2 - ang;
//如果是鈍角則直接返回距離
if (ang > Math.PI / 2)
return a;
else
return a * Math.sin(ang);
}
else//如果(xx,yy)到點(x2,y2)這條邊較短
{
//如果兩個點的縱座標相同,則直接得到直線斜率的弧度
if (y1 == y2)
if (x1 < x2)
ang1 = Math.PI;
else
ang1 = 0;
else
{
m = (x1 - x2) / c;
if (m - 1 > 0.00001)
m = 1;
ang1 = Math.acos(m);
if (y2 > y1)
ang1 = Math.PI * 2 - ang1;
}
m = (xx - x2) / b;
if (m - 1 > 0.00001)
m = 1;
ang2 = Math.acos(m);//直線(x2-x1)-(xx,yy)斜率的弧度
if (y2 > yy)
ang2 = Math.PI * 2 - ang2;
ang = ang2 - ang1;
if (ang < 0) ang = -ang;
if (ang > Math.PI) ang = Math.PI * 2 - ang;//交角的大小
//如果是對角則直接返回距離
if (ang > Math.PI / 2)
return b;
else
return b * Math.sin(ang);//如果是銳角,返回計算得到的距離
}
}
</script>