【问题标题】:How to animate points over a function plot in Racket?如何在 Racket 中的函数图上为点设置动画?
【发布时间】:2020-01-21 15:10:58
【问题描述】:

我正在为遗传算法制作 GUI 可视化,并希望能够在此函数上绘制最大化函数和每一代个体的点。对于每一代,我只希望删除点,并将下一个点绘制在已经存在的函数图上。

使用函数plot/dc,我正在实现为每一代个体设置动画,绘制坐标列表中的所有点。但是这个方法每次运行时都会重绘画布。所以我不能在点后面绘制函数本身。我可以为每一代做一个功能和点的列表,但这会浪费资源。

使用此代码,您应该能够模拟我的实际开发状态。

#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))))

注意:上面的点是随机生成的,与遗传算法输出不对应,所以没有一个函数可以匹配这个坐标。

我希望在这些点后面绘制函数图形,以便能够看到发生的最大化。

【问题讨论】:

  • 您找到Interactive Overlays for 2D plots 文档了吗?特别是set-overlay-renderers 方法。 Blog Post by Alex Harsányi 有一些例子,如果你想从头开始的话,虽然这些是更少的动画和更多的鼠标交互
  • 当你在这些点后面绘制函数图形时,点变化时函数会固定吗?
  • 我已阅读文档,但很难适应点绘图,而不是鼠标交互。此外,在未来的阶段,我想绘制一个 3D 函数,其中的点覆盖它,而文档只说 2D。关于第二条评论,这正是我想要的。如有必要,该功能甚至可以是背景上的图像。

标签: user-interface plot racket


【解决方案1】:

这里有很多问题。但基本上你想把你的情节放在一个非全白的背景上,这样你就可以把别的东西(在这种情况下是一个函数情节)放在背景中。您可以使用background-alpha 参数执行此操作。

在上面的代码中添加这一行:

(plot-background-alpha 0)

将使积分不断叠加。由于您表示要移动点,因此您还需要在每个“帧”之间清除屏幕,您可以通过将绘图函数更改为:

(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 所以我们可以计算一次,将其渲染为图像,然后重新绘制每个“帧”。假设你在后台想要的函数是 (+ (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-widthget-height 不会存储实际画布的宽度/高度,直到 调用 show 方法。

现在我们需要更新 draw 函数来将这个图绘制到背景中:

(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显然这取决于您计算的细节以及您想要绘制它的速度。它实际上可能已经足够快了。 ;)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-07
    • 1970-01-01
    • 2021-07-04
    • 1970-01-01
    • 2018-01-30
    相关资源
    最近更新 更多