首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >确定两个点是否最接近另一个点的最快方法

确定两个点是否最接近另一个点的最快方法
EN

Stack Overflow用户
提问于 2019-04-22 20:09:52
回答 1查看 1.1K关注 0票数 0

我的问题包括以下几个方面:给出两对角(在球面坐标下),它由两部分组成--方位角和纬度角。如果我们把这两个角度(从而增大它们各自的半径)无限地扩展成一条长直线指向这一对角度所给出的方向,那么我的目标是确定

  1. 如果它们相交或非常接近,
  2. 它们到底在哪里相交。

目前,我尝试了几种方法:

  1. 最明显的方法是迭代比较每个半径,直到两者之间有一个匹配或足够小的距离。(当我说比较每个半径时,我指的是将每个球面坐标转换成笛卡儿,然后求出两者之间的欧几里德距离)。然而,这个运行时是$O(n^{2})$,如果我试图缩放这个程序,这是非常慢的。
  2. 第二个最明显的方法是使用优化包来找到这个距离。不幸的是,我不能迭代优化包,在一个实例之后,优化算法重复相同的答案,这是没有用的。
  3. 最不明显的方法是从角度直接计算(用微积分)精确的半径。虽然这是快速的方法,但并不是非常准确。

注意:虽然交集总是在零原点(0,0,0)看起来很简单,但情况并不总是这样。有些观点永远不会相交。

方法的代码(1)

代码语言:javascript
运行
复制
def match1(azimuth_recon_1,colatitude_recon_1,azimuth_recon_2, colatitude_recon_2,centroid_1,centroid_2 ):


   # Constants: tolerance factor and extremely large distance
    tol = 3e-2
    prevDist = 99999999

    # Initialize a list of radii to loop through
    # Checking iteravely for a solution
    for r1 in list(np.arange(0,5,tol)):
        for r2 in list(np.arange(0,5,tol)):

            # Get the estimates
            estimate_1 = np.array(spher2cart(r1,azimuth_recon_1,colatitude_recon_1)) + np.array(centroid_1)
            estimate_2 = np.array(spher2cart(r2,azimuth_recon_2,colatitude_recon_2))+ np.array(centroid_2)

            # Calculate the euclidean distance between them
            dist = np.array(np.sqrt(np.einsum('i...,i...', (estimate_1 - estimate_2), (estimate_1 - estimate_2)))[:,np.newaxis])

        # Compare the distance to this tolerance
            if dist < tol: 
                if dist == 0:
                    return estimate_1, [], True
                else:
                    return estimate_1, estimate_2, False

            ## If the distance is too big break out of the loop
            if dist > prevDist:
                prevDist = 9999999
                break
            prevDist = dist

    return [], [], False

方法的代码(3)

代码语言:javascript
运行
复制
def match2(azimuth_recon_1,colatitude_recon_1,azimuth_recon_2, colatitude_recon_2,centriod_1,centroid_2):

   # Set a Tolerance factor
    tol = 3e-2

    def calculate_radius_2(azimuth_1,colatitude_1,azimuth_2,colatitude_2):

        """Return radius 2 using both pairs of angles (azimuth and colatitude). Equation is provided in the document"""

        return 1/((1-(math.sin(azimuth_1)*math.sin(azimuth_2)*math.cos(colatitude_1-colatitude_2))
        +math.cos(azimuth_1)*math.cos(azimuth_2))**2)

    def calculate_radius_1(radius_2,azimuth_1,colatitude_1,azimuth_2,colatitude_2):

        """Returns radius 1 using both pairs of angles (azimuth and colatitude) and radius 2. 
    Equation provided in document"""

        return (radius_2)*((math.sin(azimuth_1)*math.sin(azimuth_2)*math.cos(colatitude_1-colatitude_2))
        +math.cos(azimuth_1)*math.cos(azimuth_2))

    # Compute radius 2
    radius_2 = calculate_radius_2(azimuth_recon_1,colatitude_recon_1,azimuth_recon_2,colatitude_recon_2)

    #Compute radius 1
    radius_1 = calculate_radius_1(radius_2,azimuth_recon_1,colatitude_recon_1,azimuth_recon_2,colatitude_recon_2)

    # Get the estimates
    estimate_1 = np.array(spher2cart(radius_1,azimuth_recon_1,colatitude_recon_1))+ np.array(centroid_1)
    estimate_2 = np.array(spher2cart(radius_2,azimuth_recon_2,colatitude_recon_2))+ np.array(centroid_2) 

    # Calculate the euclidean distance between them
    dist = np.array(np.sqrt(np.einsum('i...,i...', (estimate_1 - estimate_2), (estimate_1 - estimate_2)))[:,np.newaxis])

    # Compare the distance to this tolerance
    if dist < tol: 
        if dist == 0:
            return estimate_1, [], True
        else:
            return estimate_1, estimate_2, False
    else:
        return [], [], False

我的问题有两方面:

  1. 有没有一种更快、更准确的方法来找出这两个点的半径?
  2. 如果是的话,我该如何做?

编辑:我正在考虑创建这两个半径的两个numpy数组,然后通过numpy布尔逻辑对它们进行比较。但是,我仍然会反复比较它们。有更快的方法来进行这种比较吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-11 23:58:30

在这种情况下使用kd树。它将很容易地查找最小距离:

代码语言:javascript
运行
复制
def match(azimuth_recon_1,colatitude_recon_1,azimuth_recon_2, colatitude_recon_2,centriod_1,centroid_2):

    cartesian_1 = np.array([np.cos(azimuth_recon_1)*np.sin(colatitude_recon_1),np.sin(azimuth_recon_1)*np.sin(colatitude_recon_1),np.cos(colatitude_recon_1)]) #[np.newaxis,:]
    cartesian_2 = np.array([np.cos(azimuth_recon_2)*np.sin(colatitude_recon_2),np.sin(azimuth_recon_2)*np.sin(colatitude_recon_2),np.cos(colatitude_recon_2)]) #[np.newaxis,:]

    # Re-center them via adding the centroid
    estimate_1 = r1*cartesian_1.T + np.array(centroid_1)[np.newaxis,:] 
    estimate_2 = r2*cartesian_2.T + np.array(centroid_2)[np.newaxis,:]

    # Add them to the output list
    n = estimate_1.shape[0]
    outputs_list_1.append(estimate_1)
    outputs_list_2.append(estimate_2)

    # Reshape them so that they are in proper format
    a = np.array(outputs_list_1).reshape(len(two_pair_mic_list)*n,3)
    b = np.array(outputs_list_2).reshape(len(two_pair_mic_list)*n,3)

    # Get the difference
    c = a - b

    # Put into a KDtree
    tree = spatial.KDTree(c)

    # Find the indices where the radius (distance between the points) is 3e-3 or less 
    indices = tree.query_ball_tree(3e-3)

这将输出距离为3e-3或更短的索引列表。现在,您所要做的就是使用索引列表和估计列表来找到确切的点。在这里,这将节省你大量的时间和空间!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55800477

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档