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;
};
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;