【问题标题】:How to draw 2D diagram in linux如何在linux中绘制二维图
【发布时间】:2016-02-14 10:36:28
【问题描述】:

我有一个 .txt 文件包含点,如下所示:

##x1 y1 x2 y2
123 567 798 900
788 900 87  89
....

我想绘制 2D 图,它使用 gnuplot 将 .txt 文件中的每一对链接起来。

编辑1:

我找到了这个Draw points and lines in gnuplot,但我不知道如何在我的情况下使用 gnuplot。

编辑2:

图表类型没有限制。 正如我所看到的here,我可以使用以下命令将终端设置为 png:

set terminal png

对于线条样式我找到了这个例子here:

set style line 1 lc rgb '#0060ad' lt 1 lw 2 pt 7 ps 1.5 

并且轴不需要标签。

【问题讨论】:

  • 这张图是PDF、PNG还是JPEG?线条会是什么颜色?它们应该有多厚?轴需要标签吗?最后,到目前为止,您尝试过什么?
  • 我已经编辑了我的问题。
  • 文件中大概有多少行?你知道 x 和 y 的最大可能值吗 - 都是 x 和 y 都在 1000 以下,也许
  • @MarkSetchell,行数为40331,最大x为54957,y为65534!

标签: linux gnuplot diagram


【解决方案1】:

更新

鉴于您对行数和最大 x,y 尺寸的回复,我在此答案底部的基于 ImageMagick 的原始方法显然不适合您的特定问题。但是,我会把它留给其他人看,因为它最多可以容纳几十行。我现在提供一个更合适的gnuplot 版本。

Gnuplot 版本

如果你想用gnuplot 来做,它看起来像这样:

set terminal png size 1000,1000
set output 'result.png'
unset xtics
unset ytics
unset border
plot 'lines.txt' using 1:2:($3-$1):($4-$2) with vectors nohead notitle

如果您将其保存在名为 plot.cmd 的文件中,则可以使用以下命令运行它

gnuplot < plot.cmd

如果您想要箭头,请使用如下变体:

set terminal png size 1000,1000
set output 'result.png'
set style arrow 1 heads filled size screen 0.03,15,45 ls 1
unset xtics
unset ytics
unset border
plot 'lines.txt' using 1:2:($3-$1):($4-$2) with vectors arrowstyle 1  notitle 

Magick++ 和 C++ 答案

我决定想出一个 Magick++ 和 C++ 的答案,只是为了好玩。代码如下所示 - 编译命令显示在顶部的 cmets 中。

////////////////////////////////////////////////////////////////////////////////
// sample.cpp
// Mark Setchell
//
// ImageMagick Magick++ sample code
//
// Compile with:
// g++ sample.cpp -o sample $(Magick++-config --cppflags --cxxflags --ldflags --libs)
////////////////////////////////////////////////////////////////////////////////
#include <Magick++.h> 
#include <iostream> 
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

using namespace std; 
using namespace Magick; 

int main(int argc,char **argv) 
{ 
   InitializeMagick(*argv);

   // Create an image object, scaled by a factor of 100 to speed it up !
   float scale=100.0;
   Image image("650x650","white");

   // Construct drawing list 
   std::list<Magick::Drawable> drawList;

   // Initial settings, blue lines 1 pixel thick
   drawList.push_back(DrawableStrokeColor("blue"));
   drawList.push_back(DrawableStrokeWidth(1));

   // Read in lines from file, expected format "x1 y1 x2 y2"
   int lineno=0;
   std::ifstream infile("lines.txt");
   std::string line;
   while (std::getline(infile, line))
   {
      std::istringstream iss(line);
      int x1,y1,x2,y2;
      iss >> x1;
      iss >> y1;
      iss >> x2;
      iss >> y2;
      x1 = int(x1/scale);
      y1 = int(x2/scale);
      x2 = int(y1/scale);
      y2 = int(y2/scale);
      cout << "Line: " << ++lineno << " " << x1 << "," << y1 << " " << x2 << "," << y2 << endl;
      // Add this point to the list of lines to draw
      drawList.push_back(DrawableLine(x1,y1,x2,y2));
   }

   // Draw everything using completed drawing list 
   image.draw(drawList);

   // Write the image to a file 
   image.write( "result.png" ); 

   return 0; 
}

我用 Perl 生成了 1000 行随机测试数据,如下所示:

perl -E 'for($i=0;$i<1000;$i++){printf("%d %d %d %d\n",int rand 65000,int rand 65000, int rand 65000, int rand 65000);}' > lines.txt

结果如下:

原答案

您也可以使用已经安装在大多数 Linux 发行版上的 ImageMagick 轻松完成。下面其实只有4行代码——剩下的都是cmets:

#!/bin/bash

# Create the output image, 1000x1000 pixels say
convert -size 1000x1000 xc:pink result.png

# Suppressing lines that have a hash (#) at the start, read in the file "lines.txt"
grep -v "^#" lines.txt | while read x1 y1 x2 y2; do

   echo Read line $x1,$y1 $x2,$y2

   # Tell ImageMagick to draw the line on the image
   convert result.png -stroke blue -strokewidth 5 -draw "line $x1,$y1 $x2,$y2" result.png
done

输出

Read line 123,567 798,900
Read line 788,900 87,89

【讨论】:

  • 我想用圆圈或其他东西显示每行的开始和结束
  • 感谢您的更新,ImageMagick 会怎样?
  • 还有如何在 ImageMagick 中更改坐标,(现在是左上角,我想成为左下角)
  • 我最初建议的 ImageMagick 方法会加载整个图像,在其上画一条线,然后为每一行再次保存整个图像,因此对于 40,000 行来说并不好。出于性能原因,它需要在 Perl、PHP 或带有 Magick++ 的 C++ 中完成,这需要安装 Perl 模块或 PHP 和库或编译器,所以如果你不知道,它会相当冗长且相对困难你在做什么 - 特别是当你有一个有效的gnu plot 解决方案时。
  • 这里有关于使用 C++ 的 Magick++ 的教程...imagemagick.org/Magick++/tutorial/Magick++_tutorial.pdf 你会看到DrawableLine()
【解决方案2】:

您也可以使用 rsvg-convert(来自 librsvg)或 svg2png 来执行此操作。这两个程序都需要一个 SVG 格式的 inout 文件并将其呈现为 PNG 文件。所以你需要转换你的

123 567 798 900
788 900 87  89

喜欢这种东西

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <line x1="123" y1="567" x2="798" y2="900" stroke="blue" stroke-width="1"/>
  <line x1="788" y1="900" x2="87" y2="89" stroke="blue" stroke-width="1"/>
</svg>

这可以通过像这样的 awk 小脚本轻松完成:

awk '
   BEGIN{ printf("<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n") }

  {
     x1=$1; y1=$2; x2=$3; y2=$4;
     printf("<line x1=\"" x1 "\" y1=\"" y1 "\" x2=\"" x2 "\" y2=\"" y2 "\" stroke=\"blue\" stroke-width=\"1\"/>\n")
  }

  END{ printf("</svg>\n") }' points.txt

然后,您可以将其输出泵入我上面提到的两个程序中的任何一个:

awk ... | rsvg-convert -b \#ffff00 > result.png

【讨论】:

    猜你喜欢
    • 2016-03-26
    • 1970-01-01
    • 2011-01-05
    • 2016-07-20
    • 2012-10-28
    • 2021-10-13
    • 1970-01-01
    • 2015-05-29
    • 1970-01-01
    相关资源
    最近更新 更多