Given a line defined by two points A and B, an arbitrary point C, and a direction vector V, the goal is to find the point D where the ray from C in direction V intersects line AB. This is the "projected point" of C onto AB along V.
Approach — Parametric Line Equations
The parametric form of a line maps a scalar t to a point on the line, where t = 0 is the start point and t = 1 is the end point:
- Line AB:
x(t₁) = Xa + (Xb − Xa) · t₁ - Line AB:
y(t₁) = Ya + (Yb − Ya) · t₁ - Projection ray from C along V: create point C′ = C + V, then define line CC′
- Line CC′:
x(t₂) = Xc + (Xc′ − Xc) · t₂ - Line CC′:
y(t₂) = Yc + (Yc′ − Yc) · t₂
At the intersection the x and y values match, so setting the two parametric equations equal and solving for t₁ gives the parameter of point D on line AB. Evaluating AB at t₁ yields the projected coordinates.
Implementation
csharp
public static double ParameterAtPoint(Line2D line2D, Point2D point2D)
{
// Parametric coefficient A for the line direction
double A = line2D.EndPoint.X - line2D.StartPoint.X;
// t = (Xc - Xa) / A → position of point on the line (0 = start, 1 = end)
double t = (point2D.X - line2D.StartPoint.X) / A;
return t;
}
public static Point2D GetProjectedPointOnLine(
Point2D toProject, Line2D line2D, Vector2D direction)
{
// Create a second point along the projection direction from C
Point2D otherPoint = new Point2D(
toProject.X + direction.X,
toProject.Y + direction.Y);
// Parametric coefficients for line AB
double Al = line2D.EndPoint.X - line2D.StartPoint.X;
double Bl = line2D.EndPoint.Y - line2D.StartPoint.Y;
// Parametric coefficients for the projection line CC'
double Apl = otherPoint.X - toProject.X;
double Bpl = otherPoint.Y - toProject.Y;
// Solve the two parametric equations simultaneously.
// t2 is the parameter on the projection line at the intersection:
double t2 = ((toProject.Y - line2D.StartPoint.Y) * Al
- (toProject.X - line2D.StartPoint.X) * Bl)
/ (Apl * Bl - Al * Bpl);
// t1 is the parameter on line AB at the intersection — this is what we need:
double t1 = ((line2D.StartPoint.Y - toProject.Y) * Apl
- (line2D.StartPoint.X - toProject.X) * Bpl)
/ (Al * Bpl - Apl * Bl);
// Evaluate line AB at t1 to get the projected point D
return PointAtParameter(line2D, t1);
}