【问题标题】:how to sample points in 3D in python with origin and normal vector如何使用原点和法线向量在 python 中对 3D 中的点进行采样
【发布时间】:2022-11-19 04:38:15
【问题描述】:

我在 3D 中有两个点 p1(x1, y1, z1) 和 p2(x2, y2, z2)。我想在以 p1 为中心的半径为 r 的圆和垂直于向量 p2-p1 的平面中采样点(因此 p2-p1 将是该平面的法向量)。我有使用极坐标系统在 XOY 平面上进行采样的代码,但在如何推广到与 (0, 0, 1) 不同的法线方面遇到了困难

rho = np.linspace(0, 2*np.pi, 50)
r = 1
x = np.cos(rho) * r
y = np.sin(rho) * r
z = np.zeros(rho.shape)

Sampled points

【问题讨论】:

    标签: python numpy geometry linear-algebra


    【解决方案1】:

    首先,您需要在圆的平面上定义两个基本向量。

    第一个是与法线正交的任意向量n = p2-p1

    选择具有最大幅度的法线分量和具有第二个幅度的分量。

    交换它们的值,取最大的取反,使第三分量为零(注意结果与法线的点积为零,所以它们是正交的)

    例如,如果n.y最大,n.z第二,则

    v = (0, n.z, -n.y)
    

    然后使用向量积计算第二个基向量

    u = n x v 
    

    规范化向量 vu。在矢量形式上使用中心点p1 圈点:

     f(rho) = p1 + r * v * cos(rho) + r * u * sin(rho)
    

    或在组件中:

     f.x = p1.x + r * v.x * cos(rho) + r * u.x * sin(rho)
    and so on
    

    【讨论】:

    • @Pxxxx96 我的回答不清楚吗?
    • 您好,非常感谢!这确实有效,但您能否详细说明其背后的原因?例如,我明白为什么v与v正交,u也与v和n都正交,但为什么选择v作为这种特定形式,为什么最后的f代表圆?
    • 我们应该找到一些与 n 点积为零的向量。这种方法只是给出了创建此类向量的任意示例。 0*nx+ny*nz-nz*ny==0 总是,选择最大的否定分量提供非零向量(如果 n 不为零)。
    • 关于圆 - 3D 中的圆可以用这样的定义来描述。两个单位垂直矢量构成基础,它们与 sin 和 cos 的组合给出圆 - 与 2d 中的矢量 (1,0) 和 (0,1) 完全一样。如果我们将基础 origin,(1,0),(0,1) 旋转并移动到 p1, v, u - 我们将得到 3d 圆
    • 如果我们旋转和移动基础 (0,0.0),(1,0.0),(0,1,0) 将其转换为 p1, v, u,我们将在 3d 中得到圆
    【解决方案2】:

    假设我们有一个向量 n,我们想要找到一个围绕中心 p1 的圆,其半径为 r,与 n 正交。这是一个带有代码的工作示例

    p1 = np.array([-21.03181359,   4.54876345,  19.26943601])
    n = np.array([-0.06592715,  0.00713031, -0.26809672])
    n = n / np.linalg.norm(n) # normalise n
    r = 0.5
    
    
    x = np.array([1,0,0]).astype(np.float64) # take a random vector of magnitude 1
    x -= x.dot(n) * n / np.linalg.norm(n)**2  # make it orthogonal to n
    x /= np.linalg.norm(x)  # normalize
    
    # find first point on circle (x1). 
    # currently it has magnitude of 1, so we multiply it by the r
    x1 = p1 + (x*r)
    
    # vector from lumen centre to first circle point
    p1x1 = x1 - p1
    
    def rotation_matrix(axis, theta):
        """
        Return the rotation matrix associated with counterclockwise rotation about
        the given axis by theta radians.
        """
        axis = np.asarray(axis)
        axis = axis / math.sqrt(np.dot(axis, axis))
        a = math.cos(theta / 2.0)
        b, c, d = -axis * math.sin(theta / 2.0)
        aa, bb, cc, dd = a * a, b * b, c * c, d * d
        bc, ad, ac, ab, bd, cd = b * c, a * d, a * c, a * b, b * d, c * d
        return np.array([[aa + bb - cc - dd, 2 * (bc + ad), 2 * (bd - ac)],
                         [2 * (bc - ad), aa + cc - bb - dd, 2 * (cd + ab)],
                         [2 * (bd + ac), 2 * (cd - ab), aa + dd - bb - cc]])
    
    
    # rotate the vector p1x1 around the axis n with angle theta
    circle = []
    for theta in range(0,360,6):
        circle_i = np.dot(rotation_matrix(n, np.deg2rad(theta)), p1x1)
        circle.append(circle_i+p1)
    
    ax = axes3d.Axes3D(plt.figure(figsize=(10,10)))
    ax.scatter3D(*np.array(circle).T, s=10, c='red')
    ax.scatter3D(*p1.T, s=10, c='black')
    ax.set_xlabel('X', size=40)
    ax.set_ylabel('Y', size=40)
    ax.set_zlabel('Z', size=40)
    
    ax.set_xlim(-19,-22)
    ax.set_ylim(2,5)
    ax.set_zlim(18,21)
    
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 2022-12-10
      • 2020-10-26
      • 2021-11-13
      • 1970-01-01
      相关资源
      最近更新 更多