proclib/ktkMap.c

468 lines
13 KiB
C

#include "ktkMap.h"
#include <stdlib.h> // malloc
#include <stdio.h> // printf, remove
#include <math.h> // round
/* ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
const declarations, etc.
```````````````````````````````` */
const struct ktkMap ktk_MAP_DEFAULT = {
0,
0, 0,
0, 0,
NULL
};
const struct ktkCell ktk_CELL_DEFAULT = {
0, 0, // id_1, id_2
NULL, 0, ktk_CELL_EMPTY|ktk_CELL_CELL_DELETE, // data, size, flags
NULL, 0 // contained cell(s), count of contained
};
/* ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Functions
```````````````````````````````` */
/*int ktk_resizeMap(struct ktkMap *map, int w, int h) {
int x, y;
int delta_w = w - map->w;
int delta_h = h - map->h;
if (w < 0 || h < 0) return 1;
// delete out of bound cells.
if (delta_w < 0) {
for (x = map->w-1; x > w; x--) {
for (y = map->h-1; y > h; y--) {
ktk_deleteCell(&map->cell[x][y]);
}
}
}
if (delta_h < 0) {
for (y = map->h-1; y > h; y--) {
for (x = map->w-1; x > w; x--) {
ktk_deleteCell(&map->cell[x][y]);
}
}
}
// free out of bound cells
for (x = w; x < map->w; x++) {
free(map->cell[x]);
}
// resize :)
if ((map->cell = realloc(map->cell, w * sizeof(struct ktkCell*))) != NULL) {
if (delta_w > 0) {
for (x = map->w; x < w; x++) {
if ((map->cell[x] = malloc(h * sizeof(struct ktkCell))) == NULL) {
// uhoh, ran out of memory. Report error, but set width to as far as we got
w = x;
int xf = x;
for (xf = x; xf > 0; xf--) {
free(map->cell[xf]);
}
break;
}
}
}
} else {
// major problem, couldn't realloc at all. Cancel operation. :S
// TODO: set error code?
return 2;
}
// realloc old x pointers if height has grown
if (delta_h > 0) {
for (x = 0; x < w; x++) { // laziness
if ((map->cell[x] = realloc(map->cell[x], h * sizeof(struct ktkCell))) == NULL) {
// MORE REPORTING ERRORS
}
}
}
// initialize new cells
if (delta_w > 0) {
for (x = map->w; x < w; x++) {
for (y = map->h; y < h; y++) {
map->cell[x][y] = ktk_CELL_DEFAULT;
}
}
}
if (delta_h > 0) {
for (y = map->h; y < h; y++) {
for (x = 0; x < w; x++) {
map->cell[x][y] = ktk_CELL_DEFAULT;
}
}
}
map->w = w;
map->h = h;
// okay!
return 0;
}*/
int ktk_resizeMap(struct ktkMap *map, int w, int h) {
if (w < map->w) {
int i;
for (i = w; i < map->w; i++) {
int j;
for (j = 0; j < map->h; j++) {
ktk_deleteCell(&(map->cell[i][j]));
}
}
}
if (h < map->h) {
int i;
for (i = 0; i < map->w; i++) {
int j;
for (j = h; j < map->h; j++) {
ktk_deleteCell(&(map->cell[i][j]));
}
}
}
map->cell = realloc(map->cell, w * sizeof(struct ktkCell*));
int i;
for (i = map->w; i < w; i++) {
map->cell[i] = NULL;
}
for (i = 0; i < w; i++) {
map->cell[i] = realloc(map->cell[i], h * sizeof(struct ktkCell));
int j;
for (j = 0; j < h; j++) {
//ktk_copyCell(&ktk_CELL_DEFAULT, &(map->cell[i][j]));
if (i >= map->w) {
map->cell[i][j] = ktk_CELL_DEFAULT;
} else {
if (j >= map->h) {
map->cell[i][j] = ktk_CELL_DEFAULT;
}
}
}
}
map->w = w;
map->h = h;
return 0;
}
int ktk_copyMap(struct ktkMap *map_1, struct ktkMap *map_2) {
int x, y;
ktk_deleteMap(map_2);
map_2->flags = map_1->flags;
map_2->x = map_1->x;
map_2->y = map_1->y;
ktk_resizeMap(map_2, map_1->w, map_1->h);
for (x = 0; x < map_1->w; x++) {
for (y = 0; y< map_1->h; y++) {
ktk_copyCell(&map_1->cell[x][y], &map_2->cell[x][y]);
}
}
return 0;
}
int ktk_mergeMaps(struct ktkMap *map_1, struct ktkMap *map_2) {
int max_x = map_2->x + map_2->w;
int max_y = map_2->y + map_2->h;
if (map_1->flags & ktk_MAP_RESIZE) {
if (max_x >= map_1->w) {
ktk_resizeMap(map_1, max_x, map_1->h);
}
if (max_y >= map_1->h) {
ktk_resizeMap(map_1, map_1->w, max_y);
}
}
int x, y;
for (x = 0; x < map_2->w; x++) {
if (map_2->x+x >= map_1->w || map_2->x+x < 0) continue;
for (y = 0; y < map_2->h; y++) {
if (map_2->y+y >= map_1->h || map_2->y+y < 0) continue;
if (map_2->cell[x][y].flags & ktk_CELL_EMPTY) continue;
// TODO: don't delete, but append
ktk_deleteCell(&(map_1->cell[map_2->x+x][map_2->y+y]));
ktk_copyCell(&(map_2->cell[x][y]), &(map_1->cell[map_2->x+x][map_2->y+y]));
}
}
return 0;
}
int ktk_deleteMap(struct ktkMap *map) {
int x, y;
for (x = 0; x < map->w; x++) {
for (y = 0; y < map->h; y++) {
ktk_deleteCell(&map->cell[x][y]);
}
free(map->cell[x]);
}
free(map->cell);
map->w = 0;
map->h = 0;
map->cell = NULL;
return 0;
}
int ktk_checkMapOverlap(struct ktkMap *map_1, struct ktkMap *map_2) {
int x, y;
for (x = 0; x < map_2->w; x++) {
if (map_2->x+x >= map_1->w || map_2->x+x < 0) continue;
for (y = 0; y < map_2->h; y++) {
if (map_2->y+y >= map_1->h || map_2->y+y < 0) continue;
//printf("%dx%d(%d|%d) vs %dx%d(%d|%d)\n", x, y, map_2->cell[x][y].id_1, map_2->cell[x][y].flags, map_2->x+x, map_2->y+y, map_1->cell[map_2->x+x][map_2->y+y].id_1, map_1->cell[map_2->x+x][map_2->y+y].flags);
//printf("%d (%d)\n", map_2->cell[x][y].flags & ktk_CELL_EMPTY, ktk_CELL_EMPTY);
//printf("%d (%d)\n", map_1->cell[map_2->x+x][map_2->y+y].flags & ktk_CELL_EMPTY, ktk_CELL_EMPTY);
if (map_2->cell[x][y].flags & ktk_CELL_EMPTY) continue;
if (map_1->cell[map_2->x+x][map_2->y+y].flags & ktk_CELL_EMPTY) continue;
return 1;
}
}
return 0;
}
int ktk_unsetMapCell(struct ktkMap *map, int x, int y) {
if (x < 0 || x > map->w) return 1;
if (y < 0 || y > map->h) return 1;
map->cell[x][y].flags |= ktk_CELL_EMPTY;
return 0;
}
int ktk_setMapCell(struct ktkMap *map, int x, int y) {
if (x < 0 || x >= map->w) return 1;
if (y < 0 || y >= map->h) return 1;
map->cell[x][y].flags &= ~ktk_CELL_EMPTY;
return 0;
}
struct ktkMap *ktk_borderCells(struct ktkMap *map, struct ktkMap *new_map) {
ktk_resizeMap(new_map, map->w, map->h);
int x = map->x, y = map->y;
for (x = 0; x < map->w; x++) {
for (y = 0; y < map->h; y++) {
if (map->cell[x][y].flags & ktk_CELL_EMPTY) continue;
// l
if (x-1 >= 0 && x < map->w) {
if (map->cell[x-1][y].flags & ktk_CELL_EMPTY) {
// new_map->cell[x-1][y].flags &= !ktk_CELL_EMPTY;
new_map->cell[x][y].flags &= !ktk_CELL_EMPTY;
}
} else {
new_map->cell[x][y].flags &= !ktk_CELL_EMPTY;
}
// r
if (x+1 < map->w) {
if (map->cell[x+1][y].flags & ktk_CELL_EMPTY) {
//new_map->cell[x+1][y].flags &= !ktk_CELL_EMPTY;
new_map->cell[x][y].flags &= !ktk_CELL_EMPTY;
}
} else {
new_map->cell[x][y].flags &= !ktk_CELL_EMPTY;
}
// u
if (y-1 >= 0) {
if (map->cell[x][y-1].flags & ktk_CELL_EMPTY) {
new_map->cell[x][y].flags &= !ktk_CELL_EMPTY;
//new_map->cell[x][y-1].flags &= !ktk_CELL_EMPTY;
}
// ul
if (x-1 >= 0) {
if (map->cell[x-1][y-1].flags & ktk_CELL_EMPTY) {
//new_map->cell[x+1][y].flags &= !ktk_CELL_EMPTY;
new_map->cell[x][y].flags &= !ktk_CELL_EMPTY;
}
}
// ur
if (x+1 < map->w) {
if (map->cell[x+1][y-1].flags & ktk_CELL_EMPTY) {
//new_map->cell[x+1][y].flags &= !ktk_CELL_EMPTY;
new_map->cell[x][y].flags &= !ktk_CELL_EMPTY;
}
}
} else {
new_map->cell[x][y].flags &= !ktk_CELL_EMPTY;
}
// d
if (y+1 < map->h) {
if (map->cell[x][y+1].flags & ktk_CELL_EMPTY) {
new_map->cell[x][y].flags &= !ktk_CELL_EMPTY;
//new_map->cell[x][y+1].flags &= !ktk_CELL_EMPTY;
}
// dl
if (x-1 >= 0) {
if (map->cell[x-1][y+1].flags & ktk_CELL_EMPTY) {
//new_map->cell[x+1][y].flags &= !ktk_CELL_EMPTY;
new_map->cell[x][y].flags &= !ktk_CELL_EMPTY;
}
}
// dr
if (x+1 < map->w) {
if (map->cell[x+1][y+1].flags & ktk_CELL_EMPTY) {
//new_map->cell[x+1][y].flags &= !ktk_CELL_EMPTY;
new_map->cell[x][y].flags &= !ktk_CELL_EMPTY;
}
}
} else {
new_map->cell[x][y].flags &= !ktk_CELL_EMPTY;
}
// ul
// ur
}
}
return new_map;
}
int ktk_fillRect(struct ktkMap *map, int o_x, int o_y, int s_x, int s_y) {
int x, y;
for (x = 0; x < s_x; x++) {
for (y = 0; y < s_y; y++) {
ktk_setMapCell(map, o_x+x, o_y+y);
}
}
return 0;
}
int ktk_fillEllipseBorder(struct ktkMap *map, int r_x, int r_y) {
int y = 0;
int x = 0;
float a, b;
r_x /= 2;
r_y /= 2;
int hw = r_x;
int hh = r_y;
int o_x = 0;
int o_y = 0;
a = (r_y*r_y) - (r_x * r_x * r_y) + (r_x * r_x) / 4;
while ((2.0 * r_y * r_y * x) <= (2.0 * r_x * r_x * y)) {
x++;
if (a <= 0) {
a = a + (2.0f * r_y * r_y * x) + (r_y * r_y);
} else {
y--;
a = a + (2.0f * r_y * r_y * x) - (2.0f * r_x * r_x * y) + (r_y * r_y);
}
ktk_setMapCell(map, o_x+x, o_y+y);
ktk_setMapCell(map, o_x-x, o_y+y);
ktk_setMapCell(map, o_x+x, o_y-y);
ktk_setMapCell(map, o_x-x, o_y-y);
x = -x;
ktk_setMapCell(map, o_x+x, o_y+y);
ktk_setMapCell(map, o_x-x, o_y+y);
ktk_setMapCell(map, o_x+x, o_y-y);
ktk_setMapCell(map, o_x-x, o_y-y);
x = -x;
}
x = r_x;
y = 0;
ktk_setMapCell(map, o_x+x, o_y+y);
ktk_setMapCell(map, o_x-x, o_y+y);
ktk_setMapCell(map, o_x+x, o_y-y);
ktk_setMapCell(map, o_x-x, o_y-y);
b = (r_x * r_x) + 2.0f * (r_y * r_y * r_x) + (r_y * r_y)/4;
while ((2.0f * r_y * r_y * x) > (2.0f * r_x * r_x * y)) {
y++;
if (b > 0) {
b = b + (r_x * r_x) - (2.0 * r_x * r_x * y);
} else {
x--;
b = b + (2.0f * r_y * r_y * x) - (2.0f * r_x * r_x * y) + (r_x * r_x);
}
ktk_setMapCell(map, o_x+x, o_y+y);
ktk_setMapCell(map, o_x-x, o_y+y);
ktk_setMapCell(map, o_x+x, o_y-y);
ktk_setMapCell(map, o_x-x, o_y-y);
y = -y;
ktk_setMapCell(map, o_x+x, o_y+y);
ktk_setMapCell(map, o_x-x, o_y+y);
ktk_setMapCell(map, o_x+x, o_y-y);
ktk_setMapCell(map, o_x-x, o_y-y);
y = -y;
}
return 0;
}
int ktk_fillEllipse(struct ktkMap *map, int o_x, int o_y, int r_x, int r_y) {
int y;
int x;
int hw = r_x/2;
int hh = r_y/2;
for (y = -hh; y <= hh; y++) {
for (x = -hw; x <= hw; x++) {
double dx = (double)x / (double)hw;
double dy = (double)y / (double)hh;
if (dx*dx+dy*dy <= 1) {
//if(x < 0 || x > r_x || y < 0 || y > r_y) continue;
//printf("%dx%d\n", hw+x, hh+y);
ktk_setMapCell(map, hw+o_x+x, hh+o_y+y);
}
}
}
return 0;
}
int ktk_fillCircle(struct ktkMap *map, int radius) {
int h = radius/2;
int x, y;
for (x = h-radius; x <= h+radius; x++) {
for(y = h-radius; y <= h+radius; y++) {
if ((x*x)+(y*y) < (radius*radius)) {
if(x < 0 || x > map->x || y < 0 || y > map->y) continue;
ktk_setMapCell(map, x, y);
}
}
}
return 0;
}
int ktk_drawLine(struct ktkMap *map, int x1, int y1, int x2, int y2) {
int x, y;
if (y2-y1 < x2-x1) {
for (x = x1; x <= x2; x++) {
y = y1 + ((y2-y1)/(x2-x1)) * (x-x1);
ktk_setMapCell(map, x, y);
}
} else {
for (y = y1; y <= y2; y++) {
x = x1 + ((x2-x1)/(y2-y1)) * (y-y1);
ktk_setMapCell(map, x, y);
}
}
return 0;
}
void ktk_printMap(struct ktkMap *map) {
int x, y;
for (y = 0; y < map->h; y++) {
printf("---\n");
for (x = 0; x < map->w; x++) {
printf("%d:%d ", map->cell[x][y].id_1, map->cell[x][y].id_2);
}
printf("\n");
}
}
int ktk_deleteCell(struct ktkCell *cell) {
if (cell->flags & ktk_CELL_DATA_FREE && cell->data != NULL) {
free(cell->data);
cell->data_size = 0;
cell->data = NULL;
}
if (cell->flags & ktk_CELL_CELL_DELETE && cell->cell != NULL) {
int z;
for (z = 0; z < cell->cell_count; z++) {
ktk_deleteCell(&(cell->cell[z]));
}
free(cell->cell);
cell->cell = NULL;
cell->cell_count = 0;
}
cell->flags = cell->flags & ~ktk_CELL_EMPTY;
return 0;
}
int ktk_copyCell(struct ktkCell *cell_1, struct ktkCell *cell_2) {
*cell_2 = *cell_1;
if (cell_1->data != NULL) {
cell_2->data = malloc(cell_1->data_size);
memcpy(cell_2->data, cell_1->data, cell_1->data_size);
}
if (cell_1->cell != NULL) {
int i;
cell_2->cell = malloc(sizeof(struct ktkCell)*cell_1->cell_count);
for (i = 0; i < cell_1->cell_count; i++) {
ktk_copyCell(&cell_1->cell[i], &cell_2->cell[i]);
}
}
return 0;
}