Distance between point and a line (from two points)
Question:
I’m using Python+Numpy (can maybe also use Scipy) and have three 2D points
(P1, P2, P3);
I am trying to get the distance from P3 perpendicular to a line drawn between P1 and P2. Let P1=(x1,y1)
, P2=(x2,y2)
and P3=(x3,y3)
In vector notation this would be pretty easy, but I’m fairly new to python/numpy and can’t get anythng that works (or even close).
Any tips appreciated, thanks!
Answers:
Try using the norm function from numpy.linalg
d = norm(np.cross(p2-p1, p1-p3))/norm(p2-p1)
np.cross
returns the z-coordinate of the cross product only for 2D vectors. So the first norm
in the accepted answer is not needed, and is actually dangerous if p3
is an array of vectors rather than a single vector. Best just to use
d=np.cross(p2-p1,p3-p1)/norm(p2-p1)
which for an array of points p3
will give you an array of distances from the line.
For the above-mentioned answers to work, the points need to be numpy arrays, here’s a working example:
import numpy as np
p1=np.array([0,0])
p2=np.array([10,10])
p3=np.array([5,7])
d=np.cross(p2-p1,p3-p1)/np.linalg.norm(p2-p1)
abs((x2-x1)*(y1-y0) - (x1-x0)*(y2-y1)) / np.sqrt(np.square(x2-x1) + np.square(y2-y1))
Can be used directly through the formula, just have to plug in the values and boom it will work.
To find distance to line from point if you have slope and intercept you can use formula from wiki
https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
Python:
def distance(point,coef):
return abs((coef[0]*point[0])-point[1]+coef[1])/math.sqrt((coef[0]*coef[0])+1)
coef is a tuple with slope and intercept
Shortest Distance from Point to a Line
This is the code I got from https://www.geeksforgeeks.org:
import math
# Function to find distance
def shortest_distance(x1, y1, a, b, c):
d = abs((a * x1 + b * y1 + c)) / (math.sqrt(a * a + b * b))
print("Perpendicular distance is", d)
Now you have to find A, B, C, x, and y.
import numpy as np
closest = []
x = (x ,y)
y = (x, y)
coef = np.polyfit(x, y, 1)
A = coef[0]
B = coef[1]
C = A*x[0] + B*x[1]
Now you can plug in the values:
shortest_dis = shortest_distance(x, y, A, B, C)
The full code may look like this:
import math
import numpy as np
def shortest_distance(x1, y1, a, b, c):
d = abs((a * x1 + b * y1 + c)) / (math.sqrt(a * a + b * b))
print("Perpendicular distance is", d)
closest = []
x = (x ,y)
y = (x, y)
coef = np.polyfit(x, y, 1)
A = coef[0]
B = coef[1]
C = A*x[0] + B*x[1]
shortest_dis = shortest_distance(x, y, A, B, C)
Please let me know if any of this is unclear.
Based on the accepted answer
Test with below line equation –
Find the perpendicular distance from the point (5, 6) to the line −2x + 3y + 4 = 0
- x-intercept p1 = [0, -4/3]
- y-intercept p2 = [2, 0]
- shortest distance from p3 = [5, 6] = 3.328
import numpy as np
norm = np.linalg.norm
p1 = np.array([0,-4/3])
p2 = np.array([2, 0])
p3 = np.array([5, 6])
d = np.abs(norm(np.cross(p2-p1, p1-p3)))/norm(p2-p1)
# output d = 3.328201177351375
3D distance should use np.dot
def threeD_corres(points_3_d,pre_points_3_d,points_camera):
for j in range (0,len(pre_points_3_d)):
vec1 = list(map(lambda x:x[0]- x[1],zip(pre_points_3_d[j], points_camera)))
vec2 = list(map(lambda x:x[0]- x[1],zip(pre_points_3_d[j], points_3_d[j])))
vec3 = list(map(lambda x:x[0]- x[1],zip(points_3_d[j], points_camera)))
distance = np.abs(np.dot(vec1_1,vec2_2))/np.linalg.norm(vec3)
print("#########distance:n",distance)
return distance
Cross products are helpful for the 2D case, but they do not generalize well to other dimensions. Dot products do however. The dot product of two orthogonal vectors is zero in any space, which you can use to come up with a simple solution.
Let’s say you have P4
on the same line as P1
–P2
. You could parametrize it with parameter t
such that
P4 = P1 + t * (P2 - P1)
The goal is to find P4
such that
(P3 - P4) . (P2 - P1) == 0
Expanding P4
in terms of t
and simplifying:
(P3 - P1 - t * (P2 - P1)) . (P2 - P1) == 0
(P3 - P1) . (P2 - P1) == t * ||P2 - P1||^2
t = (P3 - P1) . (P2 - P1) / ||P2 - P1||^2
You therefore have
D = ||P3 - P4|| = ||P3 - (P3 - P1) . (P2 - P1) / (||P2 - P1||^2)||
I’ve written a function in my library of utility routines called haggis
. You can use haggis.math.segment_distance
to compute the distance to the entire line (not just the bounded line segment) like this:
d = haggis.math.segment_distance(P3, P1, P2, segment=False)
I’m using Python+Numpy (can maybe also use Scipy) and have three 2D points
(P1, P2, P3);
I am trying to get the distance from P3 perpendicular to a line drawn between P1 and P2. Let P1=(x1,y1)
, P2=(x2,y2)
and P3=(x3,y3)
In vector notation this would be pretty easy, but I’m fairly new to python/numpy and can’t get anythng that works (or even close).
Any tips appreciated, thanks!
Try using the norm function from numpy.linalg
d = norm(np.cross(p2-p1, p1-p3))/norm(p2-p1)
np.cross
returns the z-coordinate of the cross product only for 2D vectors. So the first norm
in the accepted answer is not needed, and is actually dangerous if p3
is an array of vectors rather than a single vector. Best just to use
d=np.cross(p2-p1,p3-p1)/norm(p2-p1)
which for an array of points p3
will give you an array of distances from the line.
For the above-mentioned answers to work, the points need to be numpy arrays, here’s a working example:
import numpy as np
p1=np.array([0,0])
p2=np.array([10,10])
p3=np.array([5,7])
d=np.cross(p2-p1,p3-p1)/np.linalg.norm(p2-p1)
abs((x2-x1)*(y1-y0) - (x1-x0)*(y2-y1)) / np.sqrt(np.square(x2-x1) + np.square(y2-y1))
Can be used directly through the formula, just have to plug in the values and boom it will work.
To find distance to line from point if you have slope and intercept you can use formula from wiki
https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
Python:
def distance(point,coef):
return abs((coef[0]*point[0])-point[1]+coef[1])/math.sqrt((coef[0]*coef[0])+1)
coef is a tuple with slope and intercept
Shortest Distance from Point to a Line
This is the code I got from https://www.geeksforgeeks.org:
import math
# Function to find distance
def shortest_distance(x1, y1, a, b, c):
d = abs((a * x1 + b * y1 + c)) / (math.sqrt(a * a + b * b))
print("Perpendicular distance is", d)
Now you have to find A, B, C, x, and y.
import numpy as np
closest = []
x = (x ,y)
y = (x, y)
coef = np.polyfit(x, y, 1)
A = coef[0]
B = coef[1]
C = A*x[0] + B*x[1]
Now you can plug in the values:
shortest_dis = shortest_distance(x, y, A, B, C)
The full code may look like this:
import math
import numpy as np
def shortest_distance(x1, y1, a, b, c):
d = abs((a * x1 + b * y1 + c)) / (math.sqrt(a * a + b * b))
print("Perpendicular distance is", d)
closest = []
x = (x ,y)
y = (x, y)
coef = np.polyfit(x, y, 1)
A = coef[0]
B = coef[1]
C = A*x[0] + B*x[1]
shortest_dis = shortest_distance(x, y, A, B, C)
Please let me know if any of this is unclear.
Based on the accepted answer
Test with below line equation –
Find the perpendicular distance from the point (5, 6) to the line −2x + 3y + 4 = 0
- x-intercept p1 = [0, -4/3]
- y-intercept p2 = [2, 0]
- shortest distance from p3 = [5, 6] = 3.328
import numpy as np
norm = np.linalg.norm
p1 = np.array([0,-4/3])
p2 = np.array([2, 0])
p3 = np.array([5, 6])
d = np.abs(norm(np.cross(p2-p1, p1-p3)))/norm(p2-p1)
# output d = 3.328201177351375
3D distance should use np.dot
def threeD_corres(points_3_d,pre_points_3_d,points_camera):
for j in range (0,len(pre_points_3_d)):
vec1 = list(map(lambda x:x[0]- x[1],zip(pre_points_3_d[j], points_camera)))
vec2 = list(map(lambda x:x[0]- x[1],zip(pre_points_3_d[j], points_3_d[j])))
vec3 = list(map(lambda x:x[0]- x[1],zip(points_3_d[j], points_camera)))
distance = np.abs(np.dot(vec1_1,vec2_2))/np.linalg.norm(vec3)
print("#########distance:n",distance)
return distance
Cross products are helpful for the 2D case, but they do not generalize well to other dimensions. Dot products do however. The dot product of two orthogonal vectors is zero in any space, which you can use to come up with a simple solution.
Let’s say you have P4
on the same line as P1
–P2
. You could parametrize it with parameter t
such that
P4 = P1 + t * (P2 - P1)
The goal is to find P4
such that
(P3 - P4) . (P2 - P1) == 0
Expanding P4
in terms of t
and simplifying:
(P3 - P1 - t * (P2 - P1)) . (P2 - P1) == 0
(P3 - P1) . (P2 - P1) == t * ||P2 - P1||^2
t = (P3 - P1) . (P2 - P1) / ||P2 - P1||^2
You therefore have
D = ||P3 - P4|| = ||P3 - (P3 - P1) . (P2 - P1) / (||P2 - P1||^2)||
I’ve written a function in my library of utility routines called haggis
. You can use haggis.math.segment_distance
to compute the distance to the entire line (not just the bounded line segment) like this:
d = haggis.math.segment_distance(P3, P1, P2, segment=False)