Python,如何将 x;y 点列表定义的样条转换为 NURB 曲线

Python, how to convert spline defined by x;y list of point into NURB curve

是否可以将 (x;y) 坐标系转换为 NURBS 定义控制点和节点?

主要的想法是我正在尝试在 python 中开发一个用于空气风力发电机的建模工具,我想在数学上将叶片建模为 NURBS 表面, 但定义叶片横截面的曲线被归一化为 (x;y) 坐标文件。

现在我已将所有 (x;y) 点定义到 2D Numpy 数组中。

您可以为此使用 scipy.interpolate

import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import splev, splrep

x = np.linspace(0, 10, 10) # x-coordinates
y = np.sin(x) # y-coordinates
tck = splrep(x, y) # get bspline representation given (x,y) values
x2 = np.linspace(0, 10, 200) # new set of values, just to check
y2 = splev(x2, tck) # evaluate the y values of new coordinates on NURBS curve
plt.plot(x, y, 'o', x2, y2) 
plt.show()

元组 tck 包含结向量和控制点(系数)。 SciPy里面还有更多涉及的套路,看here.

请注意,这些仅适用于 bspline 曲线。据我所知,在 SciPy 中没有等效的曲面方法。如果你想使用表面,根据你的要求,你可以使用 igakit

from igakit.cad import ruled, circle
c1 = circle(angle=(0,np.pi/2.))
c2 = circle(radius=2,angle=(0,np.pi/2.))
print "knot vector:", c1.knots
print "control points:", c1.control
srf = ruled(c1,c2)
plt.plot(srf)
plt.show() 

knot vector: (array([ 0.,  0.,  0.,  1.,  1.,  1.]),)
control points: array([[  1.00000000e+00,   0.00000000e+00,   0.00000000e+00, 1.00000000e+00],
   [  7.07106781e-01,   7.07106781e-01,   0.00000000e+00, 7.07106781e-01],
   [  2.22044605e-16,   1.00000000e+00,   0.00000000e+00, 1.00000000e+00]])

NURBS package. For fancier stuff Blender and Salome have complete Python API for all family of NURBS curves/surfaces with the latter being based on OpenCascade.

您确定需要 NURBS 曲面吗?据我所知, 与 b 样条曲面相比,它们的主要优势在于它们可以精确地建模 圆弧。我从事机翼工作多年,弧形不是什么东西 对我特别有用。

无论如何,romeric 是正确的,他说表面没有类似于 scipy.interpolate.splprep 的东西。 但是如果你不反对自己动手,你可以创建一个 3D 数组 来自形状为 (3, m, n) 的截面数据,其中 'm' 是每个截面的点数,'n' 是 部分数,第一个维度包含 m x n 网格上的 x、y 和 z 值。 一旦你有了它,你可以使用 scipy.interpolate.RectBivariateSpline 来创建 3 个独立的 2D 参数曲面,用于 x、y 和 z 坐标。然后写 a class 将它们组合成 3D space 中的单个 2D 表面,这样当您调用 mysurf.ev(0.5, 0.2) 例如,它评估 3 RectBivariateSpline class 和 returns (x, y, z) 坐标中嵌入的实例。

我发布了一个 Gist here 可以帮助您入门。要尝试它,可以从命令行 运行,或者这样做:

from bsplinesurf import DemoBSplineSurf
srf = DemoBSplineSurf()
srf.plot()