Python中的参数化曲面创建

时间:2012-06-20 13:21:28

标签: python math scipy

是否有用于处理参数(u-v)曲面的Python模块?我正在寻找像scipy.interpolate的样条函数的3D模拟,我可以通过一组2D点创建参数样条:

xypts = [[0., 1., 5., 2.], [4., 3., 6., 7.]]
tck, u = scipy.interpolate.splprep(xypts, s=0, k=3)

然后在样条曲线上的任何t值处得到一个点,如下所示:

t = 0.5
intxypt = scipy.interpolate.splev(t, tck)

所以,我想要的是这样的东西:

# xyzpts is a 3 x m x n matrix, with m and n >= 4 for a cubic surface
tck, s, t = srfprep(xyzpts, s=0, k=3)
u, v = 0.5, 0.5
intxyzpt = srfev(u, v, tck)

我前段时间编写了我自己的代码,但坦率地说它有点糟糕(缓慢而脆弱,特别是在表面边缘)而且我正在寻找更标准和优化的东西。

1 个答案:

答案 0 :(得分:1)

这可能是显而易见的,但如果您能够猜测与每个数据点对应的uv坐标(最简单的情况u=xv=y如果曲面是图形),则参数插值{{1基本上是3个独立数据集(x,y和z坐标)的二维插值,因此您可以使用任何常用的二维插值方法。

(u,v) -> (x,y,z)实际上是这样工作的,假设点是有序的,并使用欧几里德距离根据splprep分配u坐标。如果您知道哪些点“彼此相邻”,则会推广到2-D。例如,如果u[i] = u[i-1] + dist(p[i], p[j])数据作为二维数组,则可以执行

x,y,z

编辑:好的,我不完全确定上面计算的from scipy import interpolate import numpy as np # example dataset (wavy cylinder) def surf(u, v): x = np.cos(v*np.pi*2) * (1 + 0.3*np.cos(30*u)) y = np.sin(v*np.pi*2) * (1 + 0.3*np.cos(30*u)) z = 2*u return x, y, z ux, vx = np.meshgrid(np.linspace(0, 1, 20), np.linspace(0, 1, 20)) x, y, z = surf(ux, vx) # reconstruct (u, v) using the existing (!) neighbourhood information du = np.sqrt(np.diff(x, axis=0)**2 + np.diff(y, axis=0)**2 + np.diff(z, axis=0)**2) dv = np.sqrt(np.diff(x, axis=1)**2 + np.diff(y, axis=1)**2 + np.diff(z, axis=1)**2) u = np.zeros_like(x) v = np.zeros_like(x) u[1:,:] = np.cumsum(du, axis=0) v[:,1:] = np.cumsum(dv, axis=1) u /= u.max(axis=0)[None,:] # hmm..., or maybe skip this scaling step -- may distort the result v /= v.max(axis=1)[:,None] # construct interpolant (unstructured grid) ip_surf = interpolate.CloughTocher2DInterpolator( (u.ravel(), v.ravel()), np.c_[x.ravel(), y.ravel(), z.ravel()]) # the BivariateSpline classes might also work here, but the above is more robust # plot projections import matplotlib.pyplot as plt u = np.random.rand(2000) v = np.random.rand(2000) plt.subplot(131) plt.plot(ip_surf(u, v)[:,0], ip_surf(u, v)[:,1], '.') plt.title('xy') plt.subplot(132) plt.plot(ip_surf(u, v)[:,1], ip_surf(u, v)[:,2], '.') plt.title('yz') plt.subplot(133) plt.plot(ip_surf(u, v)[:,2], ip_surf(u, v)[:,0], '.') plt.title('zx') plt.show() 在实践中有多强大,因为它似乎有失真的余地。但是,下面的LocallyLinearEmbedding在这方面可能会更好。

如果您 无法猜测u,v值,例如,您只有一堆积分且没有邻域信息,则问题变得更加困难。这里适当的关键词似乎是“表面重建”和“流形学习”。

我没有尝试,但在我看来,您可以使用scikits-learn see this example中的u,v轻松获得合适的u,v坐标。他们有许多不同的算法,这似乎足够坚固。然后,您可以在非结构化二维插值方法中使用生成的LocallyLinearEmbedding,如上所示。

也许谷歌搜索会发现更多的包裹。