1

In gnuplot, we can set object polygon to draw a polygon, including triangles, given its coordinates.

But how to do draw a set of triangles whose coordinates are stored in a file where each line is in the format <x1> <y1> <x2> <y2> <x3> <y3>?

As for rectrangles/circles, this task can be done using plot and with boxxy/with circles options, but there is no with triangles option in gnuplot.

A possible solution is to use with vectors by drawing each edge, but it is a bit complicated and this method does not support color filling.

chenzhongpu
  • 6,193
  • 8
  • 41
  • 79

2 Answers2

1

I cannot think of a way to do this in one step; the data format does not match any of gnuplot's plotting styles.

One approach is to transform the data via a temporary file. Here is an example that works in version 5.2 and newer. If you are using a newer gnuplot then you could substitute with polygons for with filledcurves closed.

$DATA << EOD
1 1 2 2 3 1
11 11 14 14 17 11
21 21 22 22 23 21
15 5 16 6 17 5
6 6 7 7 8 6
EOD

set table "temp.dat"
plot $DATA using (sprintf("%g %g\n %g %g\n %g %g\n \n",$1,$2,$3,$4,$5,$6)) with table
unset table

unset key
set style fill solid noborder
plot "temp.dat" using 1:2 with filledcurves closed fillcolor "forest-green"

enter image description here

Note: I was originally going to show use of a temporary datablock rather than an intermediate temporary file, but it this doesn't work because the formatted output from with table does not translate the newline characters \n into empty datablock lines.

Edit (show variable color)

The extra data field containing a RGB color must be present in every input line of the reformatted data, but only the value from the first vertex of each polygon is used. The sprintf format in this example has been modified to reproduce the color (NB: hexadecimal integer value) from the original data file accordingly, with zeros for the dummy values in the remaining polygon vertices.

$DATA << EOD
1 1 2 2 3 1             0x00ffff
11 11 14 14 17 11       0x191970
21 21 22 22 23 21       0x2e8b57
15 5 16 6 17 5          0xffc020
6 6 7 7 8 6             0x8b000
EOD

set table "temp.dat"
plot $DATA using (sprintf("%g %g 0x%x\n %g %g 0\n %g %g 0\n \n",$1,$2,int($7),$3,$4,$5,$6)) with table
unset table

unset key
set style fill solid noborder
plot "temp.dat" using 1:2:3 with filledcurves closed fillcolor rgb variable

enter image description here

Ethan
  • 13,715
  • 2
  • 12
  • 21
  • Thanks. What if the `fillcolor` (RGB) is also stored in the file? ` `? – chenzhongpu Apr 28 '22 at 01:52
  • @Ethan I remember a discussion with you quite a few years ago, whether `\n` should be translated to newline in a datablock as well (like in a file) or not. If you type `print $Datablock` in the gnuplot console it will appear as it was a newline, but internally it will not be interpreted as one. However, I don't remember the reason why it was *not* translated to a "real" newline in a datablock. – theozh Apr 28 '22 at 07:51
  • @theoz A datablock is not a single chunk of text with embedding newlines; it is an array of pointers, each one pointing to a character string that constitutes one "line". In this case each input line processed by the `plot` command generates one call to sprintf(), and the output datablock array is extended to contain a pointer to the output string from that sprintf(). If that string includes `\n` characters or other peculiar bytes, they are preserved. – Ethan Apr 28 '22 at 16:36
1

My suggestion would have been the same as @Ethan's. Therefore, here is an alternative approach using set object polygon. It also requires gnuplot>=5.2 since it uses indexing of datablock lines. Hence, the data should already be in a datablock without empty or commented lines. But how to get a file into a datablock?

Either something like:

set table $Data
    plot FILE u 1:2:3:4:5:6:7 w table
unset table

or alternatively see here: gnuplot: load datafile 1:1 into datablock

Script:

### draw some colored triangles from a datablock
reset session

$Data <<EOD
0   0   2   1   1   2   0xff0000
5   1   3   2   4   4   0x00ff00
3   3   2   5   1   4   0x0000ff
EOD

vx(n,t)  = word($Data[n],t*2-1)     # vertex x-coordinate
vy(n,t)  = word($Data[n],t*2)       # vertex y-coordinate
color(n) = word($Data[n],7)         # triangle color

set linetype 1 lc rgb "black"
do for [n=1:|$Data|] {
    set obj n polygon from vx(n,1),vy(n,1) to vx(n,2),vy(n,2) to vx(n,3),vy(n,3) to vx(n,1),vy(n,1)
    set obj n fc rgb color(n) fs solid 0.5 border lt 1 lw 3
}

set size square
set xrange[0:5]
set yrange[0:5]

plot NaN notitle    # or plot something else
### end of script

Result:

enter image description here

Addition:

Alternatively, similar to Ethan's solution, plotting triangles instead of drawing triangles, but without using a temporary file on disk (but a datablock). The result is identical to the graph above. I haven't tested whether drawing or plotting is faster and/or more efficient if you want to draw/plot thousands of triangles.

Script:

### plot some colored triangles from a datablock
reset session

$Data <<EOD
0   0   2   1   1   2   0xff0000
5   1   3   2   4   4   0x00ff00
3   3   2   5   1   4   0x0000ff
EOD

vx(n,t)  = word($Data[n],t*2-1)     # vertex x-coordinate
vy(n,t)  = word($Data[n],t*2)       # vertex y-coordinate
color(n) = word($Data[n],7)         # triangle color

set print $Triangles
   do for [n=1:|$Data|]  {
       print sprintf("%s %s %s\n%s %s 0\n%s %s 0\n%s %s 0\n\n", \
                     vx(n,1),vy(n,1),color(n), vx(n,2),vy(n,2), vx(n,3),vy(n,3), vx(n,1),vy(n,1))
   }
set print

set size square
set xrange[0:5]
set yrange[0:5]
set linetype 1 lc rgb "black" lw 3
set style fill solid 0.5

plot $Triangles u 1:2:3 w filledcurves lc rgb var notitle
### end of script
theozh
  • 22,244
  • 5
  • 28
  • 72