如何在 Racket 中的函数图上为点设置动画?
How to animate points over a function plot in Racket?
我正在为遗传算法制作 GUI 可视化,并希望能够绘制最大化函数和每一代个体在该函数上的点。对于每一代,我只希望删除点,然后在已经存在的函数图上绘制下一个点。
使用函数 plot/dc
,我实现了为每一代个体制作动画,绘制坐标列表中的所有点。但是此方法每次运行时都会重新绘制 canvas 。所以我无法在点后面绘制函数本身。我可以列出每一代的功能和点数,但这会浪费资源。
使用这段代码你应该可以模拟我的实际开发状态。
#lang racket
(require racket/gui plot)
(define main-window (new frame% [label "FUNCTION AND POINTS"] [width 200] [height 600]))
(define canvas-panel (new panel% [parent main-window]))
(define function-canvas (new canvas% [parent canvas-panel]))
(define (plot-points list-of-points)
(for-each
(λ (population)
(plot/dc (points population
#:x-min 0
#:x-max 3
#:y-min 0
#:y-max 9
#:color 'red)
(send function-canvas get-dc)
0 0
(- (send canvas-panel get-width) 40)
(- (send canvas-panel get-height) 40))
(sleep/yield 1))
list-of-points))
(send main-window show #t)
(plot-points '(((1 8) (2 5) (2.5 2))
((2 5) (1.5 6.5) (2 3))
((1.5 3) (2 2) (1.5 3.5))
((2 7) (0.5 1) (2 0.5))
((0.5 9) (0 5) (0.5 0))
((0 1) (1 4.5) (0 8.5))))
注意:以上点是随机生成的,与遗传算法输出不对应,所以没有函数可以匹配这个坐标。
我希望绘制这些点后面的函数图,以便能够看到最大化的发生。
这里有很多问题。但基本上你想把你的图放在非全白背景上,这样你就可以在背景中放置其他东西(在本例中是函数图)。您可以使用 background-alpha
参数执行此操作。
将这一行添加到上面的代码中:
(plot-background-alpha 0)
将让点不断地建立在彼此之上。由于您指出要移动点,因此您还需要在每个 'frame' 之间清除屏幕,您可以通过将绘制函数更改为:
来完成此操作
(define (plot-points list-of-points)
(for-each
(λ (population)
(define dc (send function-canvas get-dc))
(send dc clear)
(plot/dc .... elided ....
dc
0 0
(- (send canvas-panel get-width) 40)
(- (send canvas-panel get-height) 40))
(sleep/yield 1))
list-of-points))
现在画出你的真实背景。您可以在每一帧重新计算它,但正如您指出的那样太慢了。1 所以我们可以计算一次,将其渲染为图像,然后重新绘制每个 'frame' .假设你想要的后台函数是 (+ (sin (* 5 x)) 3),你的代码看起来像:
(define plot-func (function (λ (x) (+ (sin (* 5 x)) 3))
0 (* 2 pi)))
(define plot-background
(plot-bitmap plot-func
#:x-min 0
#:x-max 3
#:y-min 0
#:y-max 9
#:width (- (send canvas-panel get-width) 40)
#:height (- (send canvas-panel get-height) 40)))
请注意,get-width
和 get-height
不会存储实际的 canvas 的 width/height,直到 show
方法被调用。
现在我们需要更新绘制函数以将此图绘制到背景中:
(define (plot-points list-of-points)
(for-each
(λ (population)
(define dc (send function-canvas get-dc))
(send dc clear)
(send dc draw-bitmap plot-background 0 0)
... elided ...
(sleep/yield 1))
list-of-points))
将它们放在一起得出:
#lang racket
(require racket/gui plot)
(define main-window (new frame% [label "FUNCTION AND POINTS"] [width 200] [height 600]))
(define canvas-panel (new panel% [parent main-window]))
(define function-canvas (new canvas% [parent canvas-panel]))
(send main-window show #t)
(plot-background-alpha 0)
(define plot-func (function (λ (x) (+ (sin (* 5 x)) 3))
0 (* 2 pi)))
(define plot-background
(plot-bitmap plot-func
#:x-min 0
#:x-max 3
#:y-min 0
#:y-max 9
#:width (- (send canvas-panel get-width) 40)
#:height (- (send canvas-panel get-height) 40)))
(define (plot-points list-of-points)
(for-each
(λ (population)
(define dc (send function-canvas get-dc))
(send dc clear)
(send dc draw-bitmap plot-background 0 0)
(plot/dc (points population
#:x-min 0
#:x-max 3
#:y-min 0
#:y-max 9
#:color 'red)
dc
0 0
(- (send canvas-panel get-width) 40)
(- (send canvas-panel get-height) 40))
(sleep/yield 1))
list-of-points))
(plot-points '(((1 8) (2 5) (2.5 2))
((2 5) (1.5 6.5) (2 3))
((1.5 3) (2 2) (1.5 3.5))
((2 7) (0.5 1) (2 0.5))
((0.5 9) (0 5) (0.5 0))
((0 1) (1 4.5) (0 8.5))))
1显然这取决于您正在计算的细节以及您想要绘制它的速度。它实际上可能足够快。 ;)
我正在为遗传算法制作 GUI 可视化,并希望能够绘制最大化函数和每一代个体在该函数上的点。对于每一代,我只希望删除点,然后在已经存在的函数图上绘制下一个点。
使用函数 plot/dc
,我实现了为每一代个体制作动画,绘制坐标列表中的所有点。但是此方法每次运行时都会重新绘制 canvas 。所以我无法在点后面绘制函数本身。我可以列出每一代的功能和点数,但这会浪费资源。
使用这段代码你应该可以模拟我的实际开发状态。
#lang racket
(require racket/gui plot)
(define main-window (new frame% [label "FUNCTION AND POINTS"] [width 200] [height 600]))
(define canvas-panel (new panel% [parent main-window]))
(define function-canvas (new canvas% [parent canvas-panel]))
(define (plot-points list-of-points)
(for-each
(λ (population)
(plot/dc (points population
#:x-min 0
#:x-max 3
#:y-min 0
#:y-max 9
#:color 'red)
(send function-canvas get-dc)
0 0
(- (send canvas-panel get-width) 40)
(- (send canvas-panel get-height) 40))
(sleep/yield 1))
list-of-points))
(send main-window show #t)
(plot-points '(((1 8) (2 5) (2.5 2))
((2 5) (1.5 6.5) (2 3))
((1.5 3) (2 2) (1.5 3.5))
((2 7) (0.5 1) (2 0.5))
((0.5 9) (0 5) (0.5 0))
((0 1) (1 4.5) (0 8.5))))
注意:以上点是随机生成的,与遗传算法输出不对应,所以没有函数可以匹配这个坐标。
我希望绘制这些点后面的函数图,以便能够看到最大化的发生。
这里有很多问题。但基本上你想把你的图放在非全白背景上,这样你就可以在背景中放置其他东西(在本例中是函数图)。您可以使用 background-alpha
参数执行此操作。
将这一行添加到上面的代码中:
(plot-background-alpha 0)
将让点不断地建立在彼此之上。由于您指出要移动点,因此您还需要在每个 'frame' 之间清除屏幕,您可以通过将绘制函数更改为:
来完成此操作(define (plot-points list-of-points)
(for-each
(λ (population)
(define dc (send function-canvas get-dc))
(send dc clear)
(plot/dc .... elided ....
dc
0 0
(- (send canvas-panel get-width) 40)
(- (send canvas-panel get-height) 40))
(sleep/yield 1))
list-of-points))
现在画出你的真实背景。您可以在每一帧重新计算它,但正如您指出的那样太慢了。1 所以我们可以计算一次,将其渲染为图像,然后重新绘制每个 'frame' .假设你想要的后台函数是 (+ (sin (* 5 x)) 3),你的代码看起来像:
(define plot-func (function (λ (x) (+ (sin (* 5 x)) 3))
0 (* 2 pi)))
(define plot-background
(plot-bitmap plot-func
#:x-min 0
#:x-max 3
#:y-min 0
#:y-max 9
#:width (- (send canvas-panel get-width) 40)
#:height (- (send canvas-panel get-height) 40)))
请注意,get-width
和 get-height
不会存储实际的 canvas 的 width/height,直到 show
方法被调用。
现在我们需要更新绘制函数以将此图绘制到背景中:
(define (plot-points list-of-points)
(for-each
(λ (population)
(define dc (send function-canvas get-dc))
(send dc clear)
(send dc draw-bitmap plot-background 0 0)
... elided ...
(sleep/yield 1))
list-of-points))
将它们放在一起得出:
#lang racket
(require racket/gui plot)
(define main-window (new frame% [label "FUNCTION AND POINTS"] [width 200] [height 600]))
(define canvas-panel (new panel% [parent main-window]))
(define function-canvas (new canvas% [parent canvas-panel]))
(send main-window show #t)
(plot-background-alpha 0)
(define plot-func (function (λ (x) (+ (sin (* 5 x)) 3))
0 (* 2 pi)))
(define plot-background
(plot-bitmap plot-func
#:x-min 0
#:x-max 3
#:y-min 0
#:y-max 9
#:width (- (send canvas-panel get-width) 40)
#:height (- (send canvas-panel get-height) 40)))
(define (plot-points list-of-points)
(for-each
(λ (population)
(define dc (send function-canvas get-dc))
(send dc clear)
(send dc draw-bitmap plot-background 0 0)
(plot/dc (points population
#:x-min 0
#:x-max 3
#:y-min 0
#:y-max 9
#:color 'red)
dc
0 0
(- (send canvas-panel get-width) 40)
(- (send canvas-panel get-height) 40))
(sleep/yield 1))
list-of-points))
(plot-points '(((1 8) (2 5) (2.5 2))
((2 5) (1.5 6.5) (2 3))
((1.5 3) (2 2) (1.5 3.5))
((2 7) (0.5 1) (2 0.5))
((0.5 9) (0 5) (0.5 0))
((0 1) (1 4.5) (0 8.5))))
1显然这取决于您正在计算的细节以及您想要绘制它的速度。它实际上可能足够快。 ;)