This is basic graphics geometry and/or trig, and I feel dumb for asking it, but I can\'t remember how this goes. So:
The answer line is:
y=ax+b
where a=(x1-x2)/(y2-y1)
b=yp-(x1-x2)*xp/(y2-y1)
How the result was obtained:
1) slope for the original line: (y2-y1)/(x2-x1)
2) slope for the answer: -1/((y2-y1)/(x2-x1)) = (x1-x2)/(y2-y1)
3) Plug this into (xp,yp) we can have the result line.
Just calculate the answer from the lines after this (this is too long... I am hungry).
You can find that point by considering first a generic point (x, y)
along the line from (x1, y1)
to (x2, y2)
:
x = x1 + t*(x2 - x1)
y = y1 + t*(y2 - y1)
and the computing the (squared) distance from this point from (xp, yp)
E = (x - xp)**2 + (y - yp)**2
that substituting the definition of x
and y
gives
E = (x1 + t*(x2 - x1) - xp)**2 +
(y1 + t*(y2 - y1) - yp)**2
then to find the minimum of this distance varying t
we derive E
with respect to t
dE/dt = 2*(x1 + t*(x2 - x1) - xp)*(x2 - x1) +
2*(y1 + t*(y2 - y1) - yp)*(y2 - y1)
that after some computation gives
dE/dt = 2*((x1 - xp)*(x2 - x1) + (y1 - yp)*(y2 - y1) +
t*((x2 - x1)**2 + (y1 - y2)**2))
looking for when this derivative is zero we get an explicit equation for t
t = ((xp - x1)*(x2 - x1) + (yp - y1)*(y2 - y1)) /
((x2 - x1)**2 + (y2 - y1)**2)
so the final point can be computed using that value for t
in the definition of (x, y)
.
Using vector notation this is exactly the same formula suggested by Gareth...
t = <p - p1, p2 - p1> / <p2 - p1, p2 - p1>
where the notation <a, b>
represents the dot product operation ax*bx + ay*by
.
Note also that the very same formula works in an n-dimensional space.
A useful rule of thumb in this kind of computational geometry is that you should work with vectors as long as you can, switching to Cartesian coordinates only as a last resort. So let's solve this using vector algebra. Suppose your line goes from p to p + r, and the other point is q.
Now, any point on the line, including the point you are trying to find (call it s), can be expressed as s = p + λ r for a scalar parameter λ.
Now the vector from q to s must be perpendicular to r. Therefore
(q − (p + λ r)) · r = 0
Where · is the dot product operator. Expand the product:
(q − p) · r = λ (r · r)
And divide:
λ = (q − p) · r / r · r
When you come to implement it, you need to check whether r · r = 0, to avoid division by zero.
To all those poor souls looking for a concrete example using vectors... here I build upon Gareth's answer.
You have a vector from p to r (from 0,0 to 50,-50) and another point, q, which is at (50, 0). The right-angle intersection of q and the vector from p to r is { x: 25. y: -25 } and is derived with the following code.
const p = [0, 0];
const r = [50, -50];
const q = [50, 0];
const l = math.add(p, r);
const m = math.dot(math.subtract(q, p), r) / math.dot(r, r);
console.log('intersecting point', math.multiply(l, m));
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/5.1.2/math.js"></script>
Based on this article
let x1, x2, y1, y2, slope, xp, yp, m, x, y
x1 = 0
y1 = 0
x2 = 50
y2 = -50
xp = 50
yp = 0
slope = (y1 - y2) / (x1 - x2)
m = -1 / slope
x = (m * xp - yp - slope * x1 + y1) / (m - slope)
y = m * x - m * xp + yp
console.log('x: ', x, ', y: ', y )
You can solve the slope of the line connecting (x1, y1)
and (x2, y2)
. You then know the perpendicular line has a slope negative-inverse of that.
To find the y-intercept, use the slope to see how far the line travels in y
from x=0
to x1
.
b + (x1 - x0) * m = y1
b + (x1 - 0) * m = y1
b + (x1 * m) = y1
b = y1 - x1 * m
You can then get the formulas for the line between your two points and the line from (xp, yp)
with the above slope. For a given x, they have equal y's, so you can solve for that x
, then plug that into either's formula for the y
.
m = slope_from_1_to_2 = (y2 - y1) / (x2 - x1)
n = slopePerpendicular = (-1) / m
b = intercept_for_1_to_2 = y1 - x1 * m
c = intercept_for_p = yp - xp * n
Thus the equations for the lines are of the form
y = mx + b
Points 1 and 2:
y(x) = mx + b
Point p:
y(x) = nx + c
Set their y
's equal to find x'
mx' + b = nx' + c
(m-n)x' = c - b
x' = (c - b) / (m - n)
And thus use either formula to compute y'
y' = mx' + b