/* Antibes.c */
/* */
/* Creates a raw image file "Antibes.RAW". */
/* Image width is 1087 pixels, image height is 750 pixels, */
/* with three interleaved colour channels, (RGB, RGB, ...). */
/* Each colour channel is eight bits per pixel giving a total */
/* of 24 bits per pixel. */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
typedef struct tagPIXEL{ /* Pixel information */
int red; /* Red component */
int green; /* Green component */
int blue; /* Blue component */
}PIXEL;
typedef PIXEL *PPIXEL;
typedef struct tagPOLYGON{ /* Polygon information */
float x1; /* First vertex x coordinate */
float y1; /* First vertex y coordinate */
float x2; /* Second vertex x coordinate */
float y2; /* Second vertex y coordinate */
float x3; /* Third vertex x coordinate */
float y3; /* Third vertex y coordinate */
float x4; /* Fourth vertex x coordinate */
float y4; /* Fourth vertex y coordinate */
float a1, b1, c1; /* Line coefficients of first edge */
float a2, b2, c2; /* Line coefficients of second edge */
float a3, b3, c3; /* Line coefficients of third edge */
float a4, b4, c4; /* Line coefficients of fourth edge */
}POLYGON;
typedef POLYGON *PPOLYGON;
static void draw_polygon(float x1, float y1, float x2, float y2,
float x3, float y3, float x4, float y4,
int red, int green, int blue);
static void find_polygon_coeffs(PPOLYGON poly);
static void find_line_coeffs(float x1, float y1, float x2, float y2,
float *a, float *b, float *c);
static int inside_polygon_test(PPOLYGON poly, int x, int y);
PIXEL image[1087][750];
main()
{
int x, y, y1, y2, y3;
unsigned int stime;
FILE *fp;
POLYGON poly;
draw_polygon(0, 749, 0, 0, 1086, 0, 1086, 749, 255, 255, 255);
draw_polygon(137, 736, 169, 383, 942, 452, 948, 641, 189, 240, 255);
draw_polygon(942, 452, 940, 384, 1059, 353, 1024, 458, 255, 255, 0);
draw_polygon(110, 115, 178, 42, 949, 25, 1056, 174, 54, 245, 255);
draw_polygon(192, 99, 161, 87, 410, 87, 193, 99, 105, 105, 105);
draw_polygon(799, 131, 636, 95, 799, 95, 799, 130, 105, 105, 105);
draw_polygon(808, 113, 808, 95, 958, 95, 809, 113, 105, 105, 105);
/* Col de Vence */
draw_polygon(674, 429, -2000, 195, 1086, 195, 1086, 324, 46, 69, 171);
/* Chateau Grimaldi */
draw_polygon(421, 567, 420, 346, 484, 345, 484, 568, 244, 240, 254);
draw_polygon(484, 568, 482, 352, 497, 349, 501, 543, 200, 200, 200);
draw_polygon(427, 631, 427, 568, 429, 568, 429, 631, 255, 255, 255);
/* Flag flutters in the breeze */
stime = (unsigned int) time(NULL)/2;
srand(stime);
y1 = 628 + (int)(10.0 * ((float)rand()/16384.0 - 1.0));
y2 = y1 + (int)(10.0 * ((float)rand()/16384.0 - 1.0));
y3 = y2 + (int)(10.0 * ((float)rand()/16384.0 - 1.0));
draw_polygon(430, 629, 430, 604, 443, y1-25, 443, y1, 0, 0, 255);
draw_polygon(444, y1, 444, y1-25, 457, y2-25, 457, y2, 255, 255, 255);
draw_polygon(458, y2, 458, y2-25, 471, y3-25, 471, y3, 255, 0, 0);
draw_polygon(411, 443, 412, 362, 420, 365, 422, 458, 200, 200, 200);
draw_polygon(278, 448, 278, 322, 412, 328, 412, 441, 220, 234, 225);
/* Terra cotta roofs */
draw_polygon(325, 461, 276, 448, 411, 441, 421, 457, 178, 47, 4);
draw_polygon(184, 527, 178, 355, 257, 357, 257, 527, 232, 242, 245);
draw_polygon(219, 484, 213, 477, 213, 442, 219, 442, 0, 0, 0);
draw_polygon(219, 484, 219, 442, 225, 442, 225, 477, 0, 0, 0);
draw_polygon(241, 441, 235, 315, 250, 315, 253, 405, 200, 200, 200);
draw_polygon(253, 404, 250, 319, 326, 309, 333, 403, 209, 255, 250);
draw_polygon(241, 440, 253, 404, 333, 402, 320, 440, 230, 20, 0);
draw_polygon(160, 351, 161, 299, 269, 290, 269, 356, 255, 204, 247);
draw_polygon(160, 371, 160, 350, 269, 351, 269, 371, 165, 104, 5);
draw_polygon(101, 403, 104, 315, 160, 313, 161, 404, 218, 255, 214);
draw_polygon(100, 369, 100, 308, 120, 330, 117, 384, 255, 255, 255);
draw_polygon(0, 332, 0, 236, 62, 236, 65, 331, 209, 255, 250);
draw_polygon(0, 340, 0, 312, 46, 312, 61, 344, 215, 81, 1);
draw_polygon(54, 369, 50, 248, 98, 245, 100, 369, 255, 224, 250);
draw_polygon(71, 385, 54, 369, 99, 368, 117, 384, 230, 20, 6);
draw_polygon(99, 309, 97, 249, 141, 250, 143, 306, 255, 242, 217);
draw_polygon(120, 331, 99, 307, 142, 306, 158, 330, 202, 67, 2);
draw_polygon(142, 305, 141, 248, 280, 243, 284, 304, 240, 224, 255);
draw_polygon(156, 328, 141, 304, 284, 303, 284, 325, 141, 90, 7);
draw_polygon(396, 370, 391, 245, 456, 242, 456, 321, 255, 227, 237);
draw_polygon(285, 319, 280, 246, 392, 243, 398, 324, 255, 237, 212);
draw_polygon(284, 343, 285, 320, 417, 320, 397, 344, 178, 60, 4);
draw_polygon(446, 397, 411, 371, 461, 331, 502, 361, 120, 190, 120);
draw_polygon(411, 371, 396, 369, 456, 321, 461, 331, 215, 81, 1);
draw_polygon(456, 336, 456, 248, 513, 248, 513, 321, 240, 255, 250);
draw_polygon(594, 328, 594, 264, 660, 264, 660, 318, 255, 204, 247);
draw_polygon(595, 336, 609, 314, 663, 314, 657, 334, 178, 47, 4);
draw_polygon(507, 374, 511, 317, 590, 312, 589, 364, 255, 242, 227);
draw_polygon(548, 352, 549, 329, 562, 329, 563, 351, 0, 0, 0);
draw_polygon(513, 320, 513, 263, 616, 275, 597, 338, 210, 210, 210);
draw_polygon(455, 336, 525, 302, 542, 325, 521, 383, 120, 190, 120);
draw_polygon(504, 388, 502, 368, 592, 363, 567, 384, 165, 104, 5);
draw_polygon(498, 457, 497, 367, 510, 366, 513, 429, 200, 200, 200);
draw_polygon(649, 273, 682, 183, 838, 181, 805, 243, 130, 130, 130);
draw_polygon(430, 253, 441, 170, 684, 181, 650, 284, 140, 140, 140);
draw_polygon(118, 256, 149, 134, 445, 166, 433, 254, 130, 130, 130);
draw_polygon(0, 248, 0, 91, 152, 133, 121, 256, 145, 145, 145);
/* Write the image to file ... upside down */
fp = fopen("Antibes.RAW", "wb");
for (y = 749; y >= 0; y--)
for (x = 0; x < 1087; x++)
{
putc(image[x][y].red, fp);
putc(image[x][y].green, fp);
putc(image[x][y].blue, fp);
}
fclose(fp);
}
static void draw_polygon(float x1, float y1, float x2, float y2,
float x3, float y3, float x4, float y4,
int red, int green, int blue)
{
/* Draw a convex quadrilateral polygon using the vertices */
/* and colour components provided. Vertex ordering is */
/* counter-clockwise. Triangles may be drawn by making two */
/* of the points close but not coincident. */
int x, y;
POLYGON poly;
poly.x1 = x1;
poly.y1 = y1;
poly.x2 = x2;
poly.y2 = y2;
poly.x3 = x3;
poly.y3 = y3;
poly.x4 = x4;
poly.y4 = y4;
find_polygon_coeffs(&poly);
for (y = 0; y < 750; y++)
for (x = 0; x < 1087; x++)
if (inside_polygon_test(&poly, x, y))
{
image[x][y].red = red;
image[x][y].green = green;
image[x][y].blue = blue;
}
}
static void find_polygon_coeffs(PPOLYGON poly)
{
/* Find the coefficients of the implicit line equation */
/* for each of the four sides of the given polygon. */
find_line_coeffs(poly->x1, poly->y1, poly->x2, poly->y2,
&poly->a1, &poly->b1, &poly->c1);
find_line_coeffs(poly->x2, poly->y2, poly->x3, poly->y3,
&poly->a2, &poly->b2, &poly->c2);
find_line_coeffs(poly->x3, poly->y3, poly->x4, poly->y4,
&poly->a3, &poly->b3, &poly->c3);
find_line_coeffs(poly->x4, poly->y4, poly->x1, poly->y1,
&poly->a4, &poly->b4, &poly->c4);
}
static void find_line_coeffs(float x1, float y1, float x2, float y2,
float *a, float *b, float *c)
{
/* For the line connecting (x1, y1) to (x2, y2) determine */
/* the coefficients a, b, and c which satisfy the implicit */
/* line equation ax + by + c = 0 and also satisfy the */
/* constraint a*a + b*b = 1. */
/* This is achieved by calculating "direction cosines" */
/* (see "A Programmer's Geometry", pages 7-9). */
float alpha, beta;
alpha = atan2f(x1-x2, y2-y1);
beta = M_PI_2 - alpha;
*a = cosf(alpha);
*b = cosf(beta);
*c = -(*a * x1) - (*b * y1);
}
static int inside_polygon_test(PPOLYGON poly, int x, int y)
{
/* Determine if the given (x, y) coordinate is inside the */
/* given polygon. */
/* Substitute the (x, y) value into the line equations for the */
/* sides of the polygon. The result will be negative in all */
/* four cases only if the point lies inside the polygon. */
/* (See "Computer Graphics Principles and Practice", pg. 895). */
float test;
test = poly->a1*x + poly->b1*y + poly->c1;
if (test > 0.0001)
return(FALSE);
test = poly->a2*x + poly->b2*y + poly->c2;
if (test > 0.0001)
return(FALSE);
test = poly->a3*x + poly->b3*y + poly->c3;
if (test > 0.0001)
return(FALSE);
test = poly->a4*x + poly->b4*y + poly->c4;
if (test > 0.0001)
return(FALSE);
return(TRUE);
}
Back to Antibes