gnuplot 中的填充图案

Hatch patterns in gnuplot

我想知道 gnuplot 是否提供了比您在键入 "test"(例如在 wxt 终端中)时看到的那 8 个模式更多的阴影模式

也许有超过8个填充图案? ...显然不是,如下面的代码所示... 我说的不是不同颜色组合的图案,我只是说图案的类型。

我希望你能实现,例如水平或垂直阴影图案。 甚至可以设置影线之间的距离,甚至可以设置角度。 也许你可以?

### hatched pattern fill
reset session
set colorsequence classic
N = 28
set samples N
set table $Data
   plot [1:N] x
unset table
plot for [i=1:N] $Data u 1:1:(1) every ::i-1::i-1 with boxes fs pattern i not
### end of code

假设我们想要在函数 y=f(x) >0 和 y = 0 之间绘制一个区域。可以使用以下方法创建不同的 "patterns"。 (i) 创建一个包含 4 列(x、y、xdelta、ydelta)的文件。该文件描述了一组具有相同斜率的线。 (ii) 使用选项 "with vectors" 从文件中绘制数据。我们得到一个阴影(阴影)矩形。 (iii) 使用选项 "with filledcurve below y=ymax fc 'white'" 绘制 f(x)。重复步骤 (i) 和 (ii) 给出 "crossed" 模式。这是代码示例(single-hatched 模式),gnuplot v.5.2:

f(x) = 1.5+sin(x)
# Plot a "pattern" (for 2 < x < 4) and f(x):
plot[1:5][0:3] 'a1.dat'u 1:2:3:4 w vect nohead lt 4 lw 3,\
  f(x) w l lt 3 lw 4
pause -1
# Plot a "pattern" and f(x), and white area above f(x):
plot[1:5][0:3] 'a1.dat'u 1:2:3:4 w vect nohead lt 4 lw 3,\
  f(x) w l lt 3 lw 4, f(x) w filledcur below y=3 fc 'white'

文件 'a1.dat' 具有以下行:

2.0 2.5 0.5 0.5
2.0 2.0 3   3
2.0 1.5 3   3
2.0 1.0 2   2
2.0 0.5 2   2
2.0 0.0 2   2
2.5 0.0 1.5 1.5
3.0 0.0 1   1
3.5 0.0 0.5 0.5

这是实现“non-standard”填充图案的(有些麻烦)程序。 该过程很简单,但在 gnuplot 中仍然有些冗长。欢迎改进。

程序:

  1. 确定数据点的边界框
  2. 创建一个数据块$HatchBBox,用影线完全覆盖边界框(见下面的第一张图片)
  3. 通过寻找阴影线与路径的交点来切割阴影线并将其写入数据块$Hatch
  4. 绘制数据块 $Data$Hatch

$HatchBBox 的示例,即覆盖闭合路径边界框的阴影线:

要求、限制和改进:

  • 需要闭合路径
  • 适用于凸区域并仅限于凹区域,只要散列线与路径只有 2 个交点
  • 改进空间:填充图案不应取决于边界框大小,而应在像素级别上相等。当然,在某种程度上是可能的,但实现起来可能更复杂。

编辑: 这是带有新示例的修订版。 具有随机填充图案的随机路径网格。

为了保持概览,实际的舱口生成被放入外部过程tbHatchArea.gpp并从主代码中调用。

代码:

子程序:tbHatchArea.gpp

### create hatched areas from a datablock
# input ARG1: input datablock
# input ARG2: hatch parameters
# input ARG3: output datablock

# some necessary functions
# orientation of 3 points a,b,c: -1=clockwise, 0=linear, +1=counterclockwise
Orientation(a,b,c) = sgn((word(b,1)-word(a,1))*(word(c,2)-word(a,2)) - \
                         (word(c,1)-word(a,1))*(word(b,2)-word(a,2)))

# check for intersection of segment a-b with segment c-d,
# 0=no intersection, 1=intersection
IntersectionCheck(a,b,c,d) = \
    (Orientation(a,c,b)==Orientation(a,d,b)) || (Orientation(c,a,d)==Orientation(c,b,d)) ? 0 : 1

# calculate coordinates of intersection point, "" if identical points
M(a,b) = real(word(a,1)*word(b,2) - word(a,2)*word(b,1))
N(a,b,c,d) = (word(a,1)-word(b,1))*(word(c,2)-word(d,2)) - \
             (word(a,2)-word(b,2))*(word(c,1)-word(d,1))
Intersection(a,b,c,d) = N(a,b,c,d) !=0 ? sprintf("%g %g", \
    (M(a,b)*(word(c,1)-word(d,1)) - (word(a,1)-word(b,1))*M(c,d))/N(a,b,c,d), \
    (M(a,b)*(word(c,2)-word(d,2)) - (word(a,2)-word(b,2))*M(c,d))/N(a,b,c,d)) : ""

myHatchAngle(n,m)   = word(@ARG2[n+1],m+1)  # Hatch angle 1,2
myHatchSteps(n)     = word(@ARG2[n+1],4)    # Hatch steps
myHatchLinewidth(n) = word(@ARG2[n+1],5)    # Hatch linewidth
myHatchColor(n)     = word(@ARG2[n+1],6)    # Hatch color

# create datablock hatch pattern
IndexStart = 0
IndexEnd = |@ARG2|-1
set print @ARG3
do for [k=IndexStart:IndexEnd] {    # loop all sub-datablocks if there is a line in $HatchParam
    set table $SingleCurve
        plot @ARG1 u 1:2 index k w table
    unset table
    stats $SingleCurve u 1:2 nooutput
    xmin = STATS_min_x
    ymin = STATS_min_y
    xmax = STATS_max_x
    ymax = STATS_max_y
    xrange = xmax-xmin
    yrange = ymax-ymin
    Diagonal = sqrt(xrange**2 + yrange**2)
    
    # create hatch lines covering the whole bounding box
    set samples myHatchSteps(k)+1
    amax = myHatchAngle(k,2) == myHatchAngle(k,2) ? 2 : 1  # in case there are two hatch angles
    set table $HatchBBox
        do for [a=1:amax] {
            ystart = myHatchAngle(k,a) > 0 ? ymax : ymin
            Pix(i) = xmin + xrange/myHatchSteps(k)*i
            Piy(i) = ystart - sgn(myHatchAngle(k,a))*yrange/myHatchSteps(k)*i
            plot '+' u (Pix([=10=])-Diagonal*cos(myHatchAngle(k,a))): \
                       (Piy([=10=])-Diagonal*sin(myHatchAngle(k,a))): \
                       (Pix([=10=])+Diagonal*cos(myHatchAngle(k,a))): \
                       (Piy([=10=])+Diagonal*sin(myHatchAngle(k,a))) w table
        }
    unset table 

    # looping data segments for finding intersections
    do for [i=1:|$HatchBBox|] {
        a = sprintf("%s %s", word($HatchBBox[i],1),word($HatchBBox[i],2))
        b = sprintf("%s %s", word($HatchBBox[i],3),word($HatchBBox[i],4))
        Line = ''
        Intersection0 = ""
        do for [j=1:|$SingleCurve|-1] {
            c = $SingleCurve[j]
            d = $SingleCurve[j+1]
            if (IntersectionCheck(a,b,c,d)) {
                Intersection1 = Intersection(a,b,c,d)
                if ((Intersection0 ne Intersection1)) {
                    print sprintf("%s %s",Intersection0, Intersection1)
                }
                Intersection0 = Intersection1
            }
        }
    }
    print ""; print ""
}
set print
### end of code

主要代码:

### random hatched patchwork
reset session

# create some random patchwork grid points
set print $Patchwork
do for [i=0:10] {
    do for [j=0:10] { 
        print sprintf("%g %g %g %g",i,j,i+rand(0)*0.8-0.4, j+rand(0)*0.8-0.4)
    }
}
set print

# create patchwork areas from patchwork points
set print $PatchworkFrames
do for [i=0:9] {
    do for [j=0:9] {
        k = i*11+j
        print sprintf("%s %s",word($Patchwork[i*11+j+1],3),word($Patchwork[i*11+j+1],4))
        print sprintf("%s %s",word($Patchwork[i*11+j+2],3),word($Patchwork[i*11+j+2],4))
        print sprintf("%s %s",word($Patchwork[(i+1)*11+j+2],3),word($Patchwork[(i+1)*11+j+2],4))
        print sprintf("%s %s",word($Patchwork[(i+1)*11+j+1],3),word($Patchwork[(i+1)*11+j+1],4))
        print sprintf("%s %s",word($Patchwork[i*11+j+1],3),word($Patchwork[i*11+j+1],4))
        print "";  print ""
    }
}
set print

# create random angles, linecounts, linewidths and colors
# subdatablockNo, angle1, angle2, linesCount, lineWidth, color
set print $HatchParams
do for [i=1:100] {
    print sprintf("%g %g %s %g %g %s", \
      i, a=rand(0)*180-90, rand(0)>0.5 ? sprintf("%g",-a) : "NaN", \
      int(rand(0)*10)+5, rand(0)+0.5, sprintf("0x%06x",rand(0)*0xffffff))
}
set print

set size ratio -1
set angle degrees
set xrange[-1:11]
set yrange[-1:11]

call "tbHatchArea.gpp" "$PatchworkFrames" "$HatchParams" "$Hatch"

plot $PatchworkFrames u 1:2 w l lc rgb "black" notitle, \
     for [i=0:|$HatchParams|-1] $Hatch u 1:2:(-):(-) index i w vec \
     lc rgb myHatchColor(i) lw myHatchLinewidth(i) nohead notitle
### end of code

结果:(可能需要一段时间才能生成)