【C#】点到线段最短距离的那条直线与线段的交点
程序员文章站
2022-04-01 15:47:51
...
/// <summary>
/// 点到线段最短距离的那条直线与线段的交点,{x=...,y=...}
/// </summary>
/// <param name="x">线段外的点的x坐标</param>
/// <param name="y">线段外的点的y坐标</param>
/// <param name="x1">线段顶点1的x坐标</param>
/// <param name="y1">线段顶点1的y坐标</param>
/// <param name="x2">线段顶点2的x坐标</param>
/// <param name="y2">线段顶点2的y坐标</param>
/// <returns></returns>
public Vector2 PointForPointToABLine(float x, float y, float x1, float y1, float x2, float y2)
{
Vector2 reVal = new Vector2();
// 直线方程的两点式转换成一般式
// A = Y2 - Y1
// B = X1 - X2
// C = X2*Y1 - X1*Y2
float a1 = y2 - y1;
float b1 = x1 - x2;
float c1 = x2 * y1 - x1 * y2;
float x3, y3;
if (a1 == 0)
{
// 线段与x轴平行
reVal = new Vector2(x, y1);
x3 = x;
y3 = y1;
}
else if (b1 == 0)
{
// 线段与y轴平行
reVal = new Vector2(x1, y);
x3 = x1;
y3 = y;
}
else
{
// 普通线段
float k1 = -a1 / b1;
float k2 = -1 / k1;
float a2 = k2;
float b2 = -1;
float c2 = y - k2 * x;
// 直线一般式和二元一次方程的一般式转换
// 直线的一般式为 Ax+By+C=0
// 二元一次方程的一般式为 Ax+By=C
c1 = -c1;
c2 = -c2;
// 二元一次方程求解(Ax+By=C)
// a=a1,b=b1,c=c1,d=a2,e=b2,f=c2;
// X=(ce-bf)/(ae-bd)
// Y=(af-cd)/(ae-bd)
x3 = (c1 * b2 - b1 * c2) / (a1 * b2 - b1 * a2);
y3 = (a1 * c2 - c1 * a2) / (a1 * b2 - b1 * a2);
}
// 点(x3,y3)作为点(x,y)到(x1,y1)和(x2,y2)组成的直线距离最近的点,那(x3,y3)是否在(x1,y1)和(x2,y2)的线段之内(包含(x1,y1)和(x2,y2))
if (((x3 > x1) != (x3 > x2) || x3 == x1 || x3 == x2) && ((y3 > y1) != (y3 > y2) || y3 == y1 || y3 == y2))
{
// (x3,y3)在线段上
reVal = new Vector2(x3, y3);
}
else
{
// (x3,y3)在线段外
float d1_quadratic = (x - x1) * (x - x1) + (y - y1) * (y - y1);
float d2_quadratic = (x - x2) * (x - x2) + (y - y2) * (y - y2);
if (d1_quadratic <= d2_quadratic)
{
reVal = new Vector2(x1, y1);
}
else
{
reVal = new Vector2(x2, y2);
}
}
return reVal;
}