You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
363 lines
9.1 KiB
363 lines
9.1 KiB
#define STB_CONNECTED_COMPONENTS_IMPLEMENTATION |
|
#define STBCC_GRID_COUNT_X_LOG2 10 |
|
#define STBCC_GRID_COUNT_Y_LOG2 10 |
|
#include "stb_connected_components.h" |
|
|
|
#ifdef GRID_TEST |
|
|
|
#include <windows.h> |
|
#include <stdio.h> |
|
#include <direct.h> |
|
|
|
//#define STB_DEFINE |
|
#include "stb.h" |
|
|
|
//#define STB_IMAGE_IMPLEMENTATION |
|
#include "stb_image.h" |
|
|
|
//#define STB_IMAGE_WRITE_IMPLEMENTATION |
|
#include "stb_image_write.h" |
|
|
|
typedef struct |
|
{ |
|
uint16 x,y; |
|
} point; |
|
|
|
point leader[1024][1024]; |
|
uint32 color[1024][1024]; |
|
|
|
point find(int x, int y) |
|
{ |
|
point p,q; |
|
p = leader[y][x]; |
|
if (p.x == x && p.y == y) |
|
return p; |
|
q = find(p.x, p.y); |
|
leader[y][x] = q; |
|
return q; |
|
} |
|
|
|
void onion(int x1, int y1, int x2, int y2) |
|
{ |
|
point p = find(x1,y1); |
|
point q = find(x2,y2); |
|
|
|
if (p.x == q.x && p.y == q.y) |
|
return; |
|
|
|
leader[p.y][p.x] = q; |
|
} |
|
|
|
void reference(uint8 *map, int w, int h) |
|
{ |
|
int i,j; |
|
|
|
for (j=0; j < h; ++j) { |
|
for (i=0; i < w; ++i) { |
|
leader[j][i].x = i; |
|
leader[j][i].y = j; |
|
} |
|
} |
|
|
|
for (j=1; j < h-1; ++j) { |
|
for (i=1; i < w-1; ++i) { |
|
if (map[j*w+i] == 255) { |
|
if (map[(j+1)*w+i] == 255) onion(i,j, i,j+1); |
|
if (map[(j)*w+i+1] == 255) onion(i,j, i+1,j); |
|
} |
|
} |
|
} |
|
|
|
for (j=0; j < h; ++j) { |
|
for (i=0; i < w; ++i) { |
|
uint32 c = 0xff000000; |
|
if (leader[j][i].x == i && leader[j][i].y == j) { |
|
if (map[j*w+i] == 255) |
|
c = stb_randLCG() | 0xff404040; |
|
} |
|
color[j][i] = c; |
|
} |
|
} |
|
|
|
for (j=0; j < h; ++j) { |
|
for (i=0; i < w; ++i) { |
|
if (leader[j][i].x != i || leader[j][i].y != j) { |
|
point p = find(i,j); |
|
color[j][i] = color[p.y][p.x]; |
|
} |
|
} |
|
} |
|
} |
|
|
|
void write_map(stbcc_grid *g, int w, int h, char *filename) |
|
{ |
|
int i,j; |
|
for (j=0; j < h; ++j) { |
|
for (i=0; i < w; ++i) { |
|
unsigned int c; |
|
c = stbcc_get_unique_id(g,i,j); |
|
c = stb_rehash_improved(c)&0xffffff; |
|
if (c == STBCC_NULL_UNIQUE_ID) |
|
c = 0xff000000; |
|
else |
|
c = (~c)^0x555555; |
|
if (i % 32 == 0 || j %32 == 0) { |
|
int r = (c >> 16) & 255; |
|
int g = (c >> 8) & 255; |
|
int b = c & 255; |
|
r = (r+130)/2; |
|
g = (g+130)/2; |
|
b = (b+130)/2; |
|
c = 0xff000000 + (r<<16) + (g<<8) + b; |
|
} |
|
color[j][i] = c; |
|
} |
|
} |
|
stbi_write_png(filename, w, h, 4, color, 4*w); |
|
} |
|
|
|
void test_connected(stbcc_grid *g) |
|
{ |
|
int n = stbcc_query_grid_node_connection(g, 512, 90, 512, 871); |
|
//printf("%d ", n); |
|
} |
|
|
|
static char *message; |
|
LARGE_INTEGER start; |
|
|
|
void start_timer(char *s) |
|
{ |
|
message = s; |
|
QueryPerformanceCounter(&start); |
|
} |
|
|
|
void end_timer(void) |
|
{ |
|
LARGE_INTEGER end, freq; |
|
double tm; |
|
|
|
QueryPerformanceCounter(&end); |
|
QueryPerformanceFrequency(&freq); |
|
|
|
tm = (end.QuadPart - start.QuadPart) / (double) freq.QuadPart; |
|
printf("%6.4lf ms: %s\n", tm * 1000, message); |
|
} |
|
|
|
extern void quicktest(void); |
|
|
|
int loc[5000][2]; |
|
int main(int argc, char **argv) |
|
{ |
|
stbcc_grid *g; |
|
|
|
int w,h, i,j,k=0, count=0, r; |
|
uint8 *map = stbi_load("data/map_03.png", &w, &h, 0, 1); |
|
|
|
assert(map); |
|
quicktest(); |
|
|
|
for (j=0; j < h; ++j) |
|
for (i=0; i < w; ++i) |
|
map[j*w+i] = ~map[j*w+i]; |
|
|
|
for (i=0; i < w; ++i) |
|
for (j=0; j < h; ++j) |
|
//map[j*w+i] = (((i+1) ^ (j+1)) >> 1) & 1 ? 255 : 0; |
|
map[j*w+i] = stb_max(abs(i-w/2),abs(j-h/2)) & 1 ? 255 : 0; |
|
//map[j*w+i] = (((i ^ j) >> 5) ^ (i ^ j)) & 1 ? 255 : 0; |
|
//map[j*w+i] = stb_rand() & 1 ? 255 : 0; |
|
|
|
#if 1 |
|
for (i=0; i < 100000; ++i) |
|
map[(stb_rand()%h)*w + stb_rand()%w] ^= 255; |
|
#endif |
|
|
|
_mkdir("tests/output/stbcc"); |
|
|
|
stbi_write_png("tests/output/stbcc/reference.png", w, h, 1, map, 0); |
|
|
|
//reference(map, w, h); |
|
|
|
g = malloc(stbcc_grid_sizeof()); |
|
printf("Size: %d\n", stbcc_grid_sizeof()); |
|
|
|
#if 0 |
|
memset(map, 0, w*h); |
|
stbcc_init_grid(g, map, w, h); |
|
{ |
|
int n; |
|
char **s = stb_stringfile("c:/x/clockwork_update.txt", &n); |
|
write_map(g, w, h, "tests/output/stbcc/base.png"); |
|
for (i=1; i < n; i += 1) { |
|
int x,y,t; |
|
sscanf(s[i], "%d %d %d", &x, &y, &t); |
|
if (i == 571678) |
|
write_map(g, w, h, stb_sprintf("tests/output/stbcc/clockwork_good.png", i)); |
|
stbcc_update_grid(g, x, y, t); |
|
if (i == 571678) |
|
write_map(g, w, h, stb_sprintf("tests/output/stbcc/clockwork_bad.png", i)); |
|
//if (i > 571648 && i <= 571712) |
|
//write_map(g, w, h, stb_sprintf("tests/output/stbcc/clockwork_%06d.png", i)); |
|
} |
|
write_map(g, w, h, stb_sprintf("tests/output/stbcc/clockwork_%06d.png", i-1)); |
|
} |
|
return 0; |
|
#endif |
|
|
|
|
|
start_timer("init"); |
|
stbcc_init_grid(g, map, w, h); |
|
end_timer(); |
|
//g = stb_file("c:/x/clockwork_path.bin", 0); |
|
write_map(g, w, h, "tests/output/stbcc/base.png"); |
|
|
|
for (i=0; i < 5000;) { |
|
loc[i][0] = stb_rand() % w; |
|
loc[i][1] = stb_rand() % h; |
|
if (stbcc_query_grid_open(g, loc[i][0], loc[i][1])) |
|
++i; |
|
} |
|
|
|
r = 0; |
|
start_timer("reachable"); |
|
for (i=0; i < 2000; ++i) { |
|
for (j=0; j < 2000; ++j) { |
|
int x1 = loc[i][0], y1 = loc[i][1]; |
|
int x2 = loc[2000+j][0], y2 = loc[2000+j][1]; |
|
r += stbcc_query_grid_node_connection(g, x1,y1, x2,y2); |
|
} |
|
} |
|
end_timer(); |
|
printf("%d reachable\n", r); |
|
|
|
printf("Cluster size: %d,%d\n", STBCC__CLUSTER_SIZE_X, STBCC__CLUSTER_SIZE_Y); |
|
|
|
#if 1 |
|
for (j=0; j < 10; ++j) { |
|
for (i=0; i < 5000; ++i) { |
|
loc[i][0] = stb_rand() % w; |
|
loc[i][1] = stb_rand() % h; |
|
} |
|
start_timer("updating 2500"); |
|
for (i=0; i < 2500; ++i) { |
|
if (stbcc_query_grid_open(g, loc[i][0], loc[i][1])) |
|
stbcc_update_grid(g, loc[i][0], loc[i][1], 1); |
|
else |
|
stbcc_update_grid(g, loc[i][0], loc[i][1], 0); |
|
} |
|
end_timer(); |
|
write_map(g, w, h, stb_sprintf("tests/output/stbcc/update_random_%d.png", j*i)); |
|
} |
|
#endif |
|
|
|
#if 0 |
|
start_timer("removing"); |
|
count = 0; |
|
for (i=0; i < 1800; ++i) { |
|
int x,y,a,b; |
|
x = stb_rand() % (w-32); |
|
y = stb_rand() % (h-32); |
|
|
|
if (i & 1) { |
|
for (a=0; a < 32; ++a) |
|
for (b=0; b < 1; ++b) |
|
if (stbcc_query_grid_open(g, x+a, y+b)) { |
|
stbcc_update_grid(g, x+a, y+b, 1); |
|
++count; |
|
} |
|
} else { |
|
for (a=0; a < 1; ++a) |
|
for (b=0; b < 32; ++b) |
|
if (stbcc_query_grid_open(g, x+a, y+b)) { |
|
stbcc_update_grid(g, x+a, y+b, 1); |
|
++count; |
|
} |
|
} |
|
|
|
//if (i % 100 == 0) write_map(g, w, h, stb_sprintf("tests/output/stbcc/open_random_%d.png", i+1)); |
|
} |
|
end_timer(); |
|
printf("Removed %d grid spaces\n", count); |
|
write_map(g, w, h, stb_sprintf("tests/output/stbcc/open_random_%d.png", i)); |
|
|
|
|
|
r = 0; |
|
start_timer("reachable"); |
|
for (i=0; i < 1000; ++i) { |
|
for (j=0; j < 1000; ++j) { |
|
int x1 = loc[i][0], y1 = loc[i][1]; |
|
int x2 = loc[j][0], y2 = loc[j][1]; |
|
r += stbcc_query_grid_node_connection(g, x1,y1, x2,y2); |
|
} |
|
} |
|
end_timer(); |
|
printf("%d reachable\n", r); |
|
|
|
start_timer("adding"); |
|
count = 0; |
|
for (i=0; i < 1800; ++i) { |
|
int x,y,a,b; |
|
x = stb_rand() % (w-32); |
|
y = stb_rand() % (h-32); |
|
|
|
if (i & 1) { |
|
for (a=0; a < 32; ++a) |
|
for (b=0; b < 1; ++b) |
|
if (!stbcc_query_grid_open(g, x+a, y+b)) { |
|
stbcc_update_grid(g, x+a, y+b, 0); |
|
++count; |
|
} |
|
} else { |
|
for (a=0; a < 1; ++a) |
|
for (b=0; b < 32; ++b) |
|
if (!stbcc_query_grid_open(g, x+a, y+b)) { |
|
stbcc_update_grid(g, x+a, y+b, 0); |
|
++count; |
|
} |
|
} |
|
|
|
//if (i % 100 == 0) write_map(g, w, h, stb_sprintf("tests/output/stbcc/close_random_%d.png", i+1)); |
|
} |
|
end_timer(); |
|
write_map(g, w, h, stb_sprintf("tests/output/stbcc/close_random_%d.png", i)); |
|
printf("Added %d grid spaces\n", count); |
|
#endif |
|
|
|
|
|
#if 0 // for map_02.png |
|
start_timer("process"); |
|
for (k=0; k < 20; ++k) { |
|
for (j=0; j < h; ++j) { |
|
int any=0; |
|
for (i=0; i < w; ++i) { |
|
if (map[j*w+i] > 10 && map[j*w+i] < 250) { |
|
//start_timer(stb_sprintf("open %d,%d", i,j)); |
|
stbcc_update_grid(g, i, j, 0); |
|
test_connected(g); |
|
//end_timer(); |
|
any = 1; |
|
} |
|
} |
|
if (any) write_map(g, w, h, stb_sprintf("tests/output/stbcc/open_row_%04d.png", j)); |
|
} |
|
|
|
for (j=0; j < h; ++j) { |
|
int any=0; |
|
for (i=0; i < w; ++i) { |
|
if (map[j*w+i] > 10 && map[j*w+i] < 250) { |
|
//start_timer(stb_sprintf("close %d,%d", i,j)); |
|
stbcc_update_grid(g, i, j, 1); |
|
test_connected(g); |
|
//end_timer(); |
|
any = 1; |
|
} |
|
} |
|
if (any) write_map(g, w, h, stb_sprintf("tests/output/stbcc/close_row_%04d.png", j)); |
|
} |
|
} |
|
end_timer(); |
|
#endif |
|
|
|
return 0; |
|
} |
|
#endif
|
|
|