I have line segment defined by these two points: A(x1,y1,z1) and B(x2,y2,z2). I have point p(x,y,z). How can I check if the point lies on the line segment?
-
possible duplicate of [How can you determine a point is between two other points on a line segment?](http://stackoverflow.com/questions/328107/how-can-you-determine-a-point-is-between-two-other-points-on-a-line-segment) – Cade Roux Aug 13 '11 at 12:00
-
2because I need any sample code in c# – AMH Aug 13 '11 at 14:15
-
1yeah, it sounded obvious to me :) – Leggy7 Jan 02 '14 at 09:11
-
I tried to reply to MetaMapper's post but I don't have a 50 reputation. MetaMapper's solution is wrong. I personally spent a lot of time debugging and I wouldn't want anyone else to have to go through the same thing. Andy's solution is correct. It just has to be converted to C#. I hope this saves someone some time. – Ruell Black Jul 03 '18 at 22:24
-
The question above only handles the 2D case though. – user202729 Jun 19 '22 at 11:10
12 Answers
Find the distance of point P from both the line end points A, B. If AB = AP + PB, then P lies on the line segment AB.
AB = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)+(z2-z1)*(z2-z1));
AP = sqrt((x-x1)*(x-x1)+(y-y1)*(y-y1)+(z-z1)*(z-z1));
PB = sqrt((x2-x)*(x2-x)+(y2-y)*(y2-y)+(z2-z)*(z2-z));
if(AB == AP + PB)
return true;

- 571
- 1
- 4
- 4
-
1I know this is pretty late, but this answer works a lot better than the accepted answer. Especially since it works when a point is on the line segment start or end. – Roy T. Jul 28 '14 at 13:08
-
6Excellent answer. One thing you might want to consider is floating point rounding errors. Let's say AB = 12.0000001 and AP + PB = 12.000003, you still might want to consider things being "close enough", depending on what you are doing. – Joel B Mar 26 '15 at 15:19
-
9
-
2Not at all, processors have a dedicated instruction for Math.Sqrt(). It takes just as long as a division. – Hans Passant Jun 09 '19 at 10:41
-
Can't this be done without the square roots ? Since you could take the square of both sides to have `AB^2 = AP^2 + PB^2` as a minor performance gain ? – WDUK Jun 18 '21 at 01:26
-
@WDUK [x²+y² ≠ (x+y)² – Freshman's dream](https://en.wikipedia.org/wiki/Freshman%27s_dream) – but yes using cross product no division is needed. – user202729 Jun 19 '22 at 11:14
If the point is on the line then:
(x - x1) / (x2 - x1) = (y - y1) / (y2 - y1) = (z - z1) / (z2 - z1)
Calculate all three values, and if they are the same (to some degree of tolerance), your point is on the line.
To test if the point is in the segment, not just on the line, you can check that
x1 < x < x2, assuming x1 < x2, or
y1 < y < y2, assuming y1 < y2, or
z1 < z < z2, assuming z1 < z2
-
One of them is the point you're checking, and the other two are the endpoints of the line. It doesn't matter which name you give to each point, as long as you are consistent. – Karl Knechtel Aug 13 '11 at 14:08
-
AMH yes - for any point (x,y,z) this equality is only true if the the point is on the line . It's basically @Konstantin's parametric line equation answer, but eliminating the parameter p. You don't really care about the exact value of p, only that it has the same value for x, y and z. – Rob Agar Aug 14 '11 at 03:02
-
27
-
2just to complete this answer, [here](http://mathforum.org/library/drmath/view/65721.html) you can find the complete mathematical explaination – Leggy7 Jan 02 '14 at 10:14
-
3And fails if x is close to x1 or y is close to y1 or z is close to z1 due to unfixable floating point precision problems. Don't use this solution. Fine for a math exam, but completely wrong answer for c# code. – Robin Davies Apr 05 '17 at 04:04
-
As @Jeriho said, this does not work when `x1 == x2` or `y1 == y2`. It will be divide by 0. – aheze Apr 08 '21 at 22:45
First take the cross product of AB and AP. If they are colinear, then it will be 0.
At this point, it could still be on the greater line extending past B or before A, so then I think you should be able to just check if pz is between az and bz.
This appears to be a duplicate, actually, and as one of the answers mentions, it is in Beautiful Code.
-
could you give me numerical example , I misunderstand the part after the corss product – AMH Aug 13 '11 at 12:01
-
1@AMH Probably best to just see the other discussion on this: http://stackoverflow.com/questions/328107/how-can-you-determine-a-point-is-between-two-other-points-on-a-line-segment – Cade Roux Aug 13 '11 at 12:03
-
in case if someone looks for inline version:
public static bool PointOnLine2D (this Vector2 p, Vector2 a, Vector2 b, float t = 1E-03f)
{
// ensure points are collinear
var zero = (b.x - a.x) * (p.y - a.y) - (p.x - a.x) * (b.y - a.y);
if (zero > t || zero < -t) return false;
// check if x-coordinates are not equal
if (a.x - b.x > t || b.x - a.x > t)
// ensure x is between a.x & b.x (use tolerance)
return a.x > b.x
? p.x + t > b.x && p.x - t < a.x
: p.x + t > a.x && p.x - t < b.x;
// ensure y is between a.y & b.y (use tolerance)
return a.y > b.y
? p.y + t > b.y && p.y - t < a.y
: p.y + t > a.y && p.y - t < b.y;
}

- 51
- 1
- 1
-
Excluding your epsilon (ie. t) zero check, the colinear check can be written as if (Vector.crossProduct(u = new Vector(a, b), new Vector(u, new Vector(a, p))) != 0) return false; – Borgboy Sep 18 '16 at 23:15
Here's some C# code for the 2D case:
public static bool PointOnLineSegment(PointD pt1, PointD pt2, PointD pt, double epsilon = 0.001)
{
if (pt.X - Math.Max(pt1.X, pt2.X) > epsilon ||
Math.Min(pt1.X, pt2.X) - pt.X > epsilon ||
pt.Y - Math.Max(pt1.Y, pt2.Y) > epsilon ||
Math.Min(pt1.Y, pt2.Y) - pt.Y > epsilon)
return false;
if (Math.Abs(pt2.X - pt1.X) < epsilon)
return Math.Abs(pt1.X - pt.X) < epsilon || Math.Abs(pt2.X - pt.X) < epsilon;
if (Math.Abs(pt2.Y - pt1.Y) < epsilon)
return Math.Abs(pt1.Y - pt.Y) < epsilon || Math.Abs(pt2.Y - pt.Y) < epsilon;
double x = pt1.X + (pt.Y - pt1.Y) * (pt2.X - pt1.X) / (pt2.Y - pt1.Y);
double y = pt1.Y + (pt.X - pt1.X) * (pt2.Y - pt1.Y) / (pt2.X - pt1.X);
return Math.Abs(pt.X - x) < epsilon || Math.Abs(pt.Y - y) < epsilon;
}

- 968
- 8
- 22
Your segment is best defined by parametric equation
for all points on your segment, following equation holds: x = x1 + (x2 - x1) * p y = y1 + (y2 - y1) * p z = z1 + (z2 - z1) * p
Where p is a number in [0;1]
So, if there is a p such that your point coordinates satisfy those 3 equations, your point is on this line. And it p is between 0 and 1 - it is also on line segment

- 12,329
- 1
- 30
- 35
-
-
No, you just solve 3 equations against p - if all 3 values are equal within reasonable error (it's floating point - no exact match will be there), then your point is on that straight line. If p is between 0 and 1, then it is inside segment – Konstantin Pribluda Aug 13 '11 at 13:23
-
@KonstantinPribluda - thanks for the explanation. I added an answer based on your answer. – Andy Apr 29 '13 at 06:00
Or let the dotnet do the heavy lifting for you if using visual studio use a GraphicsPath
this will also allow you to add tolerances for if just clicked outside the line.
using (Drawing2D.GraphicsPath gp = new Drawing2D.GraphicsPath())
{
gp.AddLine(new Point(x1, y1), new Point(x2, y2));
// Make the line as wide as needed (make this larger to allow clicking slightly outside the line)
using (Pen objPen = new Pen(Color.Black, 6))
{
gp.Widen(objPen);
}
if (gp.IsVisible(Mouse.x, Mouse.y))
{
// The line was clicked
}
}

- 216
- 3
- 8
I use this to calculate the distance AB between points a and b.
static void Main(string[] args)
{
double AB = segment(0, 1, 0, 4);
Console.WriteLine("Length of segment AB: {0}",AB);
}
static double segment (int ax,int ay, int bx, int by)
{
Vector a = new Vector(ax,ay);
Vector b = new Vector(bx,by);
Vector c = (a & b);
return Math.Sqrt(c.X + c.Y);
}
struct Vector
{
public readonly float X;
public readonly float Y;
public Vector(float x, float y)
{
this.X = x;
this.Y = y;
}
public static Vector operator &(Vector a, Vector b)
{
return new Vector((b.X - a.X) * (b.X - a.X), (b.Y - a.Y) * (b.Y - a.Y));
}
}
based on Calculate a point along the line A-B at a given distance from A

- 1
- 1

- 197
- 2
- 8
Let V1 be the vector (B-A), and V2 = (p-A), normalize both V1 and V2.
If V1==(-V2) then the point p is on the line, but preceding A, & therefore not in the segment. If V1==V2 the point p is on the line. Get the length of (p-A) and check if this is less-or-equal to length of (B-A), if so the point is on the segment, else it is past B.

- 7,069
- 9
- 54
- 80
This is my code which can run in WPF
public static class Math2DExtensions
{
public static bool CheckIsPointOnLineSegment(Point point, Line line, double epsilon = 0.1)
{
// Thank you @Rob Agar
// (x - x1) / (x2 - x1) = (y - y1) / (y2 - y1)
// x1 < x < x2, assuming x1 < x2
// y1 < y < y2, assuming y1 < y2
var minX = Math.Min(line.APoint.X, line.BPoint.X);
var maxX = Math.Max(line.APoint.X, line.BPoint.X);
var minY = Math.Min(line.APoint.Y, line.BPoint.Y);
var maxY = Math.Max(line.APoint.Y, line.BPoint.Y);
if (!(minX <= point.X) || !(point.X <= maxX) || !(minY <= point.Y) || !(point.Y <= maxY))
{
return false;
}
if (Math.Abs(line.APoint.X - line.BPoint.X) < epsilon)
{
return Math.Abs(line.APoint.X - point.X) < epsilon || Math.Abs(line.BPoint.X - point.X) < epsilon;
}
if (Math.Abs(line.APoint.Y - line.BPoint.Y) < epsilon)
{
return Math.Abs(line.APoint.Y - point.Y) < epsilon || Math.Abs(line.BPoint.Y - point.Y) < epsilon;
}
if (Math.Abs((point.X - line.APoint.X) / (line.BPoint.X - line.APoint.X) - (point.Y - line.APoint.Y) / (line.BPoint.Y - line.APoint.Y)) < epsilon)
{
return true;
}
else
{
return false;
}
}
}
public record Line
{
public Point APoint { get; init; }
public Point BPoint { get; init; }
}
My code is in github
Thank you @Rob Agar and @MetaMapper

- 4,182
- 3
- 19
- 65
-
This won't work if `b` and `a` have the same `y` since you will get division by zero. Same if they have the same `x` aswell. – WDUK Mar 27 '22 at 22:08
-
The cross product (B - A) × (p - A) should be much much shorter than B - A. Ideally, the cross product is zero, but that's unlikely on finite-precision floating-point hardware.

- 181,030
- 38
- 327
- 365
You could check if the point lies between the two planes defined by point1 and point2 and the line direction:
/// Returns the closest point from @a point to this line on this line.
vector3 <Type>
line3d <Type>::closest_point (const vector3 <Type> & point) const
{
return this -> point () + direction () * dot (point - this -> point (), direction ());
}
/// Returns true if @a point lies between point1 and point2.
template <class Type>
bool
line_segment3 <Type>::is_between (const vector3 <Type> & point) const
{
const auto closest = line () .closest_point (point);
return abs ((closest - point0 ()) + (closest - point1 ())) <= abs (point0 () - point1 ());
}

- 37
- 6
-
This is not C# code at all - so not useful for *this* question - could be fine for C/C++ version of the same Q... And explanation is not very friendly for average person. – Alexei Levenkov Mar 17 '17 at 22:56