代码之家  ›  专栏  ›  技术社区  ›  LizardWizard

我正在使用随机生成的有序对的numpy数组,我需要确定有序对是否是不同类型的三角形

  •  1
  • LizardWizard  · 技术社区  · 8 年前

    本周我刚开始使用numpy,对此我感到非常困惑。看起来与普通的python函数非常不同。

    对于形状为1000X6的数组,是否有一种方法可以在数组中逐行检查,例如一个等边三角形。我有6列,所以每行有三个整数,每个点有2个整数。

    import numpy as np
    pnts = np.random.randint(0,50,(1000, 6))
    

    我还认为创建3个这样的数组可能更好:

    import numpy as np
    A = np.random.random((10,2))
    B = np.random.random((10,2))
    C = np.random.random((10,2))
    

    创建有序对,然后使用算法找到三角形。

    有没有更好的方法来创建一个表示1000个有序对的三元组的数组,以及如何在该数组中找到三角形,例如等边三角形。

    我现在做了一些改变。我为x坐标和y坐标制作了两个数组。

    x = np.random.randint(0,10,(3,1000))
    y = np.random.randint(0,10,(3,1000))
    

    #############添加到问题#############

    我有一个算法,它可以获取每个匹配的x和y坐标,找到每个三角形的边长和角度。我会发帖,但代码太多了。现在我有了一些函数,它们使用角度和边长来找到等角线、等边线、右等角线和非右等角点。

    我的问题现在更与指数有关。我将再次以等边三角形为例,因为这是我们一直在研究的。

    E = np.column_stack((ACXY,ABXY,CBXY))
    ES = np.logical_and(E[:,0] == E[:,1], E[:,1] == E[:,2])
    

    我用这个来找到等边三角形。

    - ACXY = the distance from point A to C
    - ABXY = the distance from point A to B
    - CBXY = the distance from point C to B
    

    我希望能够获取所有等边三角形的坐标三元组,对它们进行索引,并将它们放入一个名为E_Tri的新数组中。我认为我不需要创建布尔值的函数。我认为If:else:语句也许是更好的方法。

    这也可能有帮助,我会显示 E = np.column_stack((ACXY,ABXY,CBXY)) 以帮助理解(E)的阵列。

    [[  4.           4.47213595   7.21110255]
     [  3.60555128   2.23606798   5.83095189]
     [  2.23606798   9.05538514   8.54400375]
     ..., 
     [  3.60555128   9.05538514   6.08276253]
     [  8.94427191   8.54400375   1.        ]
     [ 10.63014581   1.          10.        ]]
    

    E将看起来像这样。希望这将有意义,如果没有请让我知道。

    也许是这样的,尽管这仅仅是增加问题的一部分是行不通的。

    E = np.column_stack((ACXY,ABXY,CBXY))
    equilateral = [] 
    def E_Tri(E):
        if E[:,0] == E[:,1] and E[:,1] == E[:,2]:
            equilateral.append(E_Tri)
        else:
            return E
    
    1 回复  |  直到 8 年前
        1
  •  3
  •   John Zwinck    8 年前

    您已经很好地描述了如何存储数据,但没有描述算法是什么。例如,如果我们想回答“这组三(x,y)点P1..P3是等边三角形吗”,我们可以这样表述:

    dist(P1,P2) == dist(P2,P3) == dist(P3,P1)
    

    哪里 dist(P1,P2) 使用毕达哥拉斯定理:

    sqrt((P1.x - P2.x)**2 + (P1.y - P2.y)**2)
    

    但请注意 sqrt() 这是不必要的,因为我们只关心三条腿的长度是否相等(如果它们相等,它们的平方也会相等)。

    在NumPy中,我们希望以可并行的方式进行所有操作。因此,如果你有一个代表1000个三角形的1000x6数组,你需要一次对1000个元素执行所有操作。如果数组名为A,其列为:

    P1.x, P1.y, P2.x, P2.y, P3.x, P3.y
    

    然后,第一个操作是:

    A[0] - A[2] # P1.x - P2.x
    A[1] - A[3] # P1.y - P2.y
    A[2] - A[4]
    A[3] - A[5]
    A[4] - A[0]
    A[5] - A[1]
    

    这可以写得更简洁:

    R = A - np.roll(A, -2, axis=0) # 1000x6 array of all differences
    

    完成后,您可以一次对所有1000x6结果求平方,得到一个1000x6数组R,从中我们将x和y对相加,得到距离的平方:

    R[0] + R[1] # (P1.x - P2.x)**2 + (P1.y - P2.y)**2
    R[2] + R[3]
    R[4] + R[5]
    

    也就是说:

    S = R[0::2] + R[1::2] # three column-wise additions at once
    

    这给了我们1000x3平方的距离数组S。现在我们只需检查每一行的列是否都相等:

    np.logical_and(S[0] == S[1], S[1] == S[2])
    

    这给了我们1000x1布尔向量,它告诉我们每一行是否是等边三角形。

    请注意,我们从未以迭代的方式逐行进行。这是因为在NumPy中这样做比执行逐列操作慢得多。

    请注意,我写了上面的内容,假设数组的形状实际上是 (6,1000) 当我说 1000x6 .这是为了便于标注( A[0] 而不是 A[:,0] )也因为当我们在列上操作时,它更高效,因为NumPy默认使用行主顺序。你可以 np.transpose() 您的输入数据(如果需要)。

    因此,最终它只是:

    A = pnts.T
    R = np.square(A - np.roll(A, -2, axis=0))
    S = R[0::2] + R[1::2] # 1000x3 squares of distances
    np.logical_and(S[0] == S[1], S[1] == S[2]) # 1000 True/False results