Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shortest distance between one point and a group of others? [duplicate]

I have a problem. I want to write a function in python which will receive a coordinate X and a group of coordinates S. I need to return the closest coordinate to x from group s. So when you call a function it will return this:

closest((9, 2), {(0, 0), (10, 0), (10, 10)}) # calling a function
(10, 0) 

Because its the closest to both points. I already have a function which calculates the distance between two points

def distance(s,t):
    v = 0
    for i in range(len(t)):
        v = v+(s[i]-t[i])**2
    return (sqrt(v))

But now I'm stuck on how to return the closest tuple of coordinates to the one given in x. My English is not that good so if you do not understand my question, please say it and I will try to explain somehow.

like image 720
user3083561 Avatar asked Dec 11 '14 16:12

user3083561


People also ask

What is the shortest distance from one point to another?

The shortest distance between two points is a straight line. This distance can be calculated by using the distance formula. The distance between two points ( x 1 , y 1 ) and ( x 2 , y 2 ) can be defined as d = ( x 2 − x 1 ) 2 + ( y 2 − y 1 ) 2 .

How do you find the shortest distance between a point and a vector?

The perpendicular distance between a point and a line is the shortest distance between these two objects. In three dimensions, the perpendicular distance, 𝐷 , between a point 𝑃 ( 𝑥 , 𝑦 , 𝑧 )    and a line with direction vector ⃑ 𝑑 is given by 𝐷 = ‖ ‖  𝐴 𝑃 × ⃑ 𝑑 ‖ ‖ ‖ ‖ ⃑ 𝑑 ‖ ‖ , where 𝐴 is any point on the line.

Why is perpendicular distance shortest?

When we say distance, we mean the shortest possible distance from the point to the line/plane, which happens to be when the distance line through the point is also perpendicular to the line/plane. But why is the shortest line segment perpendicular? This is because the longest side in a right triangle is the hypotenuse.


2 Answers

First you can make a distance function that just returns the distance between two points

import math
def distance(p1, p2):
    return math.sqrt((p2[0] - p1[0])**2 + (p2[1] - p1[1])**2)

Then closest can use the min function with the key parameter to use your distance function with each element from others

def closest(pt, others):
    return min(others, key = lambda i: distance(pt, i))

Example

>>> closest((9, 2), {(0, 0), (10, 0), (10, 10)})
(10, 0)

To calculate the average distance

def avgDistance(pt, others):
    dists = [distance(pt, i) for i in others]
    return sum(dists) / len(dists)

>>> avgDistance((9, 2), {(0, 0), (10, 0), (10, 10)})
6.505956727697075
like image 162
Cory Kramer Avatar answered Nov 14 '22 22:11

Cory Kramer


Don't reinvent the wheel. This functionality exists in python's scientific libraries (scipy) and if you're going to be performing more mathematics on your data, you should really start using those libraries as they are much faster than doing it with regular python, because the code is vectorized and is often a thin wrapper to optimized C/fortran libraries.

>>> import numpy as np
>>> from scipy.spatial.distance import cdist
>>> a = np.array([[9, 2]])
>>> others = np.array([[0, 0], [10, 0], [10, 10]])
>>> def closest_point(pt, others):
...     distances = cdist(pt, others)
...     return others[distances.argmin()]
... 
>>> closest_point(a, others)
array([10,  0])

To compute the mean distance over all distances to that one point:

>>> distances = cdist(a, others)
>>> distances
array([[ 9.21954446,  2.23606798,  8.06225775]])
>>> distances.mean()
6.5059567276970753

Finally, to find the point that is "most centered", in the sense that it has the smallest average distance to all the others, you'll have to compute the distance between all nodes:

>>> all_nodes = np.array([[0,0], [10,0], [0,10], [10, 10], [5,4]])
>>> from scipy.spatial.distance import pdist, squareform
>>> avg_dists = squareform(pdist(all_nodes)).mean(axis=1)
>>> avg_dists
array([ 8.10905197,  8.10905197,  8.39047706,  8.39047706,  5.68534957])
>>> all_nodes[avg_dists.argmin()]
array([5, 4])
like image 39
Oliver W. Avatar answered Nov 14 '22 22:11

Oliver W.