/* 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