You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
		
		
		
		
		
			
		
			
				
					
					
						
							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
 | |
| 
 |