用两个物体做螺旋

Ele*_*reg 6 python numpy python-3.x

我有一个平面和一条正弦曲线。请问如何旋转这两个对象?我的意思是让平面在 -0.1 到 0.4 的区间内缓慢倾斜,以便例如在 0.4 点垂直于 z?经过较长时间的旋转,平面和正弦的最大值和最小值将构建“圆柱的表面,轴从点[0,-0.1,0]到点[0,0.4,0]”。我希望我的意思很清楚。

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D                         
from mpl_toolkits.mplot3d import proj3d                         
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

plane1 = -0.1
plane2 = 0.4
h = 0.03

# Plane
xp = np.array([[0, 0], [0, 0]])
yp = np.array([[plane1, plane2], [plane1, plane2]])
zp = np.array([[-h, -h], [h, h]])

ax.plot_surface(xp, yp, zp, alpha=0.4, color = 'red')

# Sine
f = 100
amp = h
y = np.linspace(plane1, plane2, 5000)
z = amp*np.sin(y*f)
ax.plot(y, z, zdir='x')

plt.show()
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

所需的结果是由以下形状的正弦曲线填充的平面: 在此处输入图片说明 但没有那么旋转,整个间隔 30° 就足够了。

Mul*_*ter 2

要回答标题问题,要创建螺旋,您需要寻找一个简单的 3D 函数

amp, f = 1, 1
low, high = 0, math.pi*20
n = 1000

y = np.linspace(low, high, n)
x = amp*np.cos(f*y)
z = amp*np.sin(f*y)

ax.plot(x,y,z)
Run Code Online (Sandbox Code Playgroud)

这给出:

一个螺旋

自己找到这一点的一种方法是思考:从各个方向看它是什么样子?在 y/z 平面上制作 2D 图,您会看到 cos 图,在 y/x 平面上制作 2D 图,您会看到 sin 图。在 x/z 平面上的二维图形中,您会看到一个圆圈。这将告诉您有关 3D 功能的一切!


如果您确实想在 3D 空间中旋转正弦波的图像,事情就会变得复杂。此外,它不会像您期望的那样创建螺旋,因为您尝试创建的“圆柱体”的半径会随着 y 值的变化而变化。但是,既然你问如何进行旋转......

您将需要使用仿射变换矩阵。单次旋转可以表示为 4x4 矩阵,将其矩阵乘以齐次坐标即可找到结果点。(有关插图,请参阅链接)

rotate_about_y = np.array([
    [cos(theta), 0, sin(theta), 0],
    [0, 1, , 0],
    [-sin(theta), 0, cos(theta), 0],
    [0, 0, 0, 1],
])
Run Code Online (Sandbox Code Playgroud)

然后,要将其应用于整个点列表,您可以执行以下操作:

# Just using a mathematical function to generate the points for illustation
low, high = 0, math.pi*16
n = 1000

y = np.linspace(low, high, n)
x = np.zeros_like(y)
z = np.cos(y)
xyz = np.stack([x, y, z], axis=1) # shaped [n, 3]


min_rotation, max_rotation = 0, math.pi*16
homogeneous_points = np.concatenate([xyz, np.full([n, 1], 1)], axis=1) # shaped [n, 4]
rotation_angles = np.linspace(min_rotation, max_rotation, n)
rotate_about_y = np.zeros([n, 4, 4])
rotate_about_y[:, 0, 0] = np.cos(rotation_angles)
rotate_about_y[:, 0, 2] = np.sin(rotation_angles)
rotate_about_y[:, 1, 1] = 1
rotate_about_y[:, 2, 0] = -np.sin(rotation_angles)
rotate_about_y[:, 2, 2] = np.cos(rotation_angles)
rotate_about_y[:, 3, 3] = 1

# This broadcasts matrix multiplication over the whole homogeneous_points array
rotated_points = (homogeneous_points[:, None] @ rotate_about_y).squeeze(1)
# Remove tacked on 1
new_points = rotated_points[:, :3]

ax.plot(x, y, z)
ax.plot(new_points[:, 0], new_points[:, 1], new_points[:, 2])
Run Code Online (Sandbox Code Playgroud)

对于这种情况(其中low == min_rotationhigh == max_rotation),您会得到一个类似螺旋的结构,但是,正如我所说,它因我们绕 y 轴旋转而扭曲,并且函数转到 y=0。

旋转点

注意:@numpy中的符号表示“矩阵乘法”。“同质点”就是末尾加1的点;我不会解释他们为什么能做到这一点,但他们确实做到了。

注意#2:上面的代码假设您想要绕 y 轴旋转(即绕线 x=0, z=0)。如果你想围绕不同的线旋转,你需要进行变换。这里就不做过多赘述了,但是流程大致是这样的:

  1. 变换点,使要旋转的线映射到 y 轴
  2. 执行上述变换
  3. 执行此列表中第一个变换的逆操作

您可以通过将每个变换相互矩阵相乘来组合它们。

这是我找到的一份文档,解释了仿射变换矩阵如何以及为何工作。但是,有很多关于该主题的信息。