const char * UsageLines [] = { "Usage: circletopbm (width) (height)", "Writes unfilled circles to standard output as a PBM image.", "Each standard input line is of the form:", "\t(across1),(down1) (radius) [# (comment) ]", "Topmost row of pixels is considered - (height)/2 down.", "Leftmost column of pixels is considered - (width)/2 across.", "February 25, 2011. Newest is at gopher -p users/julianbr sdf.org", }; const int NumUsageLines = sizeof (UsageLines)/sizeof (UsageLines [0] ); struct Circle { int across, down, radius; struct Circle * next; }; #include <stdlib.h> #include <stdio.h> #include <string.h> void ReadCircles (struct Circle * * CirclesPtr) { struct Circle * * CirclePtr; unsigned long int LineNum; int across, down, radius; int IsEmpty, IsNegative, FoundRadius; char c; LineNum = 0; CirclesPtr [0] = NULL; CirclePtr = CirclesPtr; c = getchar (); while (c != EOF) { LineNum++; IsEmpty = 1; while (c == ' ') c = getchar (); if (c != EOF && c != '\n' && c != '#') IsEmpty = 0; IsNegative = 0; if (c == '-') IsNegative = 1; if (c == '+' || c == '-') c = getchar (); across = 0; while (c >= '0' && c <= '9') { across = 10*across + (c - '0'); c = getchar (); } if (IsNegative) across = - across; if (c == ',') c = getchar (); IsNegative = 0; if (c == '-') IsNegative = 1; if (c == '+' || c == '-') c = getchar (); down = 0; while (c >= '0' && c <= '9') { down = 10*down + (c - '0'); c = getchar (); } if (IsNegative) down = - down; while (c == ' ') c = getchar (); IsNegative = 0; if (c == '-') IsNegative = 1; if (c == '+' || c == '-') c = getchar (); FoundRadius = 0; radius = 0; while (c >= '0' && c <= '9') { FoundRadius = 1; radius = 10*radius + (c - '0'); c = getchar (); } if (IsNegative) radius = - radius; while (c == ' ') c = getchar (); if (c != EOF && c != '\n' && c != '#') { fprintf (stderr, "***circletopbm: Improper"); fprintf (stderr, " '%c'", c); fprintf (stderr, " line %lu\n", LineNum); } else if (!IsEmpty && !FoundRadius) { fprintf (stderr, "***circletopbm: Incomplete"); fprintf (stderr, " data"); fprintf (stderr, " in line #%lu\n", LineNum); } else if (!IsEmpty) { CirclePtr [0] = malloc (sizeof (CirclePtr [0] [0] ) ); if (CirclePtr [0] == NULL) { fprintf (stderr, "***circletopbm: Not"); fprintf (stderr, " enough memory in"); fprintf (stderr, " line #%lu\n", LineNum); } else { CirclePtr [0]->across = across; CirclePtr [0]->down = down; CirclePtr [0]->radius = radius; CirclePtr [0]->next = NULL; CirclePtr = & CirclePtr [0]->next; } } while (c != EOF && c != '\n') c = getchar (); if (c != EOF) c = getchar (); } } void WriteCircles ( int width, int height, struct Circle * Circles) { struct Circle * Circle; int across, down, x, y, temp; int OutputWeight, OutputValue, IsDark, radius2; printf ("P4\n"); printf ("%d %d\n", width, height); for (down = - height/2; down < height - height/2; down++) { OutputWeight = 128; OutputValue = 0; for (across = - width/2; across < width - width/2; across++) { IsDark = 0; Circle = Circles; while (Circle != NULL) { radius2 = Circle->radius*Circle->radius; x = across - Circle->across; y = down - Circle->down; if (x < 0) x = - x; if (y < 0) y = - y; if (x < y) { temp = x; x = y; y = temp; } if ((x*x + y*y <= radius2 && x*x + x + 1 + y*y > radius2) || (x*x + y*y >= radius2 && x*x - x + y*y < radius2) ) IsDark = 1; Circle = Circle->next; } if (IsDark) OutputValue += OutputWeight; OutputWeight /= 2; if (OutputWeight == 0) { putchar (OutputValue); OutputWeight = 128; OutputValue = 0; } } if (OutputWeight < 128) putchar (OutputValue); } } void CloseCircles (struct Circle * Circles) { struct Circle * Circle, * NextCircle; Circle = Circles; while (Circle != NULL) { NextCircle = Circle->next; free (Circle); Circle = NextCircle; } } int main (int argc, char * argv [] ) { struct Circle * Circles; int width, height, i; char c; if (argc < 2) { for (i = 0; i < NumUsageLines; i++) printf ("%s\n", UsageLines [i] ); } else if (argc == 3 && sscanf (argv [1], "%d%c", & width, & c) == 1 && width > 0 && sscanf (argv [2], "%d%c", & height, & c) == 1 && height > 0) { ReadCircles (& Circles); WriteCircles (width, height, Circles); CloseCircles (Circles); } else { fprintf (stderr, "***Usage: circletopbm"); fprintf (stderr, " (width) (height)\n"); } return 0; }