diff options
| -rwxr-xr-x | bin/piechart | 105 | ||||
| -rw-r--r-- | man/man1/piechart.1 | 66 |
2 files changed, 171 insertions, 0 deletions
diff --git a/bin/piechart b/bin/piechart new file mode 100755 index 0000000..c1a57ee --- /dev/null +++ b/bin/piechart @@ -0,0 +1,105 @@ +#!/usr/bin/awk -f +## piechart +# +# BUGS: +# Adjacient colours could have higher contrast. +# Negative angles. +# + +function hex(i) { + if (i < 16) { + if (i < 1) { + return "" + } else if (i < 10) { + return "" int(i) + } else switch (int(i)) { + case 10: return "a" + case 11: return "b" + case 12: return "c" + case 13: return "d" + case 14: return "e" + case 15: return "f" + } } + return hex(i/16) hex(i%16) +} +function phex(i) { + if (i==0) { return "00" } + if (i<16) { return "0" hex(i) } + return hex(i) +} + +BEGIN { + print "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>" + print "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1/EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">" + print "<svg" + print " xmlns=\"http://www.w3.org/2000/svg\"" + print " version=\"1.1\"" + print " width=\"500\"" + print " height=\"500\"" + print " viewBox=\"0 0 500 500\"" + print ">" + sum = 0 + values[0]=0 + labels[0]="" +} +END { + tau = 2*atan2(0,-1) + r = 100 + + progress = 0 + overlap = 0 + for (i = 1;i < length(values);i++) { + label = labels[i] + number = values[i] + angle = tau*number/sum + fangle = angle < 0 ? -angle : (angle-overlap) + + x1 = r*cos(progress); + y1 = r*sin(progress); + x2 = r*cos(progress+fangle); + y2 = r*sin(progress+fangle); + divider = progress+fangle/2; + xo = 250+(3*r/2*cos(divider)); + yo = 250+(3*r/2*sin(divider)); + + # rr = phex(int(0xff*((divider)/(tau)))); + # gg = phex(int(0xff*((divider-tau/3)/(tau)))); + # bb = phex(int(0xff*((divider-2*tau/3)/(tau)))); + + rr = int(0xff*((divider)/(tau)))%0x100; + gg = int(0xff*((divider+2*tau/3)/(tau)))%0x100; + bb = int(0xff*((divider+tau/3)/(tau)))%0x100; + + # Mx,y : move to x,y + # Lx,y : draw line to x,y + # Arx,ry rot 0,0 x,y : arc with radii rx,ry rotated by rot large-arch or not,clockwise or not to point x,y + # z : closes the path + printf "<path stroke=\"#000000\" fill=\"#%02x%02x%02x\" d=\"M250,250 L%f,%f A%f,%f 0 %d,%d %f,%f z\"/>\n", rr,gg,bb,250+x1,250+y1,r,r,(fangle>tau/2),1,250+x2,250+y2 + if (label != "") { + print "<line stroke=\"#000000\" x1=\"" 250+(2*r/3*cos(divider)) "\" y1=\"" 250+(2*r/3*sin(divider)) "\" x2=\"" xo "\" y2=\"" yo "\" />" + print "<text x=\"" xo "\" y=\"" yo "\">" label "</text>" + } + + progress += fangle; + overlap -= angle; # multiple overlaps accumulate + if (overlap<0) { overlap=0 } + } + print "</svg>" +} +# At the very least, we need a true value. +# Everything following it can be label or whatever. +/^[0-9]/ { + values[length(values)] = $1 + sum += $1 + labels[length(labels)] = substr($0, length($1)+2) +} +# If the value is negative, it is meant to overlap with the previous record. Or records. +# The value would have to be ignored for computing the sum total. +/^-[0-9]/ { + values[length(values)] = $1 + labels[length(labels)] = substr($0, length($1)+2) +} +# If there is no number, the line is obviously a comment and should be ignored. +!/^-?[0-9]/{ + print "<!-- " $0 "-->" +} diff --git a/man/man1/piechart.1 b/man/man1/piechart.1 new file mode 100644 index 0000000..dd80c65 --- /dev/null +++ b/man/man1/piechart.1 @@ -0,0 +1,66 @@ +.TH piechart 1 2026-04-12 utils + +.SH NAME +piechart \- turn a list into a piechart + +.SH SYNOPSIS +.SY piechart +.RI [ file ] +.YS + +.SH DESCRIPTION +.B piechart +is an +.BR awk (1) +script that reads a list, +either from +.BR stdin (3) +or from a specified file, +and prints out a piechart in +SVG format. +.P +The input format is simply a list, one entry per line, +starting with a number, followed by a label. +If the number is negative, it is understood to be a subset of the previous non-negative number. +Consecutive negative numbers accumulate. +.P +Lines not starting with a number are ignored. +(Actually they are preserved as comments, but they are not visible in the graphic.) + +.SH OPTIONS +.B piechart +has no options. +This may change in the future. + +.SH EXIT STATUS +No exit status is explicitly defined. + +.SH NOTES +.B piechart +is an +.BR awk (1) +script. +There is also a slightly more elegant +(and more correct) +but regrettably less readable implementation in C. +.P +Currently, +.B piechart +only renders a circular piechart. +Pseudo-3D and shadows are not implemented. + +.SH BUGS +Comment entries are preserved out of order. + +.SH EXAMPLES +.TP +.BI piechart\ data\ |\ display +Render the data in a +.BR display (1) +window. +.TP +.BI piechart\ <\ data\ >\ data.svg +Filter data into a graphics file. + +.SH SEE ALSO +.BR awk (1) |
