更新控制点时,这是NurbPython中的错误吗?

2024-04-24 10:50:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用了NURBS-python并发现了一个有趣的问题,我不确定这样做是有意的还是仅仅是一个bug。我想用两个代码来介绍这个。你知道吗

第一个输出应该与第二个相同,而不是。第一个成功地更新了NURBS曲线的控制点并绘制了一条新的曲线

更改控制点列表的方式会影响结果。你知道吗

import math
from geomdl import BSpline
from geomdl import NURBS
from geomdl import fitting
from geomdl import convert
from geomdl.visualization import VisMPL

P1=[[0, 0], [0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [0, 0]]
Degree=3
CPN=5

P2=[[0, 0], [0, 1], [2, 1], [2, 0], [2, -1], [0, -1], [0, 0]]
CP=[[0, 0], [1, 2], [2, 0], [1, -2], [0, 0]]

c1=NURBS.Curve()
c1.degree=Degree
c1.ctrlpts=P1
c1.weights=[1, 1, 1, 1, 1, 1, 1]
c1.knotvector=[0, 0, 0, 0, 0.25, 0.5, 0.75, 1, 1, 1, 1]

c1.vis=VisMPL.VisCurve2D()
c1.render()

c1.ctrlpts=P2
c1.vis=VisMPL.VisCurve2D()
c1.render()


c2=convert.bspline_to_nurbs(fitting.approximate_curve(P1, Degree, ctrlpts_size=CPN))

c2.vis=VisMPL.VisCurve2D()
c2.render()

c2.ctrlpts=CP

c2.vis=VisMPL.VisCurve2D()
c2.render()

而第二个简单地更新控制点,曲线本身没有任何变化。你知道吗

import math
from geomdl import BSpline
from geomdl import NURBS
from geomdl import fitting
from geomdl import convert
from geomdl.visualization import VisMPL

P1=[[0, 0], [0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [0, 0]]
Degree=3
CPN=5

P2=[[0, 0], [0, 1], [2, 1], [2, 0], [2, -1], [0, -1], [0, 0]]
CP=[[0, 0], [1, 2], [2, 0], [1, -2], [0, 0]]

c1=NURBS.Curve()
c1.degree=Degree
c1.ctrlpts=P1
c1.weights=[1, 1, 1, 1, 1, 1, 1]
c1.knotvector=[0, 0, 0, 0, 0.25, 0.5, 0.75, 1, 1, 1, 1]

c1.vis=VisMPL.VisCurve2D()
c1.render()


for i in range(len(P2)):
    c1.ctrlpts[i]=P2[i]
c1.vis=VisMPL.VisCurve2D()
c1.render()

c2=convert.bspline_to_nurbs(fitting.approximate_curve(P1, Degree, ctrlpts_size=CPN))

c2.vis=VisMPL.VisCurve2D()
c2.render()

for i in range(len(CP)):
    c2.ctrlpts[i]=CP[i]

c2.vis=VisMPL.VisCurve2D()
c2.render()

请帮忙,谢谢。你知道吗


Tags: fromimportrendercpvisp2c2c1
1条回答
网友
1楼 · 发布于 2024-04-24 10:50:45

Curve.ctrlptsproperty。当您访问getter时,它将返回控制点列表。访问setter需要做更多的工作,主要是一致性检查和必要的清理。你知道吗

调用cpts = c1.ctrlpts时,调用属性的__get__方法,将返回存储Curve实例内控制点的列表对象的引用,并将其分配给cpts变量:

>>> cpts = c1.ctrlpts
>>> type(cpts)
<class 'list'>

当您在列表cpts中循环时,实际上是在Curve类实例中循环它的引用。因为您直接与list对象交互,所以不能访问ctrlptssetter,它实际上通过调用Curve.reset()方法来进行清理。你知道吗

不幸的是,不可能重写内置类(在API级别上定义的类)的方法。你知道吗

>>> list.__getitem__ = my_getter_method
TypeError: can't set attributes of built-in/extension type 'list'

结果,当底层list对象更改时触发Curve.reset()方法变得有点复杂(但并非不可能)。你知道吗

设置控制点的最佳和最安全的方法是使用属性的setter方法:

my_ctrlpts = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
c1.ctrlpts = my_ctrlpts

如果要使用for循环,则需要手动调用reset方法:

for i in range(len(P2)):
    c1.ctrlpts[i]=P2[i]
c1.reset(evalpts=True)

注:我是NURBS Python(geomdl)的作者

相关问题 更多 >