Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the most efficient way to calculate the maximum distance of two points in a list?

I have a list L of points (x, y) and the usual euclidean distance measure

enter image description here

How do I find the maximum distance two points have in this list? Or, more formally: How do I find

enter image description here

The trivial approach

The simplest way to solve this problem seems to be to try everything:

def find_max_dist(L):
    max_dist = d(L[0], L[1])
    for i in range(0, len(L)-1):
        for j in range(i+1, len(L):
            max_dist = max(d(L[i], L[j]), max_dist)
    return max_dist

To make computation faster, I can use the squared distance in the loops and return the root at the end.

This approach has a run time complexity of O(n^2) where n is the lenght of the list L. (And a constant space complexity).

Convex Hull

Obviously, there cannot be any algorithm that is faster than O(n), as one has to look at least once at every element in the list.

The highest distance will be between elements of the convex hull. But it is easy to prove that the computation of the convex hull is at least in O(n log n) and Graham's scan seems to do it. But after finding the complex hull I still have to get the maximum distance. So I would end up with

def find_max_dist_graham_triv(L):
    H = Graham_scan(L)
    return find_max_dist(L)

Now, this is a point where I am not sure. I think one can improve this like so:

def find_max_dist_graham_c1(L):
    H = Graham_scan(L)  # Get ordered list of convex hull points
    max_dist = d(L[0], L[1])
    for i in range(0, len(L)-1):
        loop_max_dist = 0
        for j in range(i+1, len(L):
            curr_dist = d(L[i], L[j])
            if curr_dist < loop_max_dist:
                break
            loop_max_dist = curr_dist
            max_dist = max(loop_max_dist, max_dist)

    return max_dist

The idea is that when you take one point of a convex hull and start from its neighboring point, the diagonals keep increasing, get to a maximum and then keep decreasing. I'm not sure if this is true, though.

Intuitively, I would continue to improve the algorithm: As soon as the first inner loop finishes, we found a "longest diagonal" of that loop. This diagonal separates all other hull points in two disjunct sets. Every longer diagonal has to consist of points from both of those sets (correct?):

def find_max_dist_graham_c1(L):
    H = Graham_scan(L)  # Get ordered list of convex hull points
    max_dist = d(L[0], L[1])  # Get a fist idea what the longest distance might be

    i = 0
    p1 = L[i]  # Grab a random point
    loop_max_dist = 0
    for j in range(1, len(L):
        curr_dist = d(L[i], L[j])
        if curr_dist < loop_max_dist:
            break
        loop_max_dist = curr_dist
        max_dist = max(loop_max_dist, max_dist)
    # Every diagonal that is longer than the best one found with L[0]
    # has to have points in both of the following two sets (correct?):
    # [1...j] and [j+1...len(L)]

    # Try to find a neighboring diagonal that is longer.
    change = True
    while change:
        change = False
        if d(L[i-1], L[j+1]) > max_dist:
            max_dist = d(L[i-1], L[j+1])
            i -= 1
            j += 1
            change = True
        elif d(L[i+1], L[j-1]) > max_dist:
            max_dist = d(L[i+1], L[j-1])
            i += 1
            j -= 1
            change = True
    return max_dist

Every point P on the convex hull has a point Q on the convex hull such that PQ is the longest diagonal including P. But is then P also the "endpoint" for the longest diagonal of Q?

I am really not sure if this algorithm is correct. It would be in O(n log n).

I guess the problem is well analyzed, so could somebody please leave some notes for that?

Although I had a lot of sub-questions the main question is:

What is an efficient way to find the maximum distance of points in a list of points?

like image 452
Martin Thoma Avatar asked Jun 29 '14 05:06

Martin Thoma


People also ask

Is it possible to find the minimum distance between two segments?

Actually an algorithm which works for two sets of points is preferred more. – jk. You are right. Sometimes, the minimum distance is between a vertex and a segment. But it cannot be between two segments. By the way, the most naive algorithm to find this is checking each vertex with the other polygon and doing it for both polygons.

How do you find the distance of a matrix of points?

numpy.sqrt((X**2).sum(axis=1)[:, None] - 2 * X.dot(Y.transpose()) + ((Y**2).sum(axis=1)[None, :]) – BGabor Feb 24 '17 at 15:29 Add a comment | 1 You can also use the development of the norm (similar to remarkable identities). This is probably the most efficent way to compute the distance of a matrix of points.

What is the best way to calculate the Euclidean distance?

I would use the sklearn implementation of the euclidean distance. The advantage is the usage of the more efficient expression by using Matrix multiplication: dist(x, y) = sqrt(dot(x, x) - 2 * dot(x, y) + dot(y, y)

How to find the minimum Euclidean distance between two intersecting polygons?

Let P = { p1 , p2 ,..., pm } and Q = { q1, q2 ,..., qn } be two intersecting polygons whose vertices are specified by their cartesian coordinates in order. An optimal O ( m + n ) algorithm is presented for computing the minimum euclidean distance between a vertex pi in P and a vertex qj in Q.


1 Answers

You should look up on Rotating calipers(http://en.wikipedia.org/wiki/Rotating_calipers) - they're widely used for that kind of problems. Also, your assumption is wrong. For a fixed point p on the convex polygon: the diagonal can first increase, then decrease, then increase, and then decrease again. At least, I've got a case where this happens.

A heuristic approach also: select a point x. Find the furthest point y from it. Find the furthest point z from y. d(z,y) is a good estimation.

The image that illustrates the diagonals:

enter image description here

1->2: increasing; 2->3 decreasing; 3->4 increasing; 4->5 decreasing. The figure may not be precise, move the points that 3 and 4 point to a bit further away from p (on the same line).

like image 128
Amtrix Avatar answered Dec 14 '22 16:12

Amtrix