代码之家  ›  专栏  ›  技术社区  ›  Wahid Bitar

我怎么知道一个点是否属于某条线?

  •  18
  • Wahid Bitar  · 技术社区  · 17 年前

    我怎么知道一个点是否属于某条线?

    如有可能,请举例说明。

    11 回复  |  直到 8 年前
        1
  •  28
  •   Vityata    8 年前

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

    鉴于:

    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)形式表示,则可以使用以下公式计算坡度:

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

    然后得到y轴的交点:

     YIntersect = - Slope * X1 + Y1;
    

    编辑:我修复了Y轴交叉(已经是x1/y1…)

    你得检查一下 x1 - x2 不是 0 . 如果是,那么检查点是否在直线上是一个简单的问题,检查点中的y值是否等于 x1 x2 . 另外,检查该点的X不是“x1”或“x2”。

        2
  •  23
  •   Robin Andersson    13 年前

    我刚编写了一个函数,它处理了一些额外的需求,因为我在绘图应用程序中使用了此签入:

    • 模糊性-由于函数用于通过单击行来选择行,因此必须有一定的错误空间。
    • 这条线有一个端点和一个起点,没有无限的线。
    • 必须处理垂直和水平直线,(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;            
    }
    
        3
  •  19
  •   Dave    17 年前

    确定点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。这个解决方案有几个相关的优点:第一,它不需要垂直线的特殊情况,第二,它不划分(通常是一个缓慢的操作),第三,它不触发坏的浮点行为时,线几乎,但不是很垂直。

        4
  •  6
  •   Wahid Bitar    17 年前

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

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

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

    感谢Evryone。

        5
  •  6
  •   Daniel Brückner    12 年前

    线上两点 L0 L1 以及测试要点 P .

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

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

    符号 * 表示点积。

    例子

    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)
    
        6
  •  4
  •   Gishu    17 年前
    y = m * x + c
    

    这是一条直线的方程。x&y是坐标。每条线的特点是其坡度(m)和与Y轴(c)相交的位置。

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

        7
  •  3
  •   Patrick McDonald    17 年前

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

    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
    }
    

    不过,您需要检查除数是否为零。

        8
  •  2
  •   Community Mohan Dere    9 年前

    一条二维直线通常用一个方程表示,在两个变量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)=gt;y=x

    现在我们有了一个关于这条线的方程,很容易测试一个点是否属于这条线。如果用x=x3和y=y3代替时满足线方程,则给定点(x3,y3)属于该线。例如,点(10,10)属于该行,因为10=10,但(10,12)不属于该行,因为12!= 10。

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

    尽管我不得不说,我不确定这是否是最有效的方法。当我手头有更多的时间时,我会设法找到一种更有效的方法。

    希望这有帮助。

        9
  •  1
  •   Naveen    17 年前

    直线方程为:

    y = mx + c
    

    所以点(a,b)在这条线上,如果它满足这个方程,也就是说。 b = ma + c

        10
  •  0
  •   joshcomley    17 年前

    你能更具体点吗?

    你在说什么编程语言?

    你在说什么环境?

    你在说什么“台词”?文本?什么意思?屏幕上的xy?

        11
  •  0
  •   IAbstract    10 年前

    作为替代 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 - v.Y, s.Start.X - v.X);
    
        //  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 - v.Y, s.End.X - v.X);
        }
    
        return reference == aTanTest;
    }
    

    第一次检查 reference 确定从直线段的起点到其终点的弧角。 然后,从起点的角度,我们确定arctan到向量 v .

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

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

    推荐文章