C# 如何判断一个点是否属于某条线?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/907390/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 02:32:46  来源:igfitidea点击:

How can I tell if a point belongs to a certain line?

c#.netalgorithmgdi+line

提问by Wahid Bitar

How can I tell if a point belongs to a certain line?

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

Examples are appreciated, if possible.

如果可能的话,示例是值得赞赏的。

采纳答案by Eclipse

In the simplest form, just plug the coordinates into the line equation and check for equality.

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

Given:

鉴于:

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

Plug in X and Y:

插入 X 和 Y:

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

So yes, the point is on the line.

所以是的,重点是在线。

If your lines are represented in (X1,Y1),(X2,Y2) form, then you can calculate slope with:

如果您的线以 (X1,Y1),(X2,Y2) 形式表示,那么您可以使用以下方法计算斜率:

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

And then get the Y-Intersect with this:

然后用这个得到Y-Intersect:

 YIntersect = - Slope * X1 + Y1;

Edit: I fixed the Y-Intersect (which has been X1 / Y1 ...)

编辑:我修复了 Y 相交(X1 / Y1 ...)

You'll have to check that x1 - x2is not 0. If it is, then checking if the point is on the line is a simple matter of checking if the Y value in your point is equal to either x1or x2. Also, check that the X of the point is not 'x1' or 'x2'.

你必须检查那x1 - x2不是0。如果是,那么检查点是否在直线上就是检查点中的 Y 值是否等于x1或的简单问题x2。另外,检查点的 X 是否不是“x1”或“x2”。

回答by joshcomley

Could you be more specific?

你可以再详细一点吗?

What programming language are you talking about?

你说的是什么编程语言?

What environment are you talking about?

你说的是什么环境?

What "lines" are you talking about? Text? What point? XY on the screen?

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

回答by Gishu

y = m * x + c

This is the equation of a line. x & y are the co-ordinates. Each line is characterized by its slope (m ) and where it intersects the y-axis (c).

这是一条直线的方程。x & y 是坐标。每条线的特点是它的斜率 (m) 和它与 y 轴 (c) 的交点。

So given m & c for a line, you can determine if the point (x1, y1) is on the line by checking if the equation holds for x = x1 and y = y1

因此,给定一条线的 m & c,您可以通过检查方程是否对 x = x1 和 y = y1 成立来确定点 (x1, y1) 是否在这条线上

回答by Naveen

Equation of the line is:

直线方程为:

y = mx + c

So a point(a,b) is on this line if it satisfies this equation i.e. b = ma + c

所以一个点(a,b)在这条线上,如果它满足这个方程,即 b = ma + c

回答by Autodidact

A 2D line is generally represented using an equation in two variables x and y here is a well known equation

二维线通常使用两个变量 x 和 y 中的方程表示,这里是一个众所周知的方程

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

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

Now imagine your GDI+ line is drawn from (0,0) to (100, 100) then the value of m=(0-100)/(0-100) = 1 thus the equation for your line is y-0=1*(x-0) => y=x

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

Now that we have an equation for the line in question its easy to test if a point belongs to this line. A given point (x3, y3) belongs to this line if it satisfies the line equation when you substitute x=x3 and y=y3. For example the point (10, 10) belongs to this line since 10=10 but (10,12) does not belong to this line since 12 != 10.

既然我们有了所讨论的直线的方程,就很容易测试一个点是否属于这条直线。如果一个给定的点 (x3, y3) 满足当你代入 x=x3 和 y=y3 时的线方程,那么它就属于这条线。例如,点 (10, 10) 属于这条线,因为 10=10 但 (10,12) 不属于这条线,因为 12 != 10。

NOTE: For a vertical line the value of the slope (m) is infinite but for this special case you may use the equation for a vertical line directly x=c where c = x1 = x2.

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

Though I have to say I am not sure if this is the most efficient way of doing this. I will try and find a more efficient way when I have some more time on hand.

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

Hope this helps.

希望这可以帮助。

回答by Patrick McDonald

If you have a line defined by its endpoints

如果您有一条由其端点定义的线

PointF pt1, pt2;

and you have a point that you want to check

你有一个要检查的点

PointF checkPoint;

then you could define a function as follows:

那么你可以定义一个函数如下:

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);
}

and call it as follows:

并按如下方式调用它:

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

You will need to check for division by zero though.

不过,您需要检查除以零。

回答by Daniel Brückner

Given two points on the line L0and L1and the point to test P.

给定线上的两个点L0L1和要测试的点P

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

The norm of the vector nis the distance of the point Pfrom the line through L0and L1. If this distance is zero or small enough (in the case of rounding errors), the point lies on the line.

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

The symbol *represents the dot product.

符号*代表点积。

Example

例子

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)

回答by Dave

The best way to determine if a point R = (rx, ry) lies on the line connecting points P = (px, py) and Q = (qx, qy) is to check whether the determinant of the matrix

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

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

namely (qx - px) * (ry - py) - (qy - py) * (rx - px) is close to 0. This solution has several related advantages over the others posted: first, it requires no special case for vertical lines, second, it doesn't divide (usually a slow operation), third, it doesn't trigger bad floating-point behavior when the line is almost, but not quite vertical.

即 (qx - px) * (ry - py) - (qy - py) * (rx - px) 接近于 0。与其他解决方案相比,该解决方案有几个相关的优点:首先,它不需要垂直线的特殊情况,第二,它不会除法(通常是一个缓慢的操作),第三,当线几乎但不完全垂直时,它不会触发不良的浮点行为。

回答by Wahid Bitar

I think Mr.Patrick McDonald put the nearly correct answer and this is the correction of his answer:

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

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));
}

and of course there are many other correct answers especially Mr.Josh but i found this is the best one.

当然还有许多其他正确答案,尤其是乔希先生,但我发现这是最好的答案。

Thankx for evryone.

谢谢大家。

回答by Robin Andersson

I just wrote an function which handles a few extra requirements since I use this check in a drawing application:

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

  • Fuzziness - There must be some room for error since the function is used to select lines by clicking on them.
  • The line got an EndPoint and a StartPoint, no infinite lines.
  • Must handle straight vertical and horizontal lines, (x2 - x1) == 0 causes division by zero in the other answers.
  • 模糊性 - 由于该函数用于通过单击来选择行,因此必须存在一定的错误空间。
  • 这条线有一个端点和一个起点,没有无限线。
  • 必须处理垂直和水平直线, (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;            
}