Hatch patterns in gnuplot

后端 未结 2 1901
半阙折子戏
半阙折子戏 2020-12-18 15:59

I am wondering if gnuplot offers more hatched patterns than those 8 patterns which you see when typing \"test\" (e.g. in wxt terminal)

Maybe there are more than 8 fi

相关标签:
2条回答
  • 2020-12-18 16:35

    Here is a (somehwat cumbersome) procedure to realize "non-standard" hatch patterns. The procedure is straightforward but still somewhat lengthy in gnuplot. Improvements are welcome.

    Procedure:

    1. Determine the bounding box of the datapoints
    2. create a datablock $HatchBBox which fully covers the bounding box with hatch lines (see first image below)
    3. cut the hatch lines by looking for intersections of hatch lines with the path and write it to datablock $Hatch.
    4. plot the datablock $Data and $Hatch.

    Example of $HatchBBox, i.e. hatch lines covering the bounding box of a closed path:

    Requirements, limitations and improvements:

    • requires a closed path
    • works for convex areas and limited to concave areas as long as there are only 2 intersections of hash lines with the path
    • room for improvement: hatch pattern should not depend on bounding box size but should be equal on pixel level. Certainly, somehow possible, but probably even more complicated to realize.

    Edit: Here is a revised version with a new illustrative example. A random pathwork grid with random hatch patterns.

    In order to keep the overview, the actual hatch generation is put into an external procedure tbHatchArea.gpp and called from the main code.

    Code:

    Subprocedure: 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($0)-Diagonal*cos(myHatchAngle(k,a))): \
                           (Piy($0)-Diagonal*sin(myHatchAngle(k,a))): \
                           (Pix($0)+Diagonal*cos(myHatchAngle(k,a))): \
                           (Piy($0)+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
    

    Main 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:($3-$1):($4-$2) index i w vec \
         lc rgb myHatchColor(i) lw myHatchLinewidth(i) nohead notitle
    ### end of code
    

    Result: (might take a while to generate)

    0 讨论(0)
  • 2020-12-18 16:37

    Suppose we want to pattern an area between function y=f(x) >0 and y = 0. It is posiible to create different "patterns" by using the following method. (i) Create a file that has 4 columns (x, y, xdelta, ydelta). This file describes a set of lines with the same slope. (ii) Plot data from the file, using option "with vectors". We get a shaded (hatched) rectangle. (iii) Plot f(x), using option "with filledcurve below y=ymax fc 'white'". Repeating steps (i) and (ii) gives a "crossed" pattern. Here is an example of a code (a single-hatched pattern), 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'
    

    File 'a1.dat' has the following rows:

    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
    

    0 讨论(0)
提交回复
热议问题