Python:如何在两个3D点之间绘制曲线?

4

我希望能够在3D空间中任意两点之间绘制曲线。这条曲线必须是"垂直的"。也就是说,曲线上的x和y坐标必须在同一条直线上,但z值必须像你向地面发射抛物体,它在空中飞行并再次撞击地面一样变化。它不需要物理上的正确性,一个弧也可以。

以下是起始代码:

import numpy as np

p1=np.array([1,1,1]) #x,y,z coordinates of the first point
p2=np.array([3,3,3]) #x,y,z coordinates of the second point

xi=np.linspace(p1[0],p2[0],100) #determine 100 x coordinates between two points
yi=np.linspace(p1[1],p2[1],100) #determine 100 y coordinates between two points
zi= ??                          #determine 100 z coordinates between two points. 

我怎样能够确定这些100个z坐标(zi)呢?

确定了zi之后,就很容易使用mayavi或mplot3d在连续的点之间绘制线条,从而给出曲线的视觉效果。


拿一支笔和纸,用两个维度画出你的问题。要将三维映射到二维,只需使用勾股定理来计算两个相邻边的斜边长度即可。 - Ulrich Eckhardt
2个回答

3
我最终使用了 scipy.interpolate 来获取曲线,并将其添加到点之间的直线的 z 坐标上。正如其他人所说,有多种方法可以做到这一点。这对我的目的足够了。
### objective: draw an arc between points p1 and p2. z coordinates are raised.

import numpy as np
from scipy import interpolate
from mayavi import mlab

###inputs
p1=np.random.uniform(0,20,(3)) #first point
p2=np.random.uniform(0,20,(3)) #second point
npts = 100 # number of points to sample
y=np.array([0,.5,.75,.75,.5,0]) #describe your shape in 1d like this
amp=5 #curve height factor. bigger means heigher 

#get the adder. This will be used to raise the z coords
x=np.arange(y.size)
xnew = np.linspace(x[0],x[-1] , npts) #sample the x coord
tck = interpolate.splrep(x,y,s=0) 
adder = interpolate.splev(xnew,tck,der=0)*amp
adder[0]=adder[-1]=0
adder=adder.reshape((-1,1))

#get a line between points
shape3=np.vstack([np.linspace(p1[dim],p2[dim],npts) for dim in xrange(3)]).T

#raise the z coordinate
shape3[:,-1]=shape3[:,-1]+adder[:,-1]

#plot
x,y,z=(shape3[:,dim] for dim in xrange(3))
mlab.points3d(x,y,z,color=(0,0,0))
mlab.plot3d(x,y,z,tube_radius=1)
mlab.outline()
mlab.axes()
mlab.show()

0

这个问题没有一个正确的答案,因为弧线的曲率没有受到限制。解决这个问题的数学基础是抛体运动,它给出了两个关键方程:

x_2 - x_1 = v_1 cos theta dt
z_2 - z_1 = -1/2 g dt^2 + v_0 sin theta dt

其中v_1是抛射物的初始速度,theta是抛射物从水平方向发射的角度,dt是抛射物从点1到点2所需的时间,g是重力常数。为了简单起见,现在忽略y。你面临的问题是这给出了两个方程,但你有三个未知数,v_1、theta和dt。

你可以添加一个约束条件,例如,p1和p2中较高的那个是轨迹的顶点。如果p2更高,例如,

v_2 = v_1 - g dt = 0

解决这三个方程可以得到v_1,从而可以得到随时间变化的z坐标:
z = -1/2 g t^2 + v_1 t + z_1

t = np.linspace(0, dt, 100)会给你一个numpy时间向量,你可以将其插入到你的z公式中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接