所以我在玩一些Bezier曲线的动画--只是学习如何使用ipy画布(0,10,2)的一部分--我制作的动画真的让我头疼。我希望看到的是在4个Bezier控制点之间的一组直线,随着Bezier曲线的移动,它们在画布上“弹跳”。
我确实得到了移动的Bezier曲线--但是控制点保持不变。更奇怪的是,他们在最后的位置上是静止的,而曲线则是为了与他们相遇。
有时候Python的结构和引用会变得有点棘手,所以如果你没有认真考虑的话,你有时会得到令人困惑的结果--这完全可能是正在发生的事情--但我很困惑。
因此,为了确保我没有感到困惑,我在开始时打印了控制点( at ),然后将它们显示在画布上。这证实了我的怀疑。通过量子隧穿或其他神奇的时间旅行,线canvas.stroke_lines(pts)到达未来,抓住pts阵列,因为它将存在于未来,并使控制点处于最终状态。
pts的其他每一种使用都使用当前的时态。
所以我需要知道的是,A)物理定律是安全的,我太笨了,无法理解我自己的代码。有一些奇怪的错误,我应该报告。( C)如何将这种时间旅行代码货币化--比如,我们能用它来计算大量的数字吗?
from ipycanvas import Canvas, hold_canvas
import numpy as np
def rgb_to_hex(rgb):
if len(rgb) == 3:
return '#%02x%02x%02x' % rgb
elif len(rgb) == 4:
return '#%02x%02x%02x%02x' % rgb
def Bezier4(t, pts):
p = t**np.arange(0, 4,1)
M=np.matrix([[0,0,0,1],[0,0,3,-3],[0,3,-6,3],[1,-3,3,-1]])
return np.asarray((p*M*pts))
canvas = Canvas(width=800, height=800)
display(canvas) # display the canvas in the output cell..
pts = np.random.randint(50, 750, size=[4, 2]) #choose random starting point
print(pts) #print so we can compare with ending state
d = np.random.uniform(-4,4,size=[4,2]) #some random velocity vectors
c = rgb_to_hex(tuple(np.random.randint(75, 255,size=3))) #some random color
canvas.font = '16px serif' #font for displaying the changing pts array
with hold_canvas(canvas):
for ani in range(300):
#logic to bounce the points about...
for n in range(0,len(pts)):
pts[n]=pts[n] + d[n]
if pts[n][0] >= 800 or pts[n][0] <= 0 :
d[n][0] = - d[n][0]
if pts[n][1] >= 800 or pts[n][1] <= 0 :
d[n][1] = - d[n][1]
#calculate the points needed to display a bezier curve
B = [(Bezier4(i, pts)).ravel() for i in np.linspace(0,1,15)]
#begin display output....
canvas.clear()
#first draw bezier curve...
canvas.stroke_style = c
canvas.stroke_lines(B)
#Now draw control points
canvas.stroke_style = rgb_to_hex((255,255,128, 50))
canvas.stroke_lines(pts)
#print the control points to the canvas so we can see them move
canvas.stroke_style = rgb_to_hex((255,255,128, 150))
canvas.stroke_text(str(pts), 10, 32)
canvas.sleep(20)认真地说,我已经试着想清楚到底会发生什么事,现在我正处于空白状态。由于ipy画布正在与browser/javascript对话,所以可能首先呈现框架的所有数据,用于保存stroke_lines的stroke_lines数据的数组最终得到最后的值.而B数组是在每个循环中重新创建的。只是猜测而已。
发布于 2022-01-09 07:47:02
有两种方法可以让代码像预期的那样运行,并避免那些难看的时间旅行代码。第一种方法是将行with hold_canvas(canvas):的位置切换到循环内。然而,这使得canvas.sleep(20)行变得相当无用。
canvas = Canvas(width=800, height=800)
display(canvas)
pts = np.random.randint(50, 750, size=[4, 2])
print(pts)
d = np.random.uniform(-8,8,size=[4,2])
c = rgb_to_hex(tuple(np.random.randint(75, 255,size=3)))
canvas.font = '16px serif'
#with hold_canvas(canvas):
for ani in range(300):
with hold_canvas(canvas):
for n in range(0,len(pts)):
if pts[n][0] > 800 or pts[n][0] < 0 :
d[n][0] = -d[n][0]
if pts[n][1] > 800 or pts[n][1] < 50 :
d[n][1] = -d[n][1]
pts[n]=pts[n] + d[n]
B = [(Bezier4(i, pts)).ravel() for i in np.linspace(0,1,25)]
canvas.clear()
canvas.stroke_style = c
canvas.stroke_lines(B)
canvas.stroke_style = rgb_to_hex((255,255,128, 50))
#pts2 = np.copy(pts)
canvas.stroke_lines(pts)
canvas.fill_style = rgb_to_hex((255,255,255, 150))
canvas.fill_circles(pts.T[0], pts.T[1],np.array([4]*4))
canvas.stroke_style = rgb_to_hex((255,255,128, 150))
canvas.fill_text(str(pts), 10, 32)
sleep(20/1000)
#canvas.sleep(20)在此版本中,控制线将按预期更新。这个版本有点“实时”,因此需要sleep(20/1000)
另一种方法是确保pts的副本被制作并传递给canvas.stroke_lines。
canvas = Canvas(width=800, height=800)
display(canvas)
pts = np.random.randint(50, 750, size=[4, 2])
print(pts)
d = np.random.uniform(-8,8,size=[4,2])
c = rgb_to_hex(tuple(np.random.randint(75, 255,size=3)))
canvas.font = '16px serif'
with hold_canvas(canvas):
for ani in range(300):
#with hold_canvas(canvas):
for n in range(0,len(pts)):
if pts[n][0] > 800 or pts[n][0] < 0:
d[n][0] = -d[n][0]
if pts[n][1] > 800 or pts[n][1] < 50:
d[n][1] = -d[n][1]
pts[n]=pts[n] + d[n]
B = [(Bezier4(i, pts)).ravel() for i in np.linspace(0,1,35)]
canvas.clear()
canvas.stroke_style = c
canvas.stroke_lines(B)
canvas.stroke_style = rgb_to_hex((255,255,128, 50))
pts2 = np.copy(pts)
canvas.stroke_lines(pts2)
canvas.fill_style = rgb_to_hex((255,255,255, 150))
canvas.fill_circles(pts.T[0], pts.T[1],np.array([4]*4))
canvas.stroke_style = rgb_to_hex((255,255,128, 150))
canvas.fill_text(str(pts), 10, 32)
#sleep(20/1000)
canvas.sleep(20)我实际上找不到在python和浏览器之间传递的数据,但似乎非常符合逻辑的是,python在发送要绘制什么的小部件说明之前正在完成它的工作(和ani循环),并且发送的pts值是最后的值。
(是的,我知道弹跳逻辑中有一个错误)
https://stackoverflow.com/questions/70638846
复制相似问题