L Lawliet
L Lawliet

Reputation: 459

Find point distance from line - python

I have 3 points

p1 = 48.36736702002282, 11.112351406920268
p2 = 48.36728222003929, 11.112716801718284
p3 = 48.36720362305641,11.112587917596102

I want to find the perpendicular distance from p3 to p1 & p2.

To do so, my plan is, create a line using p1 and p2 and then will try to find the perpendicular distance from point p3 to line(created from p1 & p2).

I am following from HERE

Code from geeksforgeeks:

# Python program to find the distance between 
# a given point and a given line in 2 D. 

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 
    

# Driver Code 
x1 = 5
y1 = 6
a = -2
b = 3
c = 4
shortest_distance(x1, y1, a, b, c) 

What I am not able to understand is how to create line using p1 and p2 and what should be the value of x1, y1, a, b, c in above code

Upvotes: 3

Views: 1958

Answers (5)

Krishan Subudhi
Krishan Subudhi

Reputation: 386

What I am not able to understand is how to create line using p1 and p2 and what should be the value of x1, y1, a, b, c in above code

Here, (x1, y1) are coordinates of the point from which distance need to be found out. a,b,c are coeffecients of the line equation ax+by+c = 0

To create a line from p1, p2 in the form of ax + by + c = 0, you can use slope intercept formula (y = mx + c)

slope = m = (y2-y1)/(x2-x1)
intercept = i = y1 - m * x1

now the equation can be written in the format mx -y + i = 0
Hence a = m, b = -1, c = i


On a separate note, if you have two points for a line you don't need to find the equation to solve it. you can use the following formula

np.cross(p3-p1, p2-p1) / np.linalg.norm(p2-p1)

Upvotes: 0

blunova
blunova

Reputation: 2532

That's easily done using, for instance, the scikit-spatial library:

from skspatial.objects import Point, Line

# Define points
p1 = Point([48.36736702002282, 11.112351406920268])
p2 = Point([48.36728222003929, 11.112716801718284])
p3 = Point([48.36720362305641,11.112587917596102])

# Define line passing through p1 and p2
line_p12 = Line.from_points(p1, p2)

# Compute p3-line_p12 distance
distance = line_p12.distance_point(p3)

Upvotes: 1

Futurologist
Futurologist

Reputation: 1914

If you are talking about points on the surface of the Earth given in latitude and longitude coordinates, where the Earth is modeled as a perfect sphere of radius R = 6371000 meters, a lot of this formula stuff can be easily derived from simple 3D vector geometry.

import numpy as np
import math

R = 6371000

def cos_sin(angle):
    return math.cos(math.pi*angle/180), math.sin(math.pi*angle/180)

def S(point):
    cos_phi, sin_phi = cos_sin(point[0])
    cos_lambda, sin_lambda = cos_sin(point[1])
    return np.array([cos_phi*cos_lambda,
                      cos_phi*sin_lambda,
                      sin_phi])

def height(P1, P2, P3):
    N = np.cross(S(P1), S(P2))
    N = N / np.linalg.norm(N)
    return R*(math.pi/2 - math.acos( abs( S(P3).dot(N)) ))




p1 = 48.36736702002282, 11.112351406920268
p2 = 48.36728222003929, 11.112716801718284
p3 = 48.36720362305641, 11.112587917596102   

print(height(p1, p2, p3))

Upvotes: 0

Willem Hendriks
Willem Hendriks

Reputation: 1487

This is the answer using haversine, in python, using

Distance from Lat/Lng point to Minor Arc segment

import numpy as np
from sklearn.neighbors import DistanceMetric

dist = DistanceMetric.get_metric('haversine')

def bear( latA,lonA,latB,lonB ):
    b= np.arctan2( np.sin(lonB-lonA)*np.cos(latB) , np.cos(latA)*np.sin(latB) - np.sin(latA)*np.cos(latB)*np.cos(lonB-lonA) )
    
    return b

def crossarc( p1, p2, p3 ):
    """
     CROSSARC Calculates the shortest distance 

     between an arc (defined by p1 and p2) and a third point, p3.

     Input lat1,lon1,lat2,lon2,lat3,lon3 in degrees.
    """
    lat1,lon1 = p1
    lat2,lon2 = p2
    lat3,lon3 = p3
    
    lat1= np.radians(lat1);
    lat2= np.radians(lat2);
    lat3= np.radians(lat3);
    lon1= np.radians(lon1);
    lon2= np.radians(lon2);
    lon3= np.radians(lon3);

    bear12 = bear(lat1,lon1,lat2,lon2);
    bear13 = bear(lat1,lon1,lat3,lon3);
    
    dis13 = dist.pairwise(np.array([[lat1, lon1]]), np.array([[lat3, lon3]]))[0][0]

    diff = np.abs(bear13-bear12);
    
    if diff > np.pi:
        diff = 2 * np.pi - diff;

    if diff > (np.pi/2):
        dxa = dis13
        
    else:
        dxt = np.arcsin( np.sin(dis13)* np.sin(bear13 - bear12) );

        dis12 = dist.pairwise(np.array([[lat1, lon1]]), np.array([[lat2, lon2]]))[0][0]
        dis14 = np.arccos( np.cos(dis13) / np.cos(dxt) );
        
        if dis14 > dis12:
            dxa = dist.pairwise(np.array([[lat2, lon2]]), np.array([[lat3, lon3]]))[0][0]
        else:
            dxa = np.abs(dxt);
            
    return dxa

and we have

p1 = 48.36736702002282, 11.112351406920268
p2 = 48.36728222003929, 11.112716801718284
p3 = 48.36720362305641, 11.112587917596102

Then crossarc(p1,p2,p3) will return the distance (haversine), to convert it for instance to meters use earth radius with

print("Distance in meters: {}".format( 6371000 * crossarc(p1,p2,p3) ))

which outputs

Distance in meters: 11.390566923942787

Upvotes: 1

joostblack
joostblack

Reputation: 2525

Using the equation from wikipedia (in my opinion a good source but that is debatable):

import math
def find_distance(p1,p2,p3):
    nom = abs((p2[0]-p1[0])*(p1[1]-p3[1])-(p1[0]-p3[0])*(p2[1]-p1[1]))
    denom = math.sqrt((p2[0]-p1[0])**2+(p2[1]-p1[1])**2)
    return nom/denom

print(find_distance(p1,p2,p3))

output:

0.0001056989661888993

Upvotes: 1

Related Questions