如何判断一个点是否属于某一行?

如何判断一个点是否属于某一行?

如果可能,可以举例说明。

在最简单的forms中,只需将坐标插入线方程并检查是否相等。

鉴于:

Point p (X=4, Y=5) Line l (Slope=1, YIntersect=1) 

插入X和Y:

  Y = Slope * X + YIntersect => 5 = 1 * 4 + 1 => 5 = 5 

所以,是的,重点是在线。

如果您的线条以(X1,Y1),(X2,Y2)forms表示,那么您可以使用以下公式计算坡度:

  Slope = (y1 - y2) / (x1-x2) 

然后得到Y-Intersect:

  YIntersect = - Slope * X1 + Y1; 

编辑:我修复了Y-Intersect(已经是X1 / Y1 ……)

你必须检查x1 - x2不是0 。 如果是,则检查点是否在线是一个简单的问题,检查点中的Y值是否等于x1x2 。 另外,检查点的X不是’x1’或’x2’。

我刚刚写了一个函数来处理一些额外的要求,因为我在绘图应用程序中使用了这个检查:

  • 模糊性 – 必须有一些错误的余地,因为该function用于通过单击来选择线条。
  • 该线有一个EndPoint和一个StartPoint,没有无限的线。
  • 必须处理直的垂直和水平线,(x2 – x1)== 0导致在其他答案中除以零。
 private const double SELECTION_FUZZINESS = 3; internal override bool ContainsPoint(Point point) { LineGeometry lineGeo = geometry as LineGeometry; Point leftPoint; Point rightPoint; // Normalize start/end to left right to make the offset calc simpler. if (lineGeo.StartPoint.X <= lineGeo.EndPoint.X) { leftPoint = lineGeo.StartPoint; rightPoint = lineGeo.EndPoint; } else { leftPoint = lineGeo.EndPoint; rightPoint = lineGeo.StartPoint; } // If point is out of bounds, no need to do further checks. if (point.X + SELECTION_FUZZINESS < leftPoint.X || rightPoint.X < point.X - SELECTION_FUZZINESS) return false; else if (point.Y + SELECTION_FUZZINESS < Math.Min(leftPoint.Y, rightPoint.Y) || Math.Max(leftPoint.Y, rightPoint.Y) < point.Y - SELECTION_FUZZINESS) return false; double deltaX = rightPoint.X - leftPoint.X; double deltaY = rightPoint.Y - leftPoint.Y; // If the line is straight, the earlier boundary check is enough to determine that the point is on the line. // Also prevents division by zero exceptions. if (deltaX == 0 || deltaY == 0) return true; double slope = deltaY / deltaX; double offset = leftPoint.Y - leftPoint.X * slope; double calculatedY = point.X * slope + offset; // Check calculated Y matches the points Y coord with some easing. bool lineContains = point.Y - SELECTION_FUZZINESS <= calculatedY && calculatedY <= point.Y + SELECTION_FUZZINESS; return lineContains; } 

确定点R =(rx,ry)是否位于连接点P =(px,py)和Q =(qx,qy)的线上的最佳方法是检查矩阵的行列式

 {{qx - px, qy - py}, {rx - px, ry - py}}, 

即(qx – px)*(ry – py) – (qy – py)*(rx – px)接近0.此解决方案与其他方案相比具有几个相关的优点:首先,它不需要垂直线的特殊情况,第二,它不分(通常是慢速运算),第三,当线几乎但不是很垂直时,它不会触发不良的浮点行为。

我认为帕特里克麦克唐纳先生提出了几乎正确的答案,这是对他答案的更正:

 public bool IsOnLine(Point endPoint1, Point endPoint2, Point checkPoint) { return (((double)checkPoint.Y - endPoint1.Y)) / ((double)(checkPoint.X - endPoint1.X)) == ((double)(endPoint2.Y - endPoint1.Y)) / ((double)(endPoint2.X - endPoint1.X)); } 

当然还有很多其他正确答案,尤其是Mr.Josh,但我发现这是最好的答案。

感谢evryone。

给出L0L1线上的两个点以及测试P的点。

  (L1 - L0) * (P - L0) n = (P - L0) - --------------------- (L1 - L0) (L1 - L0) * (L1 - L0) 

向量n的范数是点P从线到L0L1的距离。 如果该距离为零或足够小(在舍入误差的情况下),则该点位于该线上。

符号*表示点积。

 P = (5, 5) L0 = (0, 10) L1 = (20, -10) L1 - L0 = (20, -20) P - L0 = (5, -5) (20, -20) * (5, -5) n = (5, -5) - --------------------- (20, -20) (20, -20) * (20, -20) 200 = (5, -5) - --- (20, -20) 800 = (5, -5) - (5, -5) = (0, 0) 
 y = m * x + c 

这是一条线的等式。 x&y是坐标。 每条线的特征在于其斜率(m)和与y轴(c)相交的位置。

因此,给定一条线的m&c,你可以通过检查方程是否适用于x = x1和y = y1来确定点(x1,y1)是否在线上

如果您的端点定义了一条线

 PointF pt1, pt2; 

你有一点想要检查

 PointF checkPoint; 

然后你可以定义一个函数如下:

 bool IsOnLine(PointF endPoint1, PointF endPoint2, PointF checkPoint) { return (checkPoint.Y - endPoint1.Y) / (endPoint2.Y - endPoint1.Y) == (checkPoint.X - endPoint1.X) / (endPoint2.X - endPoint1.X); } 

并将其命名如下:

 if (IsOnLine(pt1, pt2, checkPoint) { // Is on line } 

您需要检查除以零。

2D线通常使用两个变量x和y中的等式来表示,这里是众所周知的等式

y-y1 =(y1-y2)/(x1-x2)(x-x1)

现在想象你的GDI +线是从(0,0)到(100,100),然后是m =(0-100)/(0-100)= 1的值,因此你的线的等式是y-0 = 1 *(x-0)=> y = x

既然我们有一个有问题的线的等式,它很容易测试一个点是否属于这一行。 如果在替换x = x3和y = y3时满足线方程,则给定点(x3,y3)属于此线。 例如,点(10,10)属于该线,因为10 = 10但是(10,12)不属于该线,因为12!= 10。

注意:对于垂直线,斜率(m)的值是无穷大,但对于这种特殊情况,您可以直接使用等式表示垂直线x = c,其中c = x1 = x2。

虽然我不得不说我不确定这是否是最有效的方法。 当我有更多的时间时,我会尝试找到一种更有效的方法。

希望这可以帮助。

该方程是:

 y = mx + c 

因此,如果满足该等式,即b = ma + c ,则该点(a,b)在该线上

你可以再详细一点吗?

你在谈论什么编程语言?

你在说什么环境?

你在说什么“线”? 文本? 什么点? 屏幕上的XY?

作为slope/y-intercept方法的替代方法,我使用Math.Atan2选择了这种方法:

 // as an extension method public static bool Intersects(this Vector2 v, LineSegment s) { // check from line segment start perspective var reference = Math.Atan2(s.Start.Y - s.End.Y, s.Start.X - s.End.X); var aTanTest = Math.Atan2(s.Start.Y - vY, s.Start.X - vX); // check from line segment end perspective if (reference == aTanTest) { reference = Math.Atan2(s.End.Y - s.Start.Y, s.End.X - s.Start.X); aTanTest = Math.Atan2(s.End.Y - vY, s.End.X - vX); } return reference == aTanTest; } 

第一个检查reference确定从线段的起点到其终点的arcTan。 然后从起点角度,我们确定arcTan到向量v

如果这些值相等,我们从终点的角度进行检查。

简单,处理水平,垂直和其他所有。