/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-  */
/*
 * voronoi.c
 * Copyright (C) 2017 drdev <gualtieri@ieee.org>
 * 
 * Voronoi is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Voronoi is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

//Note - Produces some image artifacts when adjacent cell focus points are very close.
//That's a consequence of the iteration.  Works well in other cases.

#include <stdio.h>
#include <time.h>
#include <math.h>

#define size 500
#define num_cells 35

/* Prototypes */
char *strcpy(char *dest, const char *src);
void exit(int status);
void srand(unsigned int seed);
int rand();
double sqrt(double x);
/* end of prototypes */

char fn1[64];
unsigned int image[size][size];
FILE *outdata;

struct cell
{
	 int x,y,x_inc,y_inc;
	 unsigned int color;
 };

struct cell cells[num_cells];
int i,j,k,r,x_start,x_end,y_start,y_end,change_flag;
int change_flag=0;

//palette word is rrggbb.  Unless you expand the palette, the number of cells is limited to 40.
unsigned int palette[40]={0x000000,0x0000AA,0x00AA00,0x00AAAA,0xAA0000,0xAA00AA,0xAA5500,0xAAAAAA,
0x555555,0x5555FF,0x55FF55,0x55FFFF,0xFF5555,0xFF55FF,0xFFFF55,0xF7F7F7,
0x000000,0x0000AA,0x00AA00,0x00AAAA,0xAA0000,0xAA00AA,0xAA5500,0xAAAAAA,
0x555555,0x5555FF,0x55FF55,0x55FFFF,0xFF5555,0xFF55FF,0xFFFF55,0xF7F7F7,
0x11DD33,0x2233CC,0xBB4455,0x550066,0x775566,0x667788,0x887799,0x8899AA,};

//coordinates of simple cubic grid to generate hexagonal cells
int grid_x[35] = {83, 167, 250, 333, 416, 42, 125, 207, 290, 373, 83, 167,
	250, 333, 416,42, 125, 207, 290, 373, 83, 167, 250, 333, 416, 42, 125,
	207, 290, 373, 83, 167, 250, 333, 416};
int grid_y[35] = {57, 57, 57, 57, 57, 113, 113, 113, 113, 113, 170, 170,
	170, 170, 170, 227, 227, 227, 227, 227, 283, 283, 283, 283, 283, 340,
	340, 340, 340, 340, 397, 397, 397, 397, 397};

int random_position(int limit)
{
//returns a random position from 0 to limit
return(rand() % limit);
}

double ds(double dx, double dy)
{
//vector distance
return sqrt((dx*dx)+(dy*dy));
}

int main(int argc, char *argv[])
{

if (argc<2)
{
strcpy(fn1,"output.tga");
}
else
{
strcpy(fn1,argv[1]);
}

printf("\nOutput file selected = %s\n",fn1);

if ((outdata = fopen(fn1,"w"))==NULL)
	{printf ("\nOutput file cannot be opened.\n");
	exit (1);}

srand(time(NULL));

//initialize image array to all white
for (i=0;i<size;i++)
{
for (j=0;j<size;j++)
{
image[i][j] = 0xFFFFFF;
}
}

/*
//initialize cell data for simple cubic grid to generate hexagonal cells
//Note - num_cells must be set to 35
for (i=0;i<num_cells;i++)
{
cells[i].x = grid_x[i];
cells[i].y = grid_y[i];
cells[i].x_inc=0;
cells[i].y_inc=0;
cells[i].color=palette[i];
}
*/


//initialize cell data for random cell center
for (i=0;i<num_cells;i++)
{
cells[i].x = random_position(size);
cells[i].y = random_position(size);
cells[i].x_inc=0;
cells[i].y_inc=0;
cells[i].color=palette[i];
}


//cycle through cells and expand cell areas
for(k=0;k<250;k++)
{
change_flag=0;
for (r=0;r<num_cells;r++)
{
 //watch out for image boundaries
cells[r].x_inc++;
cells[r].y_inc++;
x_start=cells[r].x-cells[r].x_inc;
if(x_start<0){x_start=0;}
x_end=cells[r].x+cells[r].x_inc;
if(x_end>(size-1)){x_end=(size-1);}
for (i=x_start;i<=x_end;i++)
{
y_start=cells[r].y-cells[r].y_inc;
if(y_start<0){y_start=0;}
y_end=cells[r].y+cells[r].y_inc;
if(y_end>(size-1)){y_end=(size-1);}
//printf("%d\t%d\t",y_start,y_end);
for (j=y_start;j<=y_end;j++)
{
if (((image[i][j]==0xFFFFFF))&&(ds((i-cells[r].x),(j-cells[r].y))<=k))
{
image[i][j]=cells[r].color;
change_flag=1;
}
}
}

}
if(change_flag==0)
{
	printf("\nCompleted after %d loops.\n",k);
	break;
}
}

//mark cell centers
for (r=0;r<num_cells;r++)
{
cells[r].x_inc=0;
cells[r].y_inc=0;
}

for(k=0;k<2;k++)
{
for (r=0;r<1+num_cells;r++)
{
 //watch out for image boundaries
cells[r].x_inc++;
cells[r].y_inc++;
x_start=cells[r].x-cells[r].x_inc;
if(x_start<0){x_start=0;}
x_end=cells[r].x+cells[r].x_inc;
if(x_end>(size-1)){x_end=(size-1);}
for (i=x_start;i<=x_end;i++)
{
y_start=cells[r].y-cells[r].y_inc;
if(y_start<0){y_start=0;}
y_end=cells[r].y+cells[r].y_inc;
if(y_end>(size-1)){y_end=(size-1);}
for (j=y_start;j<=y_end;j++)
{
image[i][j]=(cells[r].color ^ (unsigned int)0xFFFFFF); //complementary color
}
}

}
}


//tga file header, written one byte at a time to prevent a
//multitude of problems, including endianess and alighment
//of variables on word boundaries.
putc(0,outdata);
putc(0,outdata);
putc(2,outdata); //uncompressed RGB file
putc(0,outdata);
putc(0,outdata);
putc(0,outdata);
putc(0,outdata);
putc(0,outdata);
putc(0,outdata);  //x origin
putc(0,outdata);
putc(0,outdata);  //y origin
putc(0,outdata);
putc((size & 0x00FF),outdata); //width low byte
putc((size & 0xFF00)/0xFF,outdata); //width high byte
putc((size & 0x00FF),outdata); //height low byte
putc((size & 0xFF00)/0xFF,outdata); //height high byte
putc(24,outdata);  //tga file is a 24 bit bitmap
putc(0,outdata);

//write image data
for (i=0;i<size;i++)
{
for (j=0;j<size;j++)
{
//color data is written as follows: red byte, green byte, blue byte
putc((image[i][j] & 0x0000FF),outdata);
putc((image[i][j] & 0x00FF00)/256,outdata);
putc((image[i][j] & 0xFF0000)/0xFFFF,outdata);
}
}

fclose(outdata);
printf("\nDone.\n");


	return (0);
}

