You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

已知次数、控制点、节点、权重时如何在SciPy中定义BSpline

实现方法

你需要复现的带权重参数的STEP样条是有理B样条(NURBS),不需要复杂计算推导样条系数,按STEP存储规则补全参数后,通过齐次坐标转换即可直接适配SciPy的BSpline类,步骤如下:

  • 补全符合SciPy要求的节点向量
    SciPy的BSpline要求节点向量长度满足len(knots) = 控制点数量 + 次数 + 1。STEP标准存储B_SPLINE_CURVE_WITH_KNOTS时默认保存去重后的节点值,常规开式(clamped)B样条首尾节点重数为次数+1,中间节点默认重数为1,按这个规则重复节点即可得到合法的节点向量。
  • 计算BSpline所需的样条系数
    对有理B样条,样条系数就是齐次化后的控制点:对每个三维控制点(x,y,z)及其对应的权重w,齐次控制点为(w*x, w*y, w*z, w)。如果是非有理B样条(所有权重为1),直接用原始控制点作为样条系数即可。
  • 求值时做齐次投影
    用补全的节点向量、齐次控制点、次数实例化四维BSpline对象,求值得到的四维结果(X,Y,Z,W),除以最后一维权重W,得到的(X/W, Y/W, Z/W)就是三维空间中对应的样条点坐标。
示例代码(适配给出的测试数据)
import numpy as np
from scipy.interpolate import BSpline

# 已知输入参数
degree = 3
knots_stored = [0.0, 0.25, 0.5, 0.75, 1.0]
ctrl_points = np.array([
    [0.0, 37.5, -18.0],
    [0.0, 37.5, -18.11781],
    [0.0, 37.54686, -18.35337],
    [0.0, 37.74703,-18.65297],
    [0.0, 38.04663, -18.85314],
    [0.0, 38.28219, -18.9],
    [0.0, 38.4, -18.9]
])
# 注:给出的示例权重长度为5,和7个控制点不匹配,实际解析时权重长度需和控制点数量一致
# 这里按首尾权重为4.0补全做演示
weights = np.array([4.0, 4.0, 1.0, 1.0, 1.0, 4.0, 4.0])

# 1. 补全节点向量(开式样条首尾重数为degree+1=4)
knots = np.array(
    [knots_stored[0]] * degree
    + knots_stored
    + [knots_stored[-1]] * degree
)

# 2. 计算齐次控制点作为BSpline的样条系数
homogeneous_coeffs = np.concatenate(
    [ctrl_points * weights[:, np.newaxis], weights[:, np.newaxis]],
    axis=1
)

# 3. 实例化BSpline对象
nurbs_spline = BSpline(knots, homogeneous_coeffs, degree, extrapolate=False)

# 求值示例:取参数u=0.5位置的样条点
u = 0.5
h_pt = nurbs_spline(u)
curve_point = h_pt[:3] / h_pt[3]
print(f"u=0.5处的样条点坐标:{curve_point}")
注意事项
  • 如果STEP文件中给出了每个节点的明确重数,不需要默认按首尾degree+1补全,直接按给出的重数重复对应节点即可,非开式周期样条不适用首尾补全的规则。
  • 非有理B样条不需要做齐次坐标转换,补全节点向量后直接传入原始控制点作为样条系数即可。

内容的提问来源于stack exchange,提问作者Oki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 08:24:11