如何确定哪个点最接近另一个点?

How to determine which point is closest to another?

我有两个列表,第一个包含矩形中心的 x、y 坐标第二个包含 x、y、w、h 坐标对于连接矩形的线的端点。 线的端点是 x1 = x, y1 = y, x2 = x + w, y2 = y + h。 我正在尝试找到 直线的哪个端点最接近矩形的中心。 我知道我需要使用毕达哥拉斯定理 计算端点与矩形中心之间的距离,但我无法正确确定它们中的哪一个最接近正确矩形的中心。

Interconnected Rectangles

Example

在这个例子中cx1,cy1最近的端点应该是x1,y1和cx2,cy2最近的端点应该是(x2,y2),(x3,y3)和(x5,y5)。其他矩形也是如此。蓝线表示哪个红点连接到哪个绿点。

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])

由于有多个嵌套 for 循环,您的代码很难阅读和理解。

一个好的做法是使用函数来构建代码。任何你能用英语句子描述的操作都应该是它自己的功能。尽可能避免嵌套循环;相反,将内部循环封装在一个函数中,该函数具有一个明确的名称来描述该函数的作用。

请注意,您实际上不需要使用math.sqrt,因为最小化距离等同于最小化平方距离。

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)]

旁注:不用我们自己的函数使用毕达哥拉斯定理计算两点之间的距离,我们可以避免重新发明轮子并在python的标准库中寻找这个函数。事实证明, math.dist 正是这样做的。因此,您可以导入 math.dist,然后将上面代码中每个出现的 squared_distance 替换为 math.dist。这很容易做到,因为我们已经将 squared_distance 封装为一个函数;如果我们每次需要时都明确地写下毕达哥拉斯公式,那会更烦人。