+-------------+
| |
| |
| |
| |
| |
+-------------+
XXXX
XXX p2
XX
XX
+------------+XX
| |
| |
| |
| |
| |
+------------+X
XXXX XXX
XXXX p4 XXX
XXX XX
+-----------+XX XXXX
| | XXXX +------------+
| | XX | |
| | X| |
| | | |
| | | |
+-----------+ | |
| |
+------------+
p1
p3
p1 is the first node on the hovered segment.
p2 is the second node on the hovered segment.
p3 is the mouse cursor position.
p4 is the point we are trying to solve for.
p3 to p4 will form a perpendicular line to the p1 to p2 segment, because that is the shortest distance to the segment. A non perpendicular line would be longer, so we don't want that.
We can think of this problem as finding the intersection of two line equations once we find the equations for the lines.
For the p1 to p2 segment we know both X, Y pairs so we can easily find the equation using point slope form:
y = m(x - p1.x) + p1.y
Where m
is the slope of the line defined by the "rise over run", which can be calculated as this fraction:
p1.y - p2.y
m = -----------
p1.x - p2.x
We also know that the slope of a perpendicular line is the negative reciprocal
of the slope, meaning if the slope is m
, the perpendicular line's slope is
-1 / m
.
See https://www.mathsisfun.com/algebra/line-parallel-perpendicular.html.
So the p1 to p2 segment's equation is:
p1.y - p2.y
y = ----------- * (x - p1.x) + p1.y
p1.x - p2.x
To simplify writing the equation, we'll call the slope m1
here:
y = m1 * (x - p1.x) + p1.y
We only know one point on the perpendicular segment, but we can figure out the slope via -1/m
formula, so that gives us:
p1.x - p2.x
y = -1 * ----------- * (x - p3.x) + p3.y
p1.y - p2.y
To simplify writing the equation, we'll call the slope m2
here:
y = m2 * (x - p3.x) + p3.y
In order to find where they intersect, we can set the two equations equal to each other and solve for X using algebra.
m1 * (x - p1.x) + p1.y = m2 * (x - p3.x) + p3.y
Subtract p1.y
from both sides:
m1 * (x - p1.x) = m2 * (x - p3.x) + p3.y - p1.y
Distribute the multiplication of m1
over the the subtraction:
(m1 * x) - (m1 * p1.x) = m2 * (x - p3.x) + p3.y - p1.y
Distribute the multiplication of m2
over the the subtraction:
(m1 * x) - (m1 * p1.x) = (m2 * x) - (m2 * p3.x) + p3.y - p1.y
We want to get all the X on the left side, so we will subtact (m2 * x)
from
both sides:
(m1 * x) - (m1 * p1.x) - (m2 * x) = - (m2 * p3.x) + p3.y - p1.y
We want to isolate the X's so we'll add the (m1 * p1.x)
to both sides:
(m1 * x) - (m2 * x) = - (m2 * p3.x) + p3.y - p1.y + (m1 * p1.x)
Now we can un-distribute the multiplication over the subtraction on the left:
(m1 - m2) * x = - (m2 * p3.x) + p3.y - p1.y + (m1 * p1.x)
The final step is dividing by m1 - m2
:
-(m2 * p3.x) + p3.y - p1.y + (m1 * p1.x)
x = ----------------------------------------
(m1 - m2)
So at this point, we know the equation solved for Y for the p3 to p4 segment, and we know an X value, so we plug in that X value to get the Y value, leaving us with the X, Y coordinate pair for p4.