3

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

L Lawliet
  • 419
  • 1
  • 7
  • 20

5 Answers5

1

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
joostblack
  • 2,465
  • 5
  • 14
  • Is distance in `cm` or `m`? – L Lawliet Mar 01 '21 at 16:00
  • @L Lawliet The distance is in points, you have to convert you coordinates into radiant values by using `np.radiant(p1)` and you have to multiply with the radius of the earth at the end (6371000m) to get meters – QuagTeX Oct 19 '22 at 08:56
1

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

Willem Hendriks
  • 1,267
  • 2
  • 9
  • 15
1

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)
blunova
  • 2,122
  • 3
  • 9
  • 21
  • This answer doesn't give the "real" distance. The output of your code would be `0.00010569896` with the unit points. You have to change the points with `np.radians()` to radiant. Afterwards you have to multiply the distance with 6371km (radius of the earth) to get the distance in km or 6371000 to get them in meters. The new result after these adaptians is `11.75318...m` – QuagTeX Oct 19 '22 at 08:52
  • I don't know why there is a difference between this result and the results of the other answers – QuagTeX Oct 19 '22 at 08:57
0

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))
Futurologist
  • 1,874
  • 2
  • 7
  • 9
0

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)
Krishan Subudhi
  • 376
  • 3
  • 18