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 中仍然有些冗长。欢迎改进。
程序:
- 确定数据点的边界框
- 创建一个数据块
$HatchBBox
,用影线完全覆盖边界框(见下面的第一张图片)
- 通过寻找阴影线与路径的交点来切割阴影线并将其写入数据块
$Hatch
。
- 绘制数据块
$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
结果:(可能需要一段时间才能生成)
我想知道 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 中仍然有些冗长。欢迎改进。
程序:
- 确定数据点的边界框
- 创建一个数据块
$HatchBBox
,用影线完全覆盖边界框(见下面的第一张图片) - 通过寻找阴影线与路径的交点来切割阴影线并将其写入数据块
$Hatch
。 - 绘制数据块
$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
结果:(可能需要一段时间才能生成)