gnuplot:如何绘制带孔的填充区域? [英] gnuplot: How to draw a filled area with hole?

查看:87
本文介绍了gnuplot:如何绘制带孔的填充区域?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

也许有一种方法可以绘制一个带有孔的填充区域? 一个实际的例子是用透明的背景绘制南非的边界.下面是一个简单的复制和粘贴示例. 分别绘制index 0index 1或以背景色绘制都无济于事.有什么想法吗?

Is there maybe a way to draw a filled area with a hole in it? A practical example would be to draw the borders of South-Africa with transparent background. A simple copy&paste example below. Plotting index 0 and index 1 separately or plotting in background color does not help. Any ideas?

代码:

### filled area with hole
reset session
# set term wxt size 600,400
set term pngcairo size 600,400 transparent
set output "FilledWithHole.png"
$Data <<EOD
2 2
8 2
8 8
2 8
2 2


4 4
4 6
6 6
6 4
4 4
EOD

unset key
set xrange [0:10]
set yrange [0:10]
set linetype 1 lc rgb "green" lw 4
set multiplot layout 2,2
    plot x lt 1, $Data w lp lw 2 pt 7 lc rgb "red"
    plot x lt 1, $Data w filledcurve lw 2 lc rgb "red"
    plot x lt 1, $Data index 0 w filledcurve fc rgb "red", \
     '' index 1 w filledcurve fc rgb "blue"
    plot x lt 1, $Data index 0 w filledcurve fc rgb "red", \
     '' index 1 w filledcurve fc bgnd
unset multiplot
set output
### end of code

在wxt终端上查看:

"pngcairo终端"上的输出(具有透明背景):

举例说明我基本上希望从边界的x,y坐标实现的目标:

to illustrate what I basically would like to achieve from x,y coordinates of the borders:

推荐答案

这里是绘制带有透明孔的填充区域的解决方案. 简单"的想法是将多个闭合路径转换为单个闭合路径,并使用filledcurves对其进行绘制.对于较大的数据来说,这有点冗长和缓慢,但是到目前为止,我还没有找到更好的方法.我既不是数学家,也不是拓扑学家,所以,如果代码中可能存在更聪明,更有效的解决方案或错误,请告诉我.在Win7/64下使用gnuplot 5.2.6测试了代码.

Here is a solution to plot filled areas with transparent holes. The "simple" idea is to convert several closed paths to a single closed path and plot it with filledcurves. It's a bit lengthy and slow for larger data, but so far, I haven't found a better way. I'm neither a mathematician nor a topologist, so, if there might be smarter and more efficient solutions or mistakes in the code please let me know. Code tested with gnuplot 5.2.6 under Win7/64.

以下通过一个简单的示例说明了代码的基本作用:

The following illustrates with a simple example what the code is basically doing:

在左侧(输入):多条曲线.点用(曲线#/点#)标记,例如(4/7).

On the left (Input): several curves. Points are marked with (curve#/point#) e.g. (4/7).

在右侧(输出):一条单独的曲线,因此可以将该曲线绘制为已填充状态,从而使孔保持打开状态.点以其新顺序标记.

On the right (Output): one single curve, such that this curve can be plotted as filled leaving the holes open. Points are marked in their new order.

假设/限制:

  • 仅输入闭合的非相交(子)曲线(第一个数据点=最后一个数据点)
  • 数据文件中的两条曲线由两条空线分隔
  • (尚未)不处理多同心"曲线.

过程:

  1. 确定所有曲线的方向,顺时针(CW)或逆时针(CCW)
  2. 确定哪条曲线是外部曲线(例如y值最大的曲线)
  3. 更改方向,以使外部曲线为CCW,所有内部曲线为CW.
  4. 确定从外曲线的点到内曲线的点的最短连接.将此连接写入连接列表,该内部曲线现在已连接".
  5. 确定从其余未连接"曲线到已连接"曲线的最短连接.将此连接写入连接列表.
  6. 从5开始重复,直到所有曲线都连接"为止.
  7. 浏览连接列表,在连接点处分割第一条曲线,然后插入第二条曲线
  8. 从7开始重复,直到插入所有曲线.

结果是可以填充并显示所需孔的单个路径.

The result is a single path which can be filled and shows the desired holes.

代码:

主程序(tbSwissCheese.dem):

### plot filled area with transparent holes
reset session
set term pngcairo size 528,434 transparent
set output "SwissCheese.png"
unset key
unset border
unset tics
set size ratio 0.6361
set xrange [5.95:10.5]
set yrange [45.8:47.9]

# load datafile 1:1 to datablock for different platforms
FILE = "SwissCheese.dat"
if (GPVAL_SYSNAME[:7] eq "Windows") { load '< echo $Data ^<^<EOD & type "'.FILE.'"' }
if (GPVAL_SYSNAME eq "Linux" ) { load '< echo "\$Data << EOD" & cat "'.FILE.'"' }
if (GPVAL_SYSNAME eq "Darwin") { load '< echo "\$Data << EOD" & cat "'.FILE.'"' }

# get number of blocks
    stats [*:*][*:*] $Data nooutput
    BlockCount = STATS_blocks
    print "Curves found: ", BlockCount

# get all orientations and number of outer curve 
    array Orientations[BlockCount]
    call "tbGetOrientationsAndOuter.gpp" "$Data" "Orientations" "IndexOuter"
    print "IndexOuter: ", IndexOuter

# adjust orientations of curves
    call "tbAdjustOrientations.gpp" "$Data" "Orientations" "IndexOuter"
    print "Orientations: ", Orientations

# initialize array Connection status
    array ConnectionStatus[BlockCount]
    do for [i=1:BlockCount] { ConnectionStatus[i] = 0 }
    ConnectionStatus[IndexOuter+1] = 1

# get minimum distances between two curves
    do for [k=1:BlockCount-1] {
        print sprintf("Checking curve %d of %d",k,BlockCount-1)
        call "tbFindMinDistCurve.gpp" "$OrientedCurves" "ConnectionStatus"
    }
    print "Connections: \n", $Connections

# Combine all curves to one single curve
    call "tbCombineCurves.gpp" "$OrientedCurves" "$Connections" "IndexOuter" "$SinglePath"

# finally plot the curve as filled
    plot \
        $SinglePath u 1:2 w filledcurves closed fc rgb "#44ffff55",\
        $Data u 1:2 w l lc rgb "orange" lw 2
    set output
### end of code

必要的gnuplot程序:

tbGetOrientationsAndOuter.gpp

### get outer curve and orientation of all curves
# ARG1 = original curves
# ARG2 = array of orientations
# ARG3 = index of outer curve

# get outer curve via maximum y-coordinate 
# and get orientation of each curve 
# orientation of the curves: -1=clockwise, +1=counterclockwise
Orientation(xa,ya,xb,yb,xc,yc) = sgn((xb-xa)*(yc-ya) - (xc-xa)*(yb-ya))

set table $Dummy
    do for [i=0:BlockCount-1] {
        xa=xb=xc=ya=yb=yc=NaN
        OSum = 0
        plot @ARG1 index i u \
            (p0maxY=($0==0? ($2): $2>=p0maxY ? $2 : p0maxY)): \
            (OuterMaxY=(i==0? (OuterIndex=i, p0maxY) : p0maxY>OuterMaxY ? (OuterIndex=i, p0maxY) : OuterMaxY)): \
            (xa=xb,xb=xc,xc=$1,ya=yb,yb=yc,yc=$2, \
            OSum=OSum+Orientation(xa,ya,xb,yb,xc,yc)) \
            with table
        @ARG2[i+1] = sgn(OSum)
    }
unset table
@ARG3 = OuterIndex
### end of code

tbAdjustOrientation.gpp

### adjust orientations of curves
# outer curve-->CCW, inner curves-->CW
# ARG1 = original curves
# ARG2 = array of orientations of curves (+1=CCW, -1=CW)
# ARG3 = IndexOuter

set print $OrientedCurves
    do for [i=1:|@ARG2|] {   # loop curves
        set table $Tmp
            plot @ARG1 index i-1 u 1:2:(column(-2)):0 w table
        unset table
        set table $TmpRev
            plot @ARG1 index i-1 u 1:2:(column(-2)):(|$Tmp|-1-$0) w table
        unset table
        Orientation = @ARG2[i]
        if ((i-1==@ARG3 && Orientation ==-1) || (i-1!=@ARG3 && Orientation==1)) {
            @ARG2[i] = -Orientation
            do for [i=|$Tmp|:1:-1] { print $TmpRev[i]}  # reverse curve
        }
        else { print $Tmp }
        print "\n"           # add empty line
        print "\n"           # add empty line
    }
set print
undef $Tmp
### end of code

tbFindMinDistCurve.gpp

### find minimum distance between curves
# ARG1 = Curves with corrected orientation
# ARG2 = Connection status

# function for distance of two points
Dist(x0,y0,x1,y1) = sqrt((x1-x0)**2 + (y1-y0)**2)

# Define macros for later
FindMinDist = "C1minB=C1B, C1minN=C1N, C1minX=C1X, C1minY=C1Y, \
               C2minB=$3,  C2minN=$0,  C2minX=$1,  C2minY=$2, Dist(C1X,C1Y,$1,$2)"
FindAbsMinDist = "AbsC1minB=C1minB, AbsC1minN=C1minN,\
                  AbsC2minB=C2minB, AbsC2minN=C2minN, MinDist"

# put connected curves into one datablock
set table $Connected
    do for [i=1:|@ARG2|] {
        if (@ARG2[i]==1) {
            plot @ARG1 index i-1 u 1:2:3:4 every ::1 w table
        }
    }
unset table

set table $Dummy
    do for [i=1:|@ARG2|] {
        if (@ARG2[i]==0) {
            do for [j=1:|$Connected|] {
                C1X = real(word($Connected[j],1))    # x-coordinate
                C1Y = real(word($Connected[j],2))    # y-coordinate
                C1B =  int(word($Connected[j],3))    # block number
                C1N =  int(word($Connected[j],4))    # point number
                plot @ARG1 index i-1 u \
                    (MinDist=(j==1?(@FindMinDist):(Dist(C1X,C1Y,$1,$2)<=MinDist) ? \
                    (@FindMinDist) : MinDist)) with table
                AbsMinDist = (j==1?(@FindAbsMinDist): MinDist<=AbsMinDist?(@FindAbsMinDist): AbsMinDist)
            }
        }
    }
unset table
@ARG2[AbsC2minB+1] = 1

set print $Connections append
    print sprintf("%d %d %d %d %g %g %g %g", \
        int(AbsC1minB), int(AbsC1minN), int(AbsC2minB), int(AbsC2minN), \
        C1minX,C1minY, C2minX,C2minY)
set print
### end of code

tbCombineCurves.gpp

### combine curves to one curve
# outer curve-->CCW, inner curves-->CW
# ARG1 = $OrientedCurves
# ARG2 = $Connections
# ARG3 = IndexOuter
# ARG4 = Combined curves

set table @ARG4
    plot @ARG1 index IndexOuter u 1:2:3:4 w table
unset table

do for [k=1:|@ARG2|] {
    Flag = 1
    Block1=int(word(@ARG2[k],1))
    Point1=int(word(@ARG2[k],2))
    Block2=int(word(@ARG2[k],3))
    Point2=int(word(@ARG2[k],4))
    set table $Tmp1
        plot @ARG4 u 1:2:3:4 w table
    set table $Tmp2 
        plot @ARG1 index Block2 u 1:2:3:4 w table
    unset table
    set print @ARG4
        do for [i=1:|$Tmp1|] {
            print $Tmp1[i]
            if (int(word($Tmp1[i],3))==Block1 && int(word($Tmp1[i],4))==Point1 && Flag) {
                do for [j=0:|$Tmp2|-1] {
                    p=(j+Point2)%(|$Tmp2|-1)
                    print $Tmp2[p+1]
                }
                print $Tmp1[i]
                Flag=0
            }
        }
        print "\n"
        print "\n"
    set print
}
undefine $Tmp*
### end of code

测试数据文件: SwissCheese.dat

# Switzerland with holes
8.850   47.200
8.843   47.234
8.821   47.265
8.788   47.289
8.746   47.305
8.700   47.310
8.654   47.305
8.612   47.289
8.579   47.265
8.557   47.234
8.550   47.200
8.557   47.166
8.579   47.135
8.612   47.111
8.654   47.095
8.700   47.090
8.746   47.095
8.788   47.111
8.821   47.135
8.843   47.166
8.850   47.200


7.550   46.800
7.543   46.834
7.521   46.865
7.488   46.889
7.446   46.905
7.400   46.910
7.354   46.905
7.312   46.889
7.279   46.865
7.257   46.834
7.250   46.800
7.257   46.766
7.279   46.735
7.312   46.711
7.354   46.695
7.400   46.690
7.446   46.695
7.488   46.711
7.521   46.735
7.543   46.766
7.550   46.800


9.150   46.700
9.143   46.737
9.121   46.771
9.088   46.797
9.046   46.814
9.000   46.820
8.954   46.814
8.912   46.797
8.879   46.771
8.857   46.737
8.850   46.700
8.857   46.663
8.879   46.629
8.912   46.603
8.954   46.586
9.000   46.580
9.046   46.586
9.088   46.603
9.121   46.629
9.143   46.663
9.150   46.700


9.700   46.800
9.690   46.846
9.662   46.888
9.618   46.921
9.562   46.943
9.500   46.950
9.438   46.943
9.382   46.921
9.338   46.888
9.310   46.846
9.300   46.800
9.310   46.754
9.338   46.712
9.382   46.679
9.438   46.657
9.500   46.650
9.562   46.657
9.618   46.679
9.662   46.712
9.690   46.754
9.700   46.800


7.600   46.300
7.590   46.346
7.562   46.388
7.518   46.421
7.462   46.443
7.400   46.450
7.338   46.443
7.282   46.421
7.238   46.388
7.210   46.346
7.200   46.300
7.210   46.254
7.238   46.212
7.282   46.179
7.338   46.157
7.400   46.150
7.462   46.157
7.518   46.179
7.562   46.212
7.590   46.254
7.600   46.300


8.300   47.000
8.285   47.068
8.243   47.129
8.176   47.178
8.093   47.209
8.000   47.220
7.907   47.209
7.824   47.178
7.757   47.129
7.715   47.068
7.700   47.000
7.715   46.932
7.757   46.871
7.824   46.822
7.907   46.791
8.000   46.780
8.093   46.791
8.176   46.822
8.243   46.871
8.285   46.932
8.300   47.000


8.75652 47.692
8.79566 47.6794
8.77868 47.7081
8.80838 47.7342
8.87728 47.7049
8.85577 47.6931
8.90052 47.6569
8.97066 47.67
9.07024 47.6836
9.16198 47.6716
9.23075 47.6578
9.35642 47.6284
9.49647 47.5645
9.54375 47.5393
9.57583 47.4924
9.60636 47.4695
9.64052 47.4616
9.65088 47.4368
9.65767 47.3999
9.66886 47.3815
9.62469 47.375
9.59403 47.3339
9.57281 47.3112
9.53591 47.2735
9.49258 47.1793
9.52463 47.1066
9.48709 47.0744
9.48043 47.0586
9.5357  47.0671
9.60366 47.0615
9.66729 47.061
9.74091 47.0456
9.79775 47.0311
9.86504 47.0261
9.8897  46.9992
9.87519 46.946
9.89922 46.9302
9.94194 46.9137
9.98239 46.9091
10.0223 46.8978
10.08   46.8638
10.1548 46.8527
10.2323 46.8787
10.2372 46.9089
10.2555 46.9322
10.3105 46.9318
10.3311 46.9626
10.388  47.0021
10.4236 46.9661
10.4627 46.9551
10.4884 46.9192
10.4674 46.8722
10.4582 46.8312
10.4297 46.7959
10.4438 46.7591
10.4174 46.716
10.3885 46.6619
10.4273 46.6413
10.486  46.613
10.484  46.5853
10.4642 46.5486
10.4188 46.5518
10.383  46.55
10.326  46.5503
10.2866 46.5704
10.254  46.5755
10.2503 46.6042
10.2335 46.6352
10.1856 46.6232
10.1086 46.6054
10.0936 46.5763
10.0509 46.5368
10.041  46.4854
10.0616 46.428
10.1313 46.4325
10.1606 46.4005
10.1173 46.3626
10.1211 46.3162
10.1478 46.2416
10.1018 46.2335
10.0621 46.2265
10.0508 46.2666
10  46.2902
9.98641 46.3342
9.96431 46.3658
9.91552 46.3768
9.85695 46.3659
9.777   46.3387
9.72824 46.3477
9.72411 46.3148
9.63031 46.2921
9.5723  46.3024
9.51322 46.3494
9.46786 46.3758
9.45087 46.4252
9.46635 46.4952
9.427   46.4935
9.37299 46.4842
9.34341 46.509
9.27718 46.4883
9.24953 46.4437
9.26993 46.4168
9.29092 46.3506
9.25114 46.2749
9.22734 46.237
9.19496 46.2003
9.15606 46.1725
9.10494 46.1377
9.07538 46.118
9.06763 46.0682
9.01162 46.0455
9.02197 46.0052
9.00059 45.9709
9.02967 45.9293
9.06734 45.9213
9.08394 45.9062
9.04751 45.8626
9.01644 45.8259
8.9916  45.8424
8.94941 45.8501
8.91422 45.854
8.93746 45.8801
8.8997  45.9327
8.88224 45.9668
8.81466 46.0004
8.79715 46.0193
8.83691 46.0434
8.85627 46.0687
8.83295 46.093
8.76167 46.1082
8.73967 46.1138
8.68504 46.1143
8.63116 46.1279
8.59412 46.1534
8.56392 46.1889
8.51833 46.2278
8.45157 46.2595
8.4349  46.3051
8.46016 46.3507
8.45917 46.386
8.46436 46.4376
8.42073 46.4643
8.35604 46.4468
8.30272 46.4277
8.30286 46.4048
8.29548 46.3737
8.21874 46.3232
8.14417 46.3094
8.09535 46.2744
8.1331  46.2373
8.16343 46.1868
8.12882 46.1431
8.07063 46.1169
8.02392 46.0742
8.00836 46.0278
7.90553 46.0042
7.87016 45.9678
7.85925 45.9345
7.80055 45.9285
7.74491 45.9487
7.7127  45.9384
7.68223 45.965
7.64943 45.9863
7.57812 45.9869
7.53851 45.985
7.522   45.9708
7.47326 45.9626
7.44166 45.9385
7.38828 45.9167
7.33869 45.9225
7.28521 45.9226
7.22129 45.8976
7.20412 45.8753
7.1564  45.8874
7.10306 45.867
7.08425 45.8921
7.0434  45.9363
7.03921 45.9627
7.00379 45.9759
6.97844 46.0311
6.93391 46.069
6.88532 46.0588
6.88842 46.0969
6.89158 46.1298
6.80094 46.1393
6.78322 46.1731
6.80249 46.2232
6.84428 46.2687
6.81911 46.3178
6.78855 46.3329
6.76052 46.3621
6.79236 46.388
6.80835 46.4248
6.71691 46.4512
6.62648 46.4595
6.48707 46.4544
6.39078 46.4172
6.30078 46.3969
6.20829 46.318
6.23374 46.291
6.25861 46.2591
6.29396 46.2628
6.27403 46.2292
6.1728  46.1749
6.06898 46.1593
6.02194 46.1469
5.97861 46.1815
5.95746 46.2038
5.99444 46.2329
6.07484 46.2496
6.10812 46.2654
6.11198 46.3041
6.15166 46.3607
6.10234 46.4022
6.07657 46.4426
6.11547 46.5162
6.10404 46.5741
6.16471 46.6209
6.26512 46.69
6.33275 46.7205
6.36921 46.7382
6.44888 46.7855
6.42341 46.8152
6.45161 46.8532
6.43369 46.9161
6.47911 46.9728
6.51035 46.9793
6.58668 46.9989
6.64764 47.0314
6.67663 47.0542
6.69297 47.0726
6.73902 47.0958
6.74026 47.1146
6.77347 47.1267
6.81503 47.1437
6.85443 47.1721
6.84365 47.182
6.87413 47.1956
6.91109 47.2261
6.93734 47.243
6.94568 47.2575
6.94118 47.2917
6.96175 47.2948
6.99482 47.3017
7.02934 47.3307
7.05429 47.3451
7.02543 47.3754
6.93628 47.3655
6.87227 47.3662
6.91176 47.4006
6.93462 47.4235
6.9951  47.4576
6.98506 47.5021
7.04216 47.5011
7.14222 47.503
7.18955 47.4922
7.17478 47.4483
7.22997 47.44
7.27313 47.4347
7.36734 47.4367
7.43686 47.4707
7.44782 47.4787
7.43112 47.5014
7.4788  47.484
7.50957 47.514
7.52749 47.5602
7.5522  47.5857
7.58312 47.5823
7.62708 47.5929
7.65024 47.6061
7.659   47.5956
7.66017 47.5769
7.64654 47.568
7.65907 47.5453
7.70219 47.5432
7.76452 47.5546
7.79921 47.5636
7.82706 47.5892
7.88092 47.591
7.91064 47.5781
7.93957 47.5489
7.95685 47.5593
8.01242 47.5538
8.05216 47.5605
8.08776 47.563
8.11247 47.5866
8.13889 47.5923
8.17595 47.6037
8.2028  47.6231
8.2277  47.6163
8.24005 47.6165
8.26922 47.6146
8.30056 47.6082
8.32723 47.5798
8.35691 47.5725
8.40435 47.5815
8.43089 47.5737
8.45715 47.5768
8.48958 47.5896
8.46754 47.6055
8.53098 47.6357
8.56918 47.6209
8.59575 47.6001
8.60178 47.6302
8.61061 47.6553
8.62305 47.6455
8.59813 47.6752
8.54224 47.6624
8.529   47.6491
8.48908 47.6499
8.46953 47.6485
8.44101 47.6582
8.42457 47.6933
8.42269 47.7081
8.45988 47.7438
8.52979 47.7769
8.57182 47.7839
8.56947 47.8053
8.62885 47.7931
8.63503 47.7646
8.64465 47.792
8.68775 47.7751
8.70257 47.7617
8.72933 47.746
8.73522 47.7193
8.75652 47.692

结果: SwissCheese.png

这篇关于gnuplot:如何绘制带孔的填充区域?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆