Python 找出三个最近的点,其中三角形包含球体上的给定点

Python 找出三个最近的点,其中三角形包含球体上的给定点,python,geometry,point,closest-points,spherical-coordinate,Python,Geometry,Point,Closest Points,Spherical Coordinate,我有一个表面上有点的3D球体。这些点以球坐标表示,因此方位角、仰角和r 例如,我的数据集是一个矩阵,包含给定球体上的所有可用点: azimuth elevation r [[ 0. 90. 1.47 ] [ 0. 85.2073787 1.47 ] [ 0. 78.16966379 1.47 ] [ 0. 70.30452954

我有一个表面上有点的3D球体。这些点以球坐标表示,因此方位角、仰角和r

例如,我的数据集是一个矩阵,包含给定球体上的所有可用点:

  azimuth       elevation     r
[[  0.          90.           1.47      ]
 [  0.          85.2073787    1.47      ]
 [  0.          78.16966379   1.47      ]
 [  0.          70.30452954   1.47      ]
 [  0.          62.0367492    1.47      ]
 [  0.          53.56289304   1.47      ]
 [  0.          45.           1.47      ]
 [  0.          36.43710696   1.47      ]
 [  0.          27.9632508    1.47      ]
 [  0.          19.69547046   1.47      ]
 [  0.          11.83033621   1.47      ]
 [  0.           4.7926213    1.47      ]
 [  0.           0.           1.47      ]
 [  0.          -4.7926213    1.47      ]
 [  0.         -11.83033621   1.47      ]
 [  0.         -19.69547046   1.47      ]
 [  0.         -27.9632508    1.47      ]
 [  0.         -36.43710696   1.47      ]
 [  0.         -45.           1.47      ]
 [  0.         -53.56289304   1.47      ]
 [  0.         -62.0367492    1.47      ]
 [  0.         -70.30452954   1.47      ]
 [  0.         -78.16966379   1.47      ]
 [  0.         -85.2073787    1.47      ]
 [  0.         -90.           1.47      ]
 [  1.64008341  -1.6394119    1.47      ]
 [  1.64008341   1.6394119    1.47      ]
 [  2.37160039   8.01881788   1.47      ]
 [  2.37160039  -8.01881788   1.47      ]
 [  2.80356493 -15.58649429   1.47      ]
 [  2.80356493  15.58649429   1.47      ]
 [  3.16999007  23.70233802   1.47      ]
 [  3.16999007 -23.70233802   1.47      ]
 [  3.56208248 -32.09871039   1.47      ]
 [  3.56208248  32.09871039   1.47      ]
 [  4.04606896  40.63141594   1.47      ]
 [  4.04606896 -40.63141594   1.47      ]
 [  4.1063771   -4.09587122   1.47      ]
ecc...
注意:我故意省略了完整的数据矩阵,因为它包含了相当多的数据。如果需要/需要使问题完全可再现,我将提供完整数据

此矩阵表示类似于此图像的内容:

给定一个任意点,我想计算数据集中“包含”输入点的3个最近点

到目前为止,我的代码如下:

def compute_three_closest_positions(self, azimuth_angle, elevation):
    requested_position = np.array([azimuth_angle, elevation, 0])

    # computing the absolute difference between the requested angles and the available one in the dataset
    result = abs(self.sourcePositions - requested_position) #subtracting between dataset and requested point
    result = np.delete(result, 2, 1) # removing the r data 
    result = result.sum(axis=1) #summing the overall difference for each point

    # returning index of the closest points
    indexes = result.argsort()[:3] 

    closest_points = self.sourcePositions[indexes]
    
    return closest_points 
基本上,我是从矩阵数据集中的所有点(
self.sourcePositions
)中减去请求的方位角和仰角,然后对每个点的差异求和,计算前3个最小索引,然后使用这些索引访问数据集中的点

代码运行良好,问题是有时我会得到3个不包含请求点的最近点

示例:

错的一个:

  Requested point: azimut, elevation, distance
    [200   0   1.47]
    # As you might notice, the requested point is not inside the triangle created by the 3 closest points
    Three closest points: azimut, elevation, distance
    [[199.69547046   0.           1.47      ]
     [199.40203659   5.61508214   1.47      ]
     [199.40203659  -5.61508214   1.47      ]]
好的:

Requested position:
[190   0   1.47]
# As you can notice, in this case the requested point is inside the triangle generated by the closest 3 points
Three closest points:
[[191.83033621   0.           1.47      ]
 [188.02560265   2.34839855   1.47      ]
 [188.02560265  -2.34839855   1.47      ]]

我如何解决这个问题?我想得到3个最近的点,其中“三角形”(我在球面上,所以它不是真正的三角形)包含我请求的点。

从初学者那里
方位角+仰角
听起来不太合适,我更喜欢
纬度+经度
therms,因为你使用的是其他东西

现在,如注释中所述,如果您的点形成一个规则的网格,您可以创建一个方程,将拓扑映射到点,然后再映射到由数组中的点的整数索引(或2个索引)描述拓扑的位置。但是,如果您无法推断这一点,或者网格不规则,则可以执行以下操作:

  • 对数组重新排序,使其按纬度和长度排序

    所以经度在
    中,纬度在
    中,所以我会根据这两者对数组进行排序,而纬度的优先级(权重)更高。让我们调用这个新数组
    pnt[]

  • 将点
    p
    映射到球体的最近顶点

    只需二进制搜索
    pnt[]
    ,直到找到比
    p

    然后从
    ix
    线性搜索(如果您将
    pnt[]
    重新排序为切片或记住每个纬度有多少个点,则可以使用二进制搜索),直到找到小于或等于
    p
    的最大纬度

    现在
    pnt[ix]
    是球体上距离
    p

  • 列出最靠近
    pnt[ix]

    因此,简单地说,
    pnt[ix]
    是从经度的左侧开始的,所以
    pnt[ix+1]
    应该是下一个点(如果你穿过阵列大小,你需要用蛮力检查这些点,但只是阵列中的最后几个点)

    现在我们只需要在这两个点的下方或上方找到相应的点(取决于
    p
    在哪一侧)。因此,以与
    #2
    相同的方式找到距离
    p
    最近的两个点,但纬度越小越大(前后各一片)。这将得到
    3*2个点
    ,它们形成(始终使用最先找到的2个点)4个潜在三角形

  • 测试可能的三角形

    所以你们有一个潜在的三角形,和球面平行。因此,只需将点投影到其平面上:

    u = p1-p0
    v = p2-p0
    v = cross(u,v)
    v = cross(u,v)
    p' = p0 + dot(p-p0,u)*u + dot(p-p0,v)*v
    
    因此,
    u,v
    是基向量,
    p0
    是平面的原点。。。现在,
    p'
    的测试就在三角形内部,所以要么使用2D和重心坐标,要么利用叉积,检查CW/CCW,如:

     if (dot(cross(p1-p0,p'-p0),p')>=0)
      if (dot(cross(p2-p1,p'-p1),p')>=0)
       if (dot(cross(p0-p2,p'-p2),p')>=0)
        point_is_inside;
     if (dot(cross(p1-p0,p'-p0),p')<=0)
      if (dot(cross(p2-p1,p'-p1),p')<=0)
       if (dot(cross(p0-p2,p'-p2),p')<=0)
        point_is_inside;
    
    if(点(交叉点(p1-p0,p'-p0),p'>=0)
    如果(点(交叉点(p2-p1,p'-p1),p'>=0)
    如果(点(交叉点(p0-p2,p'-p2),p'>=0)
    点在里面;
    
    if(dot(cross(p1-p0,p'-p0,p'))你有代码可以判断点是否在“三角形”中吗?不幸的是,没有,这就是我正在努力的地方。我不知道如何正确地检查返回的三元组是否包含我的点。即使我能够做到这一点,我也不知道如何用“基线”计算正确的三元组我有密码。看起来(至少对我来说)对于我想要完成的任务,我的简单解决方案有一些缺点,但我不确定。你的点肯定会形成三角形网格。如果你有这个网格的数学定义,可以通过简单的计算找到所需的三角形。@MBo不幸的是,我无法找到这些点的数学定义。它是一个3D音频数据集(),在球体上具有离散度量。您可以对所有点进行三角剖分。然后找到包含您的点的三角形(也称为“定位点”)。这些任务的算法很容易找到。