[英]How can I tell if a point belongs to a certain line?
How can I tell if a point belongs to a certain line? 如何判断一个点是否属于某一行?
Examples are appreciated, if possible. 如果可能的话,可以理解例子。
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-Intersect(已经是X1 / Y1 ......)
You'll have to check that x1 - x2
is not 0
. 你必须检查x1 - x2
不是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 x1
or x2
. 如果是,则检查点是否在线是一个简单的问题,检查点中的Y值是否等于x1
或x2
。 Also, check that the X of the point is not 'x1' or 'x2'. 另外,检查点的X不是'x1'或'x2'。
I just wrote an function which handles a few extra requirements since I use this check in a drawing application: 我刚刚写了一个函数来处理一些额外的要求,因为我在绘图应用程序中使用了这个检查:
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;
}
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.此解决方案与其他方案相比具有几个相关的优点:首先,它不需要垂直线的特殊情况,第二,它不分(通常是慢速操作),第三,当线几乎但不是很垂直时,它不会触发不良的浮点行为。
Given two points on the line L0
and L1
and the point to test P
. 给出L0
和L1
线上的两个点以及测试P
的点。
(L1 - L0) * (P - L0)
n = (P - L0) - --------------------- (L1 - L0)
(L1 - L0) * (L1 - L0)
The norm of the vector n
is the distance of the point P
from the line through L0
and L1
. 向量n
的范数是点P
从线到L0
和L1
的距离。 If this distance is zero or small enough (in the case of rounding errors), the point lies on the line. 如果该距离为零或足够小(在舍入误差的情况下),则该点位于该线上。
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)
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. 当然还有许多其他正确答案,尤其是Mr.Josh,但我发现这是最好的答案。
Thankx for evryone. 感谢evryone。
y = m * x + c
This is the equation of a line. 这是一条线的等式。 x & y are the co-ordinates. x&y是坐标。 Each line is characterized by its slope (m ) and where it intersects the y-axis (c). 每条线的特征在于其斜率(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)是否在线上
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. 您需要检查除以零。
A 2D line is generally represented using an equation in two variables x and y here is a well known equation 2D线通常使用两个变量x和y中的等式来表示,这里是众所周知的等式
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. 如果在替换x = x3和y = y3时满足线方程,则给定点(x3,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. 例如,点(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. 希望这可以帮助。
Equation of the line is: 该方程是:
y = mx + c
So a point(a,b) is on this line if it satisfies this equation ie b = ma + c
因此,如果满足该等式,即b = ma + c
,则该点(a,b)在该线上
As an alternative to the slope/y-intercept
method, I chose this approach using Math.Atan2
: 作为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;
}
The first check reference
determines the arcTan from the start point of the line segment to it's end-point. 第一个检查reference
确定从线段起点到其终点的arcTan。 Then from the start point perspective, we determine the arcTan to the vector v
. 然后从起点角度,我们确定arcTan到向量v
。
If those values are equal, we check from the perspective of the end-point. 如果这些值相等,我们从终点的角度进行检查。
Simple and handles horizontal, vertical and all else in between. 简单,处理水平,垂直和其他所有。
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?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.