Home > OS >  How to determine which point is closest to another?
How to determine which point is closest to another?

Time:03-08

I have two lists, the first contains x, y coordinates for the center of a rectangle and the second contains x, y, w, h coordinates for the end points of the line that connects the rectangles. The end points of the lines are x1 = x, y1 = y, x2 = x w, y2 = y h. I am trying to find which end point of the line is closest to the center of the rectangle. I know that I need to use Pythagoras' Theorem to calculate the distance between the end points to the center of the rectangle but I am having issues correctly determining which of them are closest to the center of the correct rectangle.

Interconnected Rectangles

Example

In this example cx1, cy1 closest end point is supposed to be x1, y1 and cx2, cy2 closest end points are supposed to be (x2, y2), (x3, y3) and (x5, y5). The same goes for the other rectangles. The blue lines represent which red dot connects to which green dot.

distance = []
#masterStruc contains the x and y coordinates for the center of the rectangle
for z in range(len(masterStruc)):
    cx = masterStruc[z][3]
    cy = masterStruc[z][4]
    #lineStruc contains the x, y, w, h coordinates for the end points of the line
    for n in range(len(lineStruc)):
        lx = lineStruc[n][0]
        ly = lineStruc[n][1]
        lw = lineStruc[n][2]
        lh = lineStruc[n][3]

        #Calculating the distances from the end points to the center of a rectangle
        dist1 = int(math.sqrt((lx-cx)**2   (ly-cy)**2))
        dist2 = int(math.sqrt((lx lw-cx)**2   (ly lh-cy)**2))

        #Loop to compare which of the distances are closest to the center
        for j in range(len(lineStruc)):
            xx = lineStruc[n][0]
            yy = lineStruc[n][1]
            xw = lineStruc[n][2]
            yh = lineStruc[n][3]

            #Calculating the distances from the end points to the center of a rectangle
            dist3 = int(math.sqrt((xx-cx)**2   (yy-cy)**2))
            dist4 = int(math.sqrt((xx xw-cx)**2   (yy yh-cy)**2))

            #Checking if the distance of the end points are closer
            if(dist1 < dist4):
                lx1 = lx
                ly1 = ly
            elif(dist1 < dist3):
                lx1 = lx
                ly1 = ly
            elif(dist2 < dist4):
                lx1 = lx   lw
                ly1 = ly   lh
            else:
                lx1 = lx   lw
                ly1 = ly   lh
    #Storing the points of the closest end point and center of rectangle
    distance.append([cx, cy, lx1, ly1])

CodePudding user response:

Your code is pretty hard to read and understand due to multiple nested for-loops.

A good practice is to structure the code using functions. Any operation that you can describe in an English sentence should be its own function. As much as possible, avoid nesting loops; instead, encapsulate the inner loop in a function with an explicit name that describes what this function does.

Note that you don't actually need to use math.sqrt, because minimizing the distance is equivalent to minimizing the squared distance.

def squared_distance(p1, p2):
    (x1, y1) = p1
    (x2, y2) = p2
    return (x2 - x1)**2   (y2 - y1)**2

def get_closer_point(center, endpoints):
    x, y, w, h = endpoints
    p1 = (x, y)
    p2 = (x   w, y   h)
    if squared_distance(center, p1) <= squared_distance(center, p2):
        return p1
    else:
        return p2

def get_closer_points(center_list, endpoints_list):
    l = []
    for c, e in zip(center_list, endpoints_list):
        l.append(get_closer_point(c, e))
    return l

# TESTING
centers =   [(0,0), (37, 42), (18, 12)]
endpoints = [(1,0,0,1), (30,40,5,3), (20,20,-5,-5)]

closer_points = get_closer_points(centers, endpoints)
print('centers:   ', centers)
print('endpoints: ', endpoints)
print('closer:    ', closer_points)

# centers:    [(0, 0), (37, 42), (18, 12)]
# endpoints:  [(1, 0, 0, 1), (30, 40, 5, 3), (20, 20, -5, -5)]
# closer:     [(1, 0), (35, 43), (15, 15)]

Sidenote: instead of using our own function to calculate the distance between two points using Pythagoras' theorem, we can avoid reinventing the wheel and look for this function in python's standard library. As it turns out, there is math.dist which does exactly that. So, you can import math.dist, then replace every occurrence of squared_distance in the code above with math.dist instead. This is easy to do, since we've already encapsulated squared_distance as a function; it would be much more annoying to do if we had written Pythagoras' formula explicitly everytime we needed it.

  • Related