add working unfinished prototype
This commit is contained in:
parent
bf7a7d5069
commit
9e61f3b192
|
@ -1,2 +1,5 @@
|
|||
# crystal
|
||||
|
||||
my implementation of BWinf 41.1 #2 in C.
|
||||
|
||||
accessible at <https://bwinf.de/fileadmin/bundeswettbewerb/41/Bundeswettbewerb_41_Aufgabenblatt_WEB.pdf>.
|
||||
|
|
5
bmp.h
5
bmp.h
|
@ -1,3 +1,6 @@
|
|||
#ifndef __BMP_H__
|
||||
#define __BMP_H__
|
||||
|
||||
#define BPP 3 /* rgb */
|
||||
#define FILE_HEADER_SIZE 14
|
||||
#define INFO_HEADER_SIZE 40
|
||||
|
@ -5,3 +8,5 @@
|
|||
void generate_bitmap(unsigned char* image, int h, int w, char* file_name);
|
||||
unsigned char* create_bitmap_file_header(int height, int stride);
|
||||
unsigned char* create_bitmap_info_header(int height, int width);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* bres.c
|
||||
*
|
||||
* copied from https://de.wikipedia.org/wiki/Diskussion:Bresenham-Algorithmus#kompakt_fehler?
|
||||
**/
|
||||
#include<stdlib.h> /* abs */
|
||||
|
||||
extern int paint_pixel(unsigned int x, unsigned int y, unsigned char clr);
|
||||
|
||||
void line(int x0, int y0, int x1, int y1, unsigned char clr)
|
||||
{
|
||||
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
|
||||
int dy = -abs(y1-y0), sy = y0<y1 ? 1 : -1;
|
||||
int err = dx+dy, e2; /* error value e_xy */
|
||||
|
||||
for(;;){ /* loop */
|
||||
paint_pixel(x0,y0,clr);
|
||||
if (x0==x1 && y0==y1) break;
|
||||
e2 = 2*err;
|
||||
if (e2 > dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */
|
||||
if (e2 < dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */
|
||||
}
|
||||
}
|
273
crystal.c
273
crystal.c
|
@ -8,6 +8,7 @@
|
|||
#include<stdio.h> /* printf; fprintf */
|
||||
#include<stdlib.h> /* atoi; rand; srand */
|
||||
#include<time.h> /* time */
|
||||
#include<math.h> /* lround */
|
||||
|
||||
#include "crystal.h"
|
||||
#include "bmp.h"
|
||||
|
@ -15,19 +16,18 @@
|
|||
/* how many colours, max at 256 */
|
||||
int colors = 256;
|
||||
|
||||
extern void generate_bitmap(unsigned char *image, int h, int w, char *file_name); /* bmp.c */
|
||||
extern void line(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, unsigned char clr); /* bres.c */
|
||||
|
||||
void paint_picture();
|
||||
int paint_pixel(unsigned int x, unsigned int y, unsigned char clr);
|
||||
char new_sprout(unsigned int id);
|
||||
void process(unsigned int id, unsigned int step);
|
||||
void debug();
|
||||
void sift_struct(struct SPROUT s);
|
||||
|
||||
unsigned char image[HEIGHT][WIDTH][BPP];
|
||||
struct SPROUT col[SPROUTS]; /* collection of all created sprouts, unallocated */
|
||||
struct SPROUT col[SPROUTS]; /* collection of all created sprouts */
|
||||
|
||||
/* struct SPROUT *csprt = NULL; /\* pointer to current sprout for quick access *\/ */
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
int main(void)
|
||||
{
|
||||
if(colors<3) colors = 3;
|
||||
if(colors>256) colors=256;
|
||||
|
@ -35,40 +35,41 @@ int main(int argc, char* argv[])
|
|||
char *file_name = (char*) "out.bmp";
|
||||
srand(time(NULL));
|
||||
|
||||
/* allocate ample memory for collection */
|
||||
/* col = malloc(SPROUTS * sizeof(struct SPROUT)); */
|
||||
|
||||
int i;
|
||||
for(i=0; i<SPROUTS; ++i)
|
||||
for(unsigned int i=0; i<SPROUTS; ++i)
|
||||
{
|
||||
char err = new_sprout(i);
|
||||
if(err==1) fprintf(stderr, "sprouting failed for id %d\n", i);
|
||||
}
|
||||
|
||||
debug();
|
||||
|
||||
for(i=0; i<SIMLENGTH; ++i)
|
||||
for(unsigned int i=1; i<=SIMLENGTH; ++i)
|
||||
{
|
||||
for(int j=0; j<SPROUTS; ++j) process(j, i);
|
||||
for(unsigned int j=0; j<SPROUTS; ++j) process(j, i);
|
||||
}
|
||||
|
||||
generate_bitmap((unsigned char*)image, HEIGHT, WIDTH, file_name);
|
||||
printf("done.\n");
|
||||
|
||||
/* free(col); */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char generate_color()
|
||||
{
|
||||
unsigned char clr = rand() % colors;
|
||||
|
||||
clr*=(unsigned char)lround( (256/colors) );
|
||||
|
||||
return clr;
|
||||
}
|
||||
|
||||
char new_sprout(unsigned int id)
|
||||
{
|
||||
unsigned int velocity[] = {1, 1, 1, 1};
|
||||
if(id>=SPROUTS) return 1;
|
||||
|
||||
unsigned int sx = rand() % WIDTH + 1;
|
||||
unsigned int sy = rand() % HEIGHT + 1;
|
||||
unsigned int gclr = rand() % colors;
|
||||
gclr*=(256/colors); /*color limiting*/
|
||||
unsigned int sx = rand() % WIDTH + 1;
|
||||
unsigned int sy = rand() % HEIGHT + 1;
|
||||
/* unsigned int sx = 663; */
|
||||
/* unsigned int sy = 17; */
|
||||
unsigned char gclr = generate_color(); /* color limiting */
|
||||
|
||||
unsigned int coords[] = {sx, sy};
|
||||
|
||||
|
@ -76,132 +77,142 @@ char new_sprout(unsigned int id)
|
|||
s.ID=id;
|
||||
s.c= gclr;
|
||||
|
||||
int i;
|
||||
for(i=0; i<4; ++i){ s.v[i]=velocity[i]; }
|
||||
for(i=0; i<2; ++i){ s.coords[i]= coords[i]; }
|
||||
for(int i=0; i<4; ++i){ s.v[i]=velocity[i]; }
|
||||
|
||||
s.x0 = sx;
|
||||
s.y0 = sy;
|
||||
|
||||
col[id]=s;
|
||||
|
||||
/* if(csprt==NULL){ fprintf(stderr, "sprout for id %d is null, check sprout array.\n", id); return 1; } */
|
||||
|
||||
for(int i=0; i<3; ++i)
|
||||
{
|
||||
printf("x: %d :: y: %d :: i: %d = %d\n", sx, sy, i, gclr);
|
||||
image[sy][sx][i]=gclr;
|
||||
}
|
||||
printf("sprout %d at (%d|%d)\n", id, sx, sy);
|
||||
paint_pixel(sx, sy, gclr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* mode is the cardinal direction from north (0) to west (3) */
|
||||
unsigned int process_calculation(int mode, unsigned int step, struct SPROUT *s/* , int n */)
|
||||
{
|
||||
if(mode>3 || s==NULL) return 0;
|
||||
|
||||
unsigned int velocity = s->v[mode];
|
||||
unsigned int deflection = velocity * step;
|
||||
unsigned int i = 0;
|
||||
|
||||
|
||||
unsigned int x = s->x0;
|
||||
unsigned int y = s->y0;
|
||||
unsigned int z[] = {y, x, y, x}; /* this allows a compact switch statement */
|
||||
unsigned int limits[] = {0, WIDTH, HEIGHT, 0};
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case 0: /* north y→0 */
|
||||
case 3: /* west x→0 */
|
||||
if(deflection > z[mode])
|
||||
{
|
||||
i = 0;
|
||||
s->killswitch = 1;
|
||||
}
|
||||
else
|
||||
i = z[mode] - deflection;
|
||||
|
||||
break;
|
||||
case 1: /* east x→infinity */
|
||||
case 2: /* south y→infinity */
|
||||
i = z[mode] + deflection;
|
||||
if ( i > limits[mode] )
|
||||
{
|
||||
i = limits[mode];
|
||||
s->killswitch = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void process(unsigned int id, unsigned int step)
|
||||
{
|
||||
/* as long as process() is only called from within */
|
||||
/* the for loop in main(), no array-length-check */
|
||||
/* is necessary. */
|
||||
/* if(id>=SPROUTS) */
|
||||
/* { */
|
||||
/* fprintf(stderr, "Cannot process, %d is bigger than SPROUTS max %d\n", id, SPROUTS); */
|
||||
/* return; */
|
||||
/* } */
|
||||
/* The basic idea of this function is to take a sprout, then calculate the outer
|
||||
bounds (4 points) by always calculating the velocity with the current step
|
||||
number (step). Then, the Bresenham algorithm (bres.c) is used to draw a line
|
||||
between the four boundary points.
|
||||
FIRST OF ALL, (id) and (step) need to be checked to their maximal limits
|
||||
(SPROUTS) and (SIMLENGTH), respectively, to avoid hopefully impossible problems.
|
||||
Throw an error to stderr if they appear so that you know.
|
||||
AFTER THAT, you get the sprout through (id), check if it is null, then get the
|
||||
(killswitch) variable. If it is 1, then do not proceed, the sprout is done.
|
||||
SET (killswitch) TO 1 IF [paint_pixel] returns 1, that is, if the sprout’s
|
||||
crystal touches another one. */
|
||||
|
||||
/* (id) needs to be smaller than (SPROUTS) because they are taken from an
|
||||
array which famously start at 0. */
|
||||
if(id>=SPROUTS || step>SIMLENGTH)
|
||||
{
|
||||
fprintf(stderr, "State sprout%d @ %d is bigger than max %d;%d.\n", id, step, SPROUTS, SIMLENGTH);
|
||||
return;
|
||||
}
|
||||
if(col[id].killswitch==1) { /* printf("%d skipped because of killswitch\n", col[id].ID); */ return; }
|
||||
|
||||
struct SPROUT *csprt = &col[id];
|
||||
struct SPROUT *s = &col[id];
|
||||
|
||||
unsigned int bounds[4][1];
|
||||
unsigned int north[2], east[2], south[2], west[2];
|
||||
|
||||
printf("Bounds for %d(%d|%d) are:\n", csprt->ID, csprt->coords[0], csprt->coords[1]);
|
||||
unsigned int rez[] = {0, 0, 0, 0};
|
||||
|
||||
for(int i=0; i<4; ++i) /* north east south west */
|
||||
for(int i=0; i<4; ++i) rez[i] = process_calculation(i, step, s);
|
||||
|
||||
|
||||
north[0] = s->x0;
|
||||
north[1] = rez[0];
|
||||
|
||||
east[0] = rez[1];
|
||||
east[1] = s->y0;
|
||||
|
||||
south[0] = s->x0;
|
||||
south[1] = rez[2];
|
||||
|
||||
west[0] = rez[3];
|
||||
west[1] = s->y0;
|
||||
|
||||
|
||||
paint_pixel(s->x0, north[1], s->c);
|
||||
paint_pixel(east[0], s->y0, s->c);
|
||||
paint_pixel(s->x0, south[1], s->c);
|
||||
paint_pixel(west[0], s->y0, s->c);
|
||||
|
||||
line(west[0], s->y0, s->x0, north[1], s->c);
|
||||
line(s->x0, north[1], east[0], s->y0, s->c);
|
||||
line(east[0], s->y0, s->x0, south[1], s->c);
|
||||
line(s->x0, south[1], west[0], s->y0, s->c);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int check_pixel(unsigned int x, unsigned int y)
|
||||
{
|
||||
/* as the image will be grayscaled, it works to check only one layer */
|
||||
/* this implies the background colour is 0 */
|
||||
if(image[y][x][0]!=0)
|
||||
{
|
||||
unsigned int x, y; /* these are the coordinates which should be filled into image */
|
||||
unsigned int sub;
|
||||
x = csprt->coords[0];
|
||||
y = csprt->coords[1];
|
||||
|
||||
switch(i)
|
||||
{
|
||||
case 0: /* north */
|
||||
sub = ( (csprt->v[i]) * step );
|
||||
|
||||
if(y-sub<=0)
|
||||
{
|
||||
y=0;
|
||||
col[id].killswitch=1; /* prevent this sprout from being processed again */
|
||||
}
|
||||
else y-=sub;
|
||||
|
||||
/* bounds[i][0]=x; */
|
||||
bounds[i][1]=y;
|
||||
break;
|
||||
case 1: /* east */
|
||||
x+=( (csprt->v[i]) * step );
|
||||
|
||||
if(x>WIDTH)
|
||||
{
|
||||
x=WIDTH;
|
||||
col[id].killswitch=1;
|
||||
}
|
||||
|
||||
bounds[i][0]=x;
|
||||
/* bounds[i][1]=y; */
|
||||
break;
|
||||
case 2: /* south */
|
||||
y+=( (csprt->v[i]) * step);
|
||||
|
||||
if(y>HEIGHT)
|
||||
{
|
||||
y=HEIGHT;
|
||||
col[id].killswitch=1;
|
||||
}
|
||||
|
||||
/* bounds[i][0]=x; */
|
||||
bounds[i][1]=y;
|
||||
break;
|
||||
case 3: /* west */
|
||||
sub = ( (csprt->v[i]) * step);
|
||||
|
||||
if(x-sub<=0)
|
||||
{
|
||||
x=0;
|
||||
col[id].killswitch=1;
|
||||
}
|
||||
else x-=sub;
|
||||
|
||||
bounds[i][0]=x;
|
||||
/* bounds[i][1]=y; */
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%d in for loop up to 3\n", i);
|
||||
return;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int paint_pixel(unsigned int x, unsigned int y, unsigned char clr)
|
||||
{
|
||||
if(x>WIDTH || y>HEIGHT)
|
||||
{
|
||||
fprintf(stderr, "coords (%d|%d) exceed image size %d×%d.\n", x, y, WIDTH, HEIGHT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("(%d|%d)\n", bounds[0][0], bounds[3][1]);
|
||||
|
||||
/* for(int i=0; i<4; ++i) */
|
||||
/* { */
|
||||
/* printf("(%d|%d) :: ", bounds[i][0], bounds[i][1]); */
|
||||
/* image[bounds[i][1]][bounds[i][0]][0]=csprt->c; */
|
||||
/* /\* image[bounds[i][1]][bounds[i][0]][1]=csprt->c; *\/ */
|
||||
/* /\* image[bounds[i][1]][bounds[i][0]][2]=csprt->c; *\/ */
|
||||
/* } */
|
||||
printf("\n\n");
|
||||
if(check_pixel(x, y)) return 1;
|
||||
|
||||
/* printf("%d :: %d\n", csprt->ID, csprt->v[2]); */
|
||||
image[y][x][0]=clr;
|
||||
image[y][x][1]=clr;
|
||||
image[y][x][2]=clr;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void debug()
|
||||
{
|
||||
for(int i=0; i<SPROUTS; ++i)sift_struct(col[i]);
|
||||
return;
|
||||
}
|
||||
|
||||
void sift_struct(struct SPROUT s)
|
||||
{
|
||||
printf("%d '%d %d %d %d' %d '%d %d'\n", s.ID, s.v[0], s.v[1], s.v[2], s.v[3], s.c, s.coords[0], s.coords[1]);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
|
24
crystal.h
24
crystal.h
|
@ -4,6 +4,9 @@
|
|||
* EUPL-1.2
|
||||
**/
|
||||
|
||||
#ifndef __CRYSTAL_H__
|
||||
#define __CRYSTAL_H__
|
||||
|
||||
/* for 4k */
|
||||
/* #define WIDTH 3840 */
|
||||
/* #define HEIGHT 2160 */
|
||||
|
@ -12,19 +15,21 @@
|
|||
#define WIDTH 1920
|
||||
#define HEIGHT 1080
|
||||
|
||||
/* 360 p*/
|
||||
/* for 360p*/
|
||||
/* #define WIDTH 480 */
|
||||
/* #define HEIGHT 360 */
|
||||
|
||||
/* #define SPROUTS 50000 /\* recommended for 4k *\/ */
|
||||
/* #define SPROUTS 5000 /\* recommended for fullhd *\/o */
|
||||
/* #define SPROUTS 500 /\* recommended for 360p *\/ */
|
||||
#define SPROUTS 1 /* delete */
|
||||
/* #define SPROUTS 50000 */
|
||||
/* #define SPROUTS 5000 */
|
||||
/* #define SPROUTS 500 */
|
||||
#define SPROUTS 20
|
||||
/* #define SPROUTS 1 */
|
||||
|
||||
/* length of simulation */
|
||||
/* #define SIMLENGTH 10000 */
|
||||
#define SIMLENGTH 500
|
||||
/* #define SIMLENGTH 1 */
|
||||
/* #define SIMLENGTH 20 */
|
||||
|
||||
struct SPROUT
|
||||
{
|
||||
|
@ -33,5 +38,12 @@ struct SPROUT
|
|||
unsigned int ID;
|
||||
unsigned int v[4]; /* velocity in cardinal directions */
|
||||
unsigned char c; /* color */
|
||||
unsigned int coords[2]; /* initial coordinates from which to expand */
|
||||
unsigned int x0; /* initial coordinates of the sprout */
|
||||
unsigned int y0;
|
||||
};
|
||||
|
||||
/* default velocity */
|
||||
/* const int velocity[] = {1, 1, 1, 1}; */
|
||||
const int velocity[] = {20, 20, 20, 20};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue