1

好的,所以基本上我的问题是将思维框架从“在纸上”解决数学问题转变为通过编程来解决它们。让我解释一下:我想知道是否可以在为变量赋值之前对其执行操作。就像如果我有类似的东西,(1-x)**n我可以先分配 na 值,然后将其转换为特定程度的特定值,然后给出 xa 值或值。如果我不够清楚:如果 n=2,我可以先将方程转换为形式1-2x+x**2,然后在下一步处理 x 值吗?

我想编写一个用于计算和绘制 n 次贝塞尔曲线的代码。我为此使用伯恩斯坦多项式,所以我意识到方程由 3 部分组成:第一部分是多项式系数,它们都是帕斯卡三角形的一部分;我正在计算这些并将它们放在一个列表中。第二部分是控制点的坐标,也是某种系数,并将它们放在单独的列表中。现在是困难的部分:方程的一部分有一个变量。伯恩斯坦正在使用气压中心坐标(意思是 u 和 1-u)。这部分方程的第 N 度公式是:

u**i  *(1-u)**(n-i)

其中 n 是曲线度,我从 0->n 开始,U 是可变的。U 是实际标准化变量,这意味着它的值可以从 0 到 1,我想稍后在一定数量的步骤中迭代它(比如 1000) .但问题是,如果我尝试使用提到的方程,我会不断出错,因为 Python 不知道如何处理 u 我教过嵌套循环,其中第一个将 u 的值从 0 迭代到 1,第二个会处理提到从0到n的方程,但不确定它是否是正确的解决方案,也不知道如何检查结果。你怎么看?PS:我没有上传代码,因为我遇到问题的部分我什至无法开始,而且,我认为但可能是错误的,它与代码的其余部分是分开的;但如果你认为它可以帮助解决问题,我可以上传它。

4

2 回答 2

3

您可以使用高阶函数,即返回函数的函数,例如

def Bernstein(n,i):
    def f(t):
        return t**i*(1.0-t)**(n-i)
    return f

你可以这样使用

b52 = Bernstein(5,2)
val = b52(0.74)

但你宁愿使用列表

Bernstein_ni = [Bernstein(n,i) for i in range(n+1)]

用于高阶函数来构建贝塞尔曲线函数

def mk_bezier(Px,Py):
    "Input, lists of control points, output a function of t that returns (x,y)" 
    n = len(Px)
    binomials = {0:[1], 1:[1,1], 2:[1,2,1],
                 3:[1,3,3,1], 4:[1,4,6,4,1], 5:[1,5,10,10,5,1]}
    binomial = binomials[n-1]
    bPx = [b*x for b,x in zip(binomial,Px)]
    bPy = [b*y for b,y in zip(binomial,Py)]
    bns = [Bernstein(n-1,i) for i in range(n)]
    def f(t):
        x = 0 ; y = 0
        for i in range(n):
            berns = bns[i](t)
            x = x + bPx[i]*berns
            y = y + bPy[i]*berns
        return x, y
    return f

最终,在您的程序中,您可以像这样使用函数工厂

linear = mk_bezier([0.0,1.0],[1.0,0.0])
quadra = mk_bezier([0.0,1.0,2.0],[1.0,3.0,1.0])

for t in (0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0):
    l = linear(t) ;  q = quadra(t)
    print "%3.1f     (%6.4f,%6.4f)    (%6.4f,%6.4f)" % (t,  l[0],l[1],  q[0],q[1])

这是测试输出

0.0     (0.0000,1.0000)    (0.0000,1.0000)
0.1     (0.1000,0.9000)    (0.2000,1.3600)
0.2     (0.2000,0.8000)    (0.4000,1.6400)
0.3     (0.3000,0.7000)    (0.6000,1.8400)
0.4     (0.4000,0.6000)    (0.8000,1.9600)
0.5     (0.5000,0.5000)    (1.0000,2.0000)
0.6     (0.6000,0.4000)    (1.2000,1.9600)
0.7     (0.7000,0.3000)    (1.4000,1.8400)
0.8     (0.8000,0.2000)    (1.6000,1.6400)
0.9     (0.9000,0.1000)    (1.8000,1.3600)
1.0     (1.0000,0.0000)    (2.0000,1.0000)

编辑

我认为正确的方法是在模块级别,使用顶级排序 -defaultdictionary记住执行实际计算所需的所有不同列表,但不会defaultdict变量传递给它default_factory,我不会为了这个答案,感觉像子类dict化(不是现在),主要原因是我以前从未子类化......

回应OP评论

你说功能度是主要参数?但它是由控制点列表的长度隐含定义的......

N   = user_input()
P0x = user_input()
P0y = user_input()
PNx = user_input()
PNy = user_input()
# code that computes P1, ..., PNminus1
orderN = mk_bezier([P0x,P1x,...,PNminus1x,PNx],
                   [P0y,P1y,...,PNminus1y,PNy])

x077, y077 = orderN(0.77)

但是客户永远是对的,所以如果你说我的解决方案与你的期望不同,我永远不会再试图说服你我的解决方案对你有用。

于 2014-11-12T23:57:20.303 回答
1

有用于执行符号数学的 Python 包,但使用Numpy 中可用的一些多项式函数可能更容易。这些函数使用多项式表示为系数数组的约定,从最低阶系数开始。所以多项式a*x^2 + b*x + c将表示为array([c, b, a])

一些例子:

In [49]: import numpy.polynomial.polynomial as poly

In [50]: p = [-1, 1]  # -x + 1

In [51]: p = poly.polypow(p, 2)

In [52]: p # should be 1 - 2x + x^2
Out[52]: array([ 1., -2.,  1.])

In [53]: x = np.arange(10)

In [54]: poly.polyval(x, p)  # evaluate polynomial at points x
Out[54]: array([  1.,   0.,   1.,   4.,   9.,  16.,  25.,  36.,  49.,  64.])

你可以用与此类似的方式计算你的伯恩斯坦多项式(仍然缺少二项式系数):

In [55]: def Bernstein(n, i):
    ...:     part1 = poly.polypow([0, 1], i)  # (0 + u)**i
    ...:     part2 = poly.polypow([1, -1], n - i)  # (1 - u)**(n - i)
    ...:     return poly.polymul(part1, part2)

In [56]: p = Bernstein(3, 2)

In [57]: p
Out[57]: array([ 0.,  0.,  1., -1.])

In [58]: poly.polyval(x, p)  # evaluate polynomial at points x
Out[58]: array([   0.,    0.,   -4.,  -18.,  ..., -448., -648.])
于 2014-11-12T22:37:24.357 回答