diff options
author | David Wührer <def@gmx.at> | 2017-02-19 15:20:12 +0100 |
---|---|---|
committer | David Wührer <def@gmx.at> | 2017-02-19 15:20:12 +0100 |
commit | faf540b146dc7c4a48480673af9a8de56df2e34f (patch) | |
tree | 13d9b5750a3e956c2157f80aaa3cae4d9d441593 |
initial commit
-rw-r--r-- | piechart.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/piechart.c b/piechart.c new file mode 100644 index 0000000..aa52afd --- /dev/null +++ b/piechart.c @@ -0,0 +1,92 @@ +/* + * BUGS: + * adjacient colours could have higher contrast + * negative angles + */ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> + +const float tau=(float)(M_PI*2); + +// draw sector +void draw(float angle, char* label){ + const float r=100; + static float progress=0; + static float overlap=0; + float fangle; if(angle<0)fangle=-angle;else fangle=angle-overlap; + // 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 + float x1=r*cosf(progress); + float y1=r*sinf(progress); + float x2=r*cosf(progress+fangle); + float y2=r*sinf(progress+fangle); + float divider=progress+fangle/2; + unsigned char rr=(unsigned char)(0xff*((divider)/(tau))); + unsigned char gg=(unsigned char)(0xff*((divider-tau/3)/(tau))); + unsigned char bb=(unsigned char)(0xff*((divider-2*tau/3)/(tau))); + printf("<path stroke=\"#000000\" fill=\"#%02x%02x%02x\" d=\"M250,250 L%f,%f A%f,%f 0 %d,%d %f,%f z\"/>",rr,gg,bb,250+x1,250+y1,r,r,(fangle>M_PI),1,250+x2,250+y2); + float xo=250+(3*r/2*cosf(divider)); + float yo=250+(3*r/2*sinf(divider)); + printf("<line stroke=\"#000000\" x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" />",250+(2*r/3*cosf(divider)),250+(2*r/3*sinf(divider)),xo,yo); + printf("<text x=\"%f\" y=\"%f\">%s</text>\n",xo,yo,label); + progress+=fangle; + overlap-=angle; // multiple overlaps accumulate + if(overlap<0)overlap=0; +} +// put preliminary data on the stack +float scan_line (FILE* input, float sum){ + char* line=NULL; size_t len=0; + if(getline(&line,&len,input) != -1){ + { // chomp + char* l=&(line[strlen(line)-1]); + if(*l=='\n')*l='\0'; + } + /* at the very least, we need a true value. + * everything following it can be label or whatever. + * if strtof does not find anything (or the value is miniscule), the line is obviously a comment and should be ignored. + * (if the value is too huge to handle, the output will be meaningless.) + * + * 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. + */ + char* label=line; + float number=strtof(label,&label); + if(number>0){ + sum=scan_line(input,sum+number); + float angle=tau*number/sum; + draw(angle,label); + }else if(number<0){ + sum=scan_line(input,sum); + float angle=tau*number/sum; + draw(angle,label); + }else{ + sum=scan_line(input,sum); + printf("<!-- %s -->\n",label); + } + } + free(line); + return sum; +} + +int main(int argc, char** argv){ + FILE* input=stdin; + // getopts + // print boilerplate + puts("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n\ +<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1/EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n\ +<svg\n\ + xmlns=\"http://www.w3.org/2000/svg\"\n\ + version=\"1.1\"\n\ + width=\"500\"\n\ + height=\"500\"\n\ + viewBox=\"0 0 500 500\"\n\ +>"); + scan_line(input,0); + puts("</svg>"); + return 0; +} |