const char * UsageLines [] = {
"Usage: drawpolygons (width) (height)",
"Reads corners of polygons in across, down coordinates, from standard input.",
"Writes a ppm image of specified width and height to standard output.",
"Each nonblank input line must begin with colors r g b followed",
"by across,down for each corner (at least 3 corners to have any effect).",
"The order is front-to-back, meaning a polygon will cover",
"any polygon given in a later line.",
"drawpolygon ignores anything after # to end-of-line.",
"January 4, 2017. Newest is at gopher -p users/julianbr sdf.org",
};
const int NumUsageLines = sizeof (UsageLines)/sizeof (UsageLines [0] );
struct Polygon {
int r, g, b;
struct Corner {
long int across, down;
struct Corner * next;
} * Corners;
struct Polygon * next;
};
int ReadPolygon (struct Polygon * * PolygonPtr, int * EndOfInputPtr)
{
struct Polygon * Polygon;
struct Corner * * CornerPtr, * Corners, * Corner;
int ok, c, IsNegative;
int r, g, b, across, down, Found, FoundB, FoundDown;
ok = 1;
c = getchar ();
while (c == ' ')
c = getchar ();
Found = 0;
Polygon = NULL;
if (c != EOF && c != '\n' && c != '#') {
Found = 1;
PolygonPtr [0] = malloc (sizeof (PolygonPtr [0] [0] ) );
Polygon = PolygonPtr [0];
if (ok && Polygon == NULL) {
fprintf (stderr, "***drawpolygons: Not enough memory");
ok = 0;
}
}
IsNegative = 0;
if (c == '+')
c = getchar ();
else if (c == '-') {
IsNegative = 1;
c = getchar ();
}
r = 0;
while (c >= '0' && c <= '9') {
r = 10*r + (c - '0');
c = getchar ();
}
if (IsNegative)
r = - r;
while (c == ' ')
c = getchar ();
IsNegative = 0;
if (c == '+')
c = getchar ();
else if (c == '-') {
IsNegative = 1;
c = getchar ();
}
g = 0;
while (c >= '0' && c <= '9') {
g = 10*g + (c - '0');
c = getchar ();
}
if (IsNegative)
g = - g;
while (c == ' ')
c = getchar ();
IsNegative = 0;
if (c == '+')
c = getchar ();
else if (c == '-') {
IsNegative = 1;
c = getchar ();
}
FoundB = 0;
b = 0;
while (c >= '0' && c <= '9') {
FoundB = 1;
b = 10*b + (c - '0');
c = getchar ();
}
if (IsNegative)
b = - b;
if (ok && Found && !FoundB) {
fprintf (stderr, "***xyzproject: r g b not found");
ok = 0;
}
Corners = NULL;
CornerPtr = & Corners;
while (c == ' ')
c = getchar ();
while (c == '+' || c == '-' || (c >= '0' && c <= '9') ) {
CornerPtr [0] = malloc (sizeof (CornerPtr [0] [0] ) );
Corner = CornerPtr [0];
if (ok && CornerPtr [0] == NULL) {
fprintf (stderr, "***drawpolygons: Not");
fprintf (stderr, " enough memory");
ok = 0;
}
IsNegative = 0;
if (c == '+')
c = getchar ();
else if (c == '-') {
IsNegative = 1;
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 == '+')
c = getchar ();
else if (c == '-') {
IsNegative = 1;
c = getchar ();
}
FoundDown = 0;
down = 0;
while (c >= '0' && c <= '9') {
FoundDown = 1;
down = 10*down + (c - '0');
c = getchar ();
}
if (IsNegative)
down = - down;
if (c == ',')
c = getchar ();
if (ok && !FoundDown) {
fprintf (stderr, "***drawpolygons: Didn't find across,down");
ok = 0;
}
while (c == ' ')
c = getchar ();
if (Corner != NULL) {
Corner->across = across;
Corner->down = down;
Corner->next = NULL;
CornerPtr = & Corner->next;
}
}
if (ok && c != EOF && c != '\n' && c != '#') {
fprintf (stderr, "***drawpolygons: Found improper");
fprintf (stderr, " '%c'", c);
ok = 0;
}
while (c != EOF && c != '\n')
c = getchar ();
if (Polygon != NULL) {
Polygon->r = r;
Polygon->g = g;
Polygon->b = b;
Polygon->Corners = Corners;
Polygon->next = NULL;
}
PolygonPtr [0] = Polygon;
if (c != '\n')
EndOfInputPtr [0] = 1;
return ok;
}
int ReadPolygons (struct Polygon * * PolygonsPtr)
{
struct Polygon * * PolygonPtr, * Polygon;
int EndOfInput, LineNum, ok;
PolygonPtr = PolygonsPtr;
ok = 1;
LineNum = 0;
EndOfInput = 0 ;
while (!EndOfInput) {
LineNum++;
if (!ReadPolygon (& Polygon, & EndOfInput) ) {
fprintf (stderr, " in line %d.\n", LineNum);
ok = 0;
}
if (Polygon != NULL) {
PolygonPtr [0] = Polygon;
PolygonPtr = & Polygon->next;
}
}
return ok;
}
void DrawPolygons (struct Polygon * Polygons, int width, int height)
{
struct Polygon * Polygon;
struct Corner * Corner;
long int a1, d1, a2, d2, a, d;
int i, j, NumCrossings;
printf ("P6\n");
printf ("%d %d\n", width, height);
printf ("255\n");
for (i = 0; i < height; i++) {
d = i - height/2;
for (j = 0; j < width; j++) {
a = j - width/2;
NumCrossings = 0;
Polygon = Polygons;
while (Polygon != NULL && NumCrossings == 0) {
Corner = Polygon->Corners;
while (Corner != NULL) {
a1 = Corner->across;
d1 = Corner->down;
if (Corner->next == NULL) {
a2 = Polygon->Corners->across;
d2 = Polygon->Corners->down;
}
else {
a2 = Corner->next->across;
d2 = Corner->next->down;
}
if (d1 <= d && d < d2 ) {
if ((a - a1)*(d2 - d1) >= (a2 - a1)*(d - d1) )
NumCrossings++;
}
else if (d1 > d && d >= d2) {
if ((a - a2)*(d1 - d2) >= (a1 - a2)*(d - d2) )
NumCrossings--;
}
Corner = Corner->next;
}
if (NumCrossings != 0) {
putchar (Polygon->r);
putchar (Polygon->g);
putchar (Polygon->b);
}
Polygon = Polygon->next;
}
if (NumCrossings == 0) {
putchar (BackgroundR);
putchar (BackgroundG);
putchar (BackgroundB);
}
}
}
}