【问题标题】:GNUPlot: Animating LabelsGNUPlot:动画标签
【发布时间】:2014-09-03 05:45:31
【问题描述】:

我的问题,继我之前的问题之后,现在是这样的:我有一个粒子在平面上移动,现在我想要一个盒子在一边,上面写着粒子在 XY 中的位置和它的速度。我尝试使用标签,但它们最终会相互重叠。

这是我想看到的非常粗略的“草图”:

    +------------------------------------------+
    |         +-----------+                    |
    |         |           |       t = 2        |
    |         | PLOT HERE |  x = 0    y = 1    |
    |         |           |  vx = 2   vy = 3   |
    |         +-----------+                    |
    +------------------------------------------+

这些数字在每一帧都会发生变化。我已经能够为标题制作动画,但标签似乎有所不同。

我当前的代码看起来很像GNUPlot - Plot 2D datapoints as MPEG 中的答案,但有一些小的文体修改,我删除了标题。我可以生成只是 XY 坐标的数据,这就是我现在使用的。

我也可以产生类似的东西(这些是随机点,只是为了说明)

 #X      Y      t       vx     vy
  0.00   1.00   0.0     0.0   6.28
  0.01   0.01   0.01    1.0   6.00

用于动画标签。

【问题讨论】:

    标签: gnuplot


    【解决方案1】:

    从数据文件中放置标签的一个好方法是使用labels 绘图样式。但是,将标签放置在实际绘图区域之外存在一些困难,因为这些点和标签通常会被剪裁。

    由于您无论如何都在使用stats 来修复 x 和 y 范围,因此我将这样做:

    • 设置一个固定的右边距,例如set rmargin 20。这使用 20 个字符宽度的右边距。您也可以使用像set rmargin at screen 0.8 这样的绝对坐标,但由于您需要边距来放置标签,因此字符单位似乎是合适的。

    • 使用绘图区域的右上角作为参考点(STATS_max_x, STATS_max_y),并使用offset 参数移动标签并再次移动一些字符宽度。

    因此,一个完整的脚本可能如下所示:

    # calculate the number of points
    stats 'file.txt' using 1:2 nooutput
    
    # if you want to have a fixed range for all plots
    set xrange [STATS_min_x:STATS_max_x]
    set yrange [STATS_min_y:STATS_max_y]
    
    set terminal pngcairo size 800,400
    outtmpl = 'output%07d.png'
    
    v_label(x, y) = sprintf('vx = %.2f  vy = %.2f', x, y)
    c_label(x, y) = sprintf('x = %d  y = %d', x, y)
    t_label(t) = sprintf('t = %.2f', t)
    
    set rmargin 20
    
    do for [i=0:STATS_records-1] {
        set output sprintf(outtmpl, i)
        plot 'file.txt' every ::::i with lines title sprintf('n = %d', i),\
             '' every ::i::i using (STATS_max_x):(STATS_max_y):(t_label($3)) with labels offset char 11,-5 notitle,\
             '' every ::i::i using (STATS_max_x):(STATS_max_y):(c_label($1, $2)) with labels offset char 11,-6.5 notitle,\
             '' every ::i::i using (STATS_max_x):(STATS_max_y):(v_label($4, $5)) with labels offset char 11,-8 notitle
    }
    
    set output
    

    请注意,rmarginoffset 设置取决于终端、终端大小、字体和字体大小。为了更好地放置标签,您可以考虑分别放置 vxvy 标签,并可能更改它们的对齐方式。

    或者,在每次迭代中,您可以从数据文件中提取当前行并手动设置标签。但是,这需要您使用外部工具来提取该行:

    do for [i=0:STATS_records-1] {
        line = system(sprintf("sed -n %dp file.txt", i+2))
        set label 1 at screen 0.9, screen 0.9 sprintf("t = %.2f", real(word(line, 3)))
        set label 2 at screen 0.9, screen 0.88 sprintf("x = %.2f y = %.2f", real(word(line, 1)), real(word(line, 2)))
        plot 'file.txt' every ::::i with lines title sprintf('n = %d', i)
    }
    

    我不知道哪种变体更适合您。我使用i+2 作为行号来跳过注释的标题行,它不会自动检测到。通过使用标签 (set label 1) 的标签,您可以确保旧标签被覆盖。

    【讨论】:

    • 这很奇怪。我在终端中收到“第 23 行:警告:跳过没有有效点的数据文件”,并且标签出现在每个 other 帧中。此外,只有 t 和 vx 和 vy 标签得到更新; xy 标签仅在位于 xy 轴(粒子在椭圆中移动)时才会发生变化,因此它是 (0,1)、(-1,0) 等。
    • 我发布的脚本适用于您显示的两行数据文件(Windows 4.6.5、Linux 4.6.0、4.6.5 和 5.0rc2)。您是否尝试过这种最小配置?
    • 哦,我正在使用整个程序,大约有 2000 行。我用两条数据线试了一下,效果很好
    • 好的,现在您可以开始查看您在脚本中所做的更改,看看出了什么问题。特别是:您是否更改了画布大小和字体(名称或大小)?
    • 我也没有改变。我搞砸的只是输出文件的位置(我把它放在一个文件夹中)。通过在第 12 行中使用“c_label(x, y) = sprintf('x = %.2f y = %.2f', x, y)”,我确实设法修复了关于 XY 坐标的部分。我想要提到 XY 坐标标签出现在所有帧中,但 T 和 VX-VY 标签是每隔一帧出现的标签。
    猜你喜欢
    • 1970-01-01
    • 2013-08-05
    • 2014-05-18
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多