【问题标题】:python: how to draw a curve between two 3d points?python:如何在两个 3d 点之间绘制曲线?
【发布时间】:2013-05-13 15:31:23
【问题描述】:

我想在 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)很简单,可以看到曲线。

【问题讨论】:

  • 拿一支笔和一张纸,用两个维度画出你的问题。要从 3D 映射到 2D,您只需使用毕达哥拉斯的公式即可从两个相邻边获取斜边的长度。

标签: python curve


【解决方案1】:

我最终使用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()

【讨论】:

    【解决方案2】:

    这个问题没有一个正确的答案,因为弧的曲率不受限制。这个问题的数学基础是projectile motion,它给出了两个关键方程:

    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 公式。

    【讨论】:

      猜你喜欢
      • 2017-02-18
      • 1970-01-01
      • 1970-01-01
      • 2013-12-19
      • 2023-04-03
      • 2022-08-22
      • 1970-01-01
      • 1970-01-01
      • 2020-06-04
      相关资源
      最近更新 更多