add working unfinished prototype

This commit is contained in:
Lilith 2023-06-03 23:03:50 +02:00
parent bf7a7d5069
commit 9e61f3b192
Signed by: konomo
GPG Key ID: 3DD7B85531A23133
5 changed files with 191 additions and 137 deletions

View File

@ -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
View File

@ -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

23
bres.c Normal file
View File

@ -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
View File

@ -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 sprouts
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;
}

View File

@ -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