summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Wührer <def@gmx.at>2026-04-12 16:51:43 +0200
committerDavid Wührer <def@gmx.at>2026-04-12 16:51:43 +0200
commit912b6505f1335a1f9eabf55045b67e38738bdaf3 (patch)
tree519307c46f07dd691f643d2fef6bdf07462414e4
parent6702a32d9fdc0571570c28e9ba381c618d5a622c (diff)
piechartHEADmaster
-rwxr-xr-xbin/piechart105
-rw-r--r--man/man1/piechart.166
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)