How to Draw 2D Diagram in Linux

How to draw 2D diagram in linux

Updated

In the light of your reply about the number of lines and the maximum x,y dimensions, my original, ImageMagick-based approach at the bottom of this answer is clearly NOT the right one for your specific problem. However, I will leave it for others to see as it would be perfectly fine for up to a few dozen lines. I am now providing a more appropriate gnuplot version.

Gnuplot Version

If you want to do it with gnuplot, it would look something like this:

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

If you save that in a file calle plot.cmd, you can then run it with

gnuplot < plot.cmd

Sample Image

If you want arrowheads, use a variant like this:

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

Sample Image

Magick++ and C++ Answer

I decided to work out a Magick++ and C++ answer, just for fun. The code looks like this - and the command to compile is shown in the comments at the top.

////////////////////////////////////////////////////////////////////////////////
// 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;
}

I generated 1,000 lines of random test data with Perl like this:

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

The result looks like this:

Sample Image

Original Answer

You could also do it quite easily with ImageMagick which is already installed on most Linux distros anyway. There are actually only 4 lines of code in the following - the rest is all comments:

#!/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

Sample Image

Output

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

c++ 2d plotting tool for linux

Check out Qwt. It's worked well for all of my 2D applications, plus it's cross-platform.

Draw points and lines in gnuplot

  • Organize your data in blocks. There should be exactly one empty line between two blocks:

    x1 y1
    x2 y2

    x3 y3
    x4 y4

    x5 y5
    x6 y6
    x7 y7
  • Use every to specify which blocks of the datafile should be plotted. The syntax of every is described here or in gnuplot (type help every)

  • In your case you can then do the following

    plot "data.txt" every :::0::1 with lp, "" every :::2::2 with points 


Related Topics



Leave a reply



Submit