微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

计算双变量样条曲线的B样条曲线基础

如何解决计算双变量样条曲线的B样条曲线基础

我需要在bivariate spline中的B-spline basis上计算uv查询With this answer我有一个很好的函数(在下面复制),可以利用scipy.dfitpack.bispeu获得我需要的结果。

import numpy as np
import scipy.interpolate as si

def fitpack_bispeu(cv,u,v,count_u,count_v,degree_u,degree_v):
    # cv = grid of control vertices
    # u,v = list of u,v component queries
    # count_u,count_v = grid counts along the u and v directions
    # degree_u,degree_v = curve degree along the u and v directions
    
    # Calculate knot vectors for both u and v
    tck_u = np.clip(np.arange(count_u+degree_u+1)-degree_u,count_u-degree_u) # knot vector in the u direction
    tck_v = np.clip(np.arange(count_v+degree_v+1)-degree_v,count_v-degree_v) # knot vector in the v direction

    # Compute queries
    positions = np.empty((u.shape[0],cv.shape[1]))
    for i in range(cv.shape[1]):
        positions[:,i] = si.dfitpack.bispeu(tck_u,tck_v,cv[:,i],degree_v,v)[0]

    return positions

函数有效,但是对我而言,我可以通过提前计算bivariate basis来获得更好的性能,然后通过点积获得我的结果。这是我为计算基础而写的。

def basis_bispeu(cv,degree_v):

    # Calculate knot vectors for both u and v
    tck_u = np.clip(np.arange(count_u+degree_u+1)-degree_u,count_v-degree_v) # knot vector in the v direction

    # Compute basis for each control vertex
    basis = np.empty((u.shape[0],cv.shape[0]))
    cv_   = np.identity(len(cv))
    
    for i in range(cv.shape[0]):
        basis[:,cv_[i],v)[0]


    return basis

让我们与cProfile进行比较和分析:

# A test grid of control vertices
cv = np.array([[-0.5,-0.,0.5       ],[-0.5,0.33333333],0.        ],0.,-0.33333333],-0.5       ],[-0.16666667,1.,0.5,[ 0.16666667,[ 0.5,-0.5,-0.5       ]])

count_u = 4
count_v = 5
degree_u = 3
degree_v = 3

n = 10**6 # make 1 million random queries
u = np.random.random(n) * (count_u-degree_u) 
v = np.random.random(n) * (count_v-degree_v) 

# get the result from fitpack_bispeu
result_bispeu = fitpack_bispeu(cv,degree_v) # 0.482 seconds

# precompute the basis for the same grid
basis = basis_bispeu(cv,degree_v) # 2.124 seconds

# get results via dot product
result_basis = np.dot(basis,cv) # 0.028 seconds (17x faster than fitpack_bispeu)

# all close?
print np.allclose(result_basis,result_bispeu) # True

速度提高了17倍,预计算基础似乎是路要走,但是basis_bispeu却很慢。

问题

有没有一种更快的方法来计算二元样条的基础?我知道deBoor's algorithm会在曲线上计算出相似的基础。对于bivariates是否有类似的算法,一旦用numbacython编写,就可以产生更好的性能

否则可以改进上面的basis_bispeu函数来更快地计算基数吗?也许我不知道内置的numpy函数会有所帮助。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。