4

I'm drawing some bar charts using gnuplot (histogram). I need different and various patterns to fill the bars. Using "fs pattern XX", I can use some patterns, but they are all some lines.

I need the border to be solid line (linetype 1), and the bar be filled by dots. If I change the linetype of pattern, then the border is changed as well. I want to keep the border solid.

Any idea?

Farzad
  • 131
  • 1
  • 2
  • 10

2 Answers2

1

I found one terminal which supports dotted patterns: the lua tikz terminal:

set terminal lua tikz standalone
set output 'dot-pattern.tex'

set boxwidth 0.8 relative
set samples 10
unset key
set yrange [0:11]

plot '+' using 1:($0+1) with boxes lt -1 lw 2 lc rgb '#990000' fillstyle pattern 8
set output
system('pdflatex dot-pattern.tex')

enter image description here

With this you could also use custom fill patterns by overwriting a predefined pattern:

set terminal lua tikz standalone header '\tikzset{gp pattern 8/.style={pattern=mypatterh}}'

and you must define a custom pattern, like shown in Custom and built in TikZ fill patterns.

Using black borders and colored fill pattern is possible with

plot '+' using 1:($0+1) with boxes lc rgb '#990000' fillstyle pattern 8 noborder,\
     '+' using 1:($0+1) with boxes lt -1 lw 2
Community
  • 1
  • 1
Christoph
  • 47,569
  • 8
  • 87
  • 187
  • I'm trying to install lua. Having some problems, I can not install it and check your answer. – Farzad Apr 12 '14 at 20:56
  • What system do you run? – Christoph Apr 12 '14 at 20:59
  • ubuntu 12.04 LTS gnuplot v 4.6.4 – Farzad Apr 12 '14 at 21:49
  • Some time ago (don't remember exaclty when) I also had problems with lua on Debian. Here the problem was, that `pkg-config --libs lua` (as used in the `configure` file) didn't work. I had to do the following to get it working: run `export LUA_CFLAGS=$(pkg-config --cflags lua5.1) LUA_LIBS=$(pkg-config --libs lua5.1)` before running `./configure`. I don't remember if you need to specify `lua5.1` or `lua5.0` or `lua5`. – Christoph Apr 13 '14 at 09:02
0

If something does not exist in gnuplot, the chances are high that there is a workaround. Sometimes it's easy, sometimes it might get lengthy and awkward. For the gnuplot version at the time of OP's question, it might be probably difficult without the use of external tools. But here is a platform-independent gnuplot-only solution which works for gnuplot>=5.2.0, Sept. 2017.

So, if the existing fill patterns (no horizontal and vertical lines) are not sufficient you have to draw them "manually". Here, the fill is limited to boxes, but you could also do convex polygons or hatched lines.

Comments:

  • the script requires data in a datablock (you can either plot your file to a datablock or use this). Since the script uses indexing of datablocks it requires gnuplot>=5.2.0

  • it might not work properly with autorange. The range and the absolute boxwidth needs to be set beforehand

  • the spacing of fill lines or dots are given in pixel units. The script will convert to pixel coordinates and back. Hence, the script needs to plot a dummy plot in oder to get the proper GPVAL_ variable values

  • the fillstyle is set in column 3, where 0=empty, 1=horizontal lines, 2=vertical lines, and 4=dots. Other integers will result in an overlay of these basic patterns, e.g. 3 will be horizontal and vertical lines (boolean AND).

  • the color is set in column 4

  • depending on the pixel spacing dxp and dyp you might see aliasing artefacts. I don't know how to avoid them. This could maybe be a topic for the graphics library.

I know, it is a bit cumbersome, slow and certainly not efficient, but if you want horizontal or vertical lines or dots as fill it seems you have to "do-it-yourself". Suggestions for simplifications are welcome!

Script: (works with gnuplot>=5.2.0, Sept. 2017)

### "manual" pattern fills
reset session

# x  y    fill  color
$Data <<EOD
 1   46.4   0   0x000000
 2   64.6   1   0xff0000
 3   59.5   2   0x00ff00
 4   89.4   3   0x0000ff
 5   62.8   4   0xff00ff
 6   77.4   5   0xffff00
 7   83.7   6   0x00ffff
 8   55.0   7   0xffa500
EOD

set key noautotitle
set xrange[0:9]
set yrange[0:100]
set grid x,y
myBoxwidth = 0.8
myFill(i)  = int(word($Data[i],3))
myColor(i) = int(word($Data[i],4))

set boxwidth myBoxwidth
# plot data to get GPVAL_... values
plot $Data u 1:2 w boxes

# terminal constants
xmin     = GPVAL_X_MIN
ymin     = GPVAL_Y_MIN
xtmin    = GPVAL_TERM_XMIN
ytmin    = GPVAL_TERM_YMIN
Factor   = GPVAL_VERSION==5.2 && int(GPVAL_PATCHLEVEL)<=7 ? \
           GPVAL_TERM eq "wxt" ? 20 : GPVAL_TERM eq "qt" ? 10 : 1 : 1  # workaround for 5.2.0-5.2.7
Rxa2p    = (GPVAL_X_MAX-xmin)/(GPVAL_TERM_XMAX-xtmin)*Factor   # x ratio axes units to pixel units
Rya2p    = (GPVAL_Y_MAX-ymin)/(GPVAL_TERM_YMAX-ytmin)*Factor   # y
ax2px(x) = (x-xmin)/Rxa2p  + xtmin   # x axes coordinates to pixel coordinates
ay2py(y) = (y-ymin)/Rya2p  + ytmin   # y
px2ax(x) = (x-xtmin)*Rxa2p + xmin    # x pixel coordinates to axes coordinates
py2ay(y) = (y-ytmin)*Rya2p + ymin    # y
 
set table $Pix   # boxes in pixel coordinates
    plot $Data u (ax2px($1)-myBoxwidth/2./Rxa2p):(ay2py(GPVAL_Y_MIN)): \
                 (ax2px($1)+myBoxwidth/2./Rxa2p):(boxCount=$0+1,ay2py($2)) w table
unset table

x0(i)  = real(word($Pix[i],1))  # bottom left corner x
y0(i)  = real(word($Pix[i],2))  # bottom left corner y
x1(i)  = real(word($Pix[i],3))  # top right corner x
y1(i)  = real(word($Pix[i],4))  # top right corner y
ndx(i) = int((x1(i)-x0(i))/dxp) # number of lines in x
ndy(i) = int((y1(i)-y0(i))/dyp) # number of lines in y

maxSamples = (GPVAL_TERM_XMAX-GPVAL_TERM_XMIN) > (GPVAL_TERM_YMAX-GPVAL_TERM_YMIN) ? \
              GPVAL_TERM_XMAX-GPVAL_TERM_XMIN : GPVAL_TERM_YMAX-GPVAL_TERM_YMIN
set samples    maxSamples/Factor
set isosamples maxSamples/Factor

dxp = 8              # pixel spacing in x
dyp = 8              # pixel spacing in y
set table $Horizontal
    do for [i=1:boxCount] {
        plot '+' u (px2ax(x0(i)-myBoxwidth)):(y0=py2ay(y0(i)+$0*dyp)):(px2ax(x0(i))+myBoxwidth):(y0) every ::::ndy(i) w table
        plot '+' u ('') every ::0::1 w table
    }
unset table
set table $Vertical
    do for [i=1:boxCount] {
        plot '+' u (x0=px2ax(x0(i)+$0*dxp)):(py2ay(0)):(x0):(py2ay(y1(i))) every ::::ndx(i) w table
        plot '+' u ('') every ::0::1 w table
     }
unset table

dxp = 4              # pixel spacing in x
dyp = 4              # pixel spacing in y
set table $Dots
    do for [i=1:boxCount] {
        plot '++' u (x0=px2ax(x0(i)+(int($0)%ndx(i)+0.5)*dxp)):(y0=py2ay(y0(i)+(column(-1))*dyp)) every ::::ndx(i):ndy(i) w table
        plot '+' u ('') every ::0::1 w table
     }
unset table

plot for [i=1:boxCount] $Horizontal u (myFill(i)&1?$1:NaN):2:($3-$1):($4-$2):(myColor(i)) index i-1 w vec nohead lc rgb var, \
     for [i=1:boxCount] $Vertical   u (myFill(i)&2?$1:NaN):2:($3-$1):($4-$2):(myColor(i)) index i-1 w vec nohead lc rgb var, \
     for [i=1:boxCount] $Dots       u (myFill(i)&4?$1:NaN):2:(myColor(i)) index i-1 w p pt 7 ps 0.1 lc rgb var, \
     $Data u 1:2:(myBoxwidth):(myColor($0+1)) w boxes lw 1.3 lc rgb var
### end of script

Result:

enter image description here

theozh
  • 22,244
  • 5
  • 28
  • 72