计算点到直线的距离

  • 本文关键字:距离 计算 c# geometry
  • 更新时间 :
  • 英文 :


我正在用C#编写一个类似油漆的程序。我希望能够在单击靠近某条线时擦除该线(例如距离<10像素(。我尝试过不同的计算,但我最终遇到的问题是,只有当我在直线的起点或终点附近单击时,直线才会被删除。介于两者之间的任何东西似乎都不起作用。

设p为用户在表单中单击的点,startp和endp为行的端点。

double a = (endp.Y - startp.Y) / (endp.X - startp.X); // gradient
double b = endp.Y - a * endp.X; // y intercept
// condition such that it only works when i click close to the line segment,
// not the entire infinite line for which the calculation y=ax+b works
double yvalue = p.X * a + b;    // value the line segment has at the x-value which the user clicks on
double alpha = Math.Atan((endp.X - startp.X) / (endp.Y - startp.Y));    
double distance = Math.Sin(alpha) * Math.Abs((yvalue - p.Y));
if (distance<10)
// remove line

为什么此代码只适用于靠近起点或终点的点?我相信这不是因为我使用的条件,我在这里的例子中遗漏了这些条件

要计算的距离可以看作是三角形p-startP-endP中p的高度。因此,这给出了以下公式:

a = dist(startp, endp)
b = dist(startp, p)
c = dist(endp, p)
s = (a + b + c)/2
distance = 2 * sqrt(s(s-a)(s-b)(s-c)) / a

参见。高度(三角形(

试着使用这个来看看这是否是你所需要的:

int variance = 10; // +/- distance
PointF lineStart = new PointF(80, 80); // Starting line point
PointF lineEnd = new PointF(200, 200); // Ending line point
double x1 = lineStart.X;
double x2 = lineEnd.X;
double y1 = lineStart.Y;
double y2 = lineEnd.Y;
double mouseX = e.X; // Mouse X position
double mouseY = e.Y; // Mouse Y position
double AB = Math.Sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
double AP = Math.Sqrt((mouseX - x1) * (mouseX - x1) + (mouseY - y1) * (mouseY - y1));
double PB = Math.Sqrt((x2 - mouseX) * (x2 - mouseX) + (y2 - mouseY) * (y2 - mouseY));
if ((AP + PB) >= (AB - variance / 4) && (AP + PB) <= (AB + variance / 4))
{
// It's within the line and variance
// so erase Line
}

这更像是一道数学题。我会做以下事情:

1:求线矢量v=(x2-x1;y2-y1(

2:将线矢量旋转90度:v1=(-vy;vx(

3:让鼠标位置m=(mx;my(找到以下直线的交点:(mx,my(+k1(-vy;vx(=(x1;y1(+k2(vx;vy(

4:检查步骤4中找到的结果与点m之间的距离是否小于您想要的结果。

如果直线与基点startP、归一化方向向量d和点p相连,则找到点与直线距离的最简单方法是使用叉积

Dist = Abs(Cross(P-startP, d)) = 
Abs((P.x -startP.x) * d.y - (P.y -startP.y) * d.x)

但您需要到线段(而不是无限长的直线(的距离。在这种情况下,您还需要检查点的投影是否位于线段范围内。用标量乘积计算参数:

t = Dot(P-startP, d)

如果t在范围0..Len(D)中,则投影在分段上,否则最短距离是从点到分段末端之一的距离(从负t开始,到大t结束(。

请注意,矢量法比斜率法更通用,它不会在水平或垂直线上失败。

最新更新