Int_Arraylist* Stack_Sp_Grow(const Stack *stack, const size_t *seeds, int nseed, const size_t *targets, int ntarget, Sp_Grow_Workspace *sgw) { size_t nvoxel = Stack_Voxel_Number(stack); sgw->width = stack->width; sgw->height = stack->height; sgw->depth = stack->depth; /* allocate workspace */ if (sgw->size < nvoxel) { sgw->dist = (double*) Guarded_Realloc(sgw->dist, sizeof(double) * nvoxel, "Stack_Sp_Grow"); sgw->path = (int*) Guarded_Realloc(sgw->path, sizeof(int) * nvoxel, "Stack_Sp_Grow"); sgw->checked = (int*) Guarded_Realloc(sgw->checked, sizeof(int) * nvoxel, "Stack_Sp_Grow"); sgw->flag = (uint8_t*) Guarded_Realloc(sgw->flag, sizeof(uint8_t) * nvoxel, "Stack_Sp_Grow"); if (sgw->lengthBufferEnabled) { sgw->length = (double*) Guarded_Realloc( sgw->length, sizeof(double) * nvoxel, "Stack_Sp_Grow"); } } else { if (sgw->dist == NULL) { sgw->dist = (double*) Guarded_Malloc(sizeof(double) * nvoxel, "Stack_Sp_Grow"); } if (sgw->path == NULL) { sgw->path = (int*) Guarded_Malloc(sizeof(int) * nvoxel, "Stack_Sp_Grow"); } if (sgw->checked == NULL) { sgw->checked = (int*) Guarded_Malloc(sizeof(int) * nvoxel, "Stack_Sp_Grow"); } if (sgw->flag == NULL) { sgw->flag = (uint8_t*) Guarded_Malloc(sizeof(uint8_t) * nvoxel, "Stack_Sp_Grow"); } if (sgw->lengthBufferEnabled) { if (sgw->length == NULL) { sgw->length = (double*) Guarded_Malloc( sizeof(double) * nvoxel, "Stack_Sp_Grow"); } } } sgw->size = nvoxel; /* initialize */ size_t s; for (s = 0; s < nvoxel; s++) { sgw->dist[s] = Infinity; if (sgw->length != NULL) { sgw->length[s] = 0.0; } sgw->path[s] = -1; sgw->checked[s] = 0; sgw->flag[s] = 0; } if (sgw->mask != NULL) { memcpy(sgw->flag, sgw->mask, nvoxel); } /* Recruit seeds (source) */ int i; for (i = 0; i < nseed; i++) { if (sgw->sp_option == 1) { sgw->dist[seeds[i]] = -Stack_Array_Value(stack, seeds[i]); } else { sgw->dist[seeds[i]] = 0.0; } sgw->checked[seeds[i]] = 1; sgw->flag[seeds[i]] = SP_GROW_SOURCE; } if (sgw->mask != NULL) { for (s = 0; s < nvoxel; s++) { if (sgw->flag[s] == SP_GROW_SOURCE) { if (sgw->sp_option == 1) { sgw->dist[s] = -Stack_Array_Value(stack, s); } else { sgw->dist[s] = 0.0; } sgw->checked[s] = 1; } } } Int_Arraylist *result = New_Int_Arraylist(); for (i = 0; i < ntarget; i++) { if (sgw->flag[targets[i]] == 2) { /* overlap of source and target */ Int_Arraylist_Add(result, targets[i]); sgw->value = 0.0; return result; } sgw->flag[targets[i]] = SP_GROW_TARGET; } int width = Stack_Width(stack); int height = Stack_Height(stack); int depth = Stack_Depth(stack); double dist[26]; Stack_Neighbor_Dist_R(sgw->conn, sgw->resolution, dist); int is_in_bound[26]; int neighbors[26]; Stack_Neighbor_Offset(sgw->conn, Stack_Width(stack), Stack_Height(stack), neighbors); BOOL stop = FALSE; /* Check neighbors of seeds */ int j; // for (i = 0; i < nseed; i++) { // size_t r = seeds[i]; /* alloc <heap> */ Int_Arraylist *heap = New_Int_Arraylist(); size_t r; for (r = 0; r < nvoxel; r++) { if (sgw->flag[r] == SP_GROW_SOURCE) { /* seeds */ int nbound = Stack_Neighbor_Bound_Test_I(sgw->conn, width, height, depth, r, is_in_bound); if (nbound == sgw->conn) { /* all neighbors are in bound */ for (j = 0; j < sgw->conn; j++) { size_t nbr_index = r + neighbors[j]; if (sgw->checked[nbr_index] != 1) { update_waiting(stack, r, nbr_index, dist[j], heap, result, sgw); } } } else if (nbound > 0) { for (j = 0; j < sgw->conn; j++) { if (is_in_bound[j]) { size_t nbr_index = r + neighbors[j]; if (sgw->checked[nbr_index] != 1) { update_waiting(stack, r, nbr_index, dist[j], heap, result, sgw); } } } } } } //Verify_Int_Heap_I(heap, sgw->dist); ssize_t last_r = -1; while (stop == FALSE) { ssize_t r = extract_min(sgw->dist, sgw->checked, sgw->size, heap); if (r >= 0) { last_r = r; if (sgw->flag[r] == 0) { /* normal voxel */ int nbound = Stack_Neighbor_Bound_Test_I(sgw->conn, width, height, depth, r, is_in_bound); if (nbound == sgw->conn) { /* all neighbors are in bound */ for (j = 0; j < sgw->conn; j++) { size_t nbr_index = r + neighbors[j]; if (sgw->checked[nbr_index] != 1) { update_waiting(stack, r, nbr_index, dist[j], heap, result, sgw); } } } else if (nbound > 0) { for (j = 0; j < sgw->conn; j++) { if (is_in_bound[j]) { size_t nbr_index = r + neighbors[j]; if (sgw->checked[nbr_index] != 1) { update_waiting(stack, r, nbr_index, dist[j], heap, result, sgw); } } } } //Print_Int_Heap(heap, "%d"); //Verify_Int_Heap_I(heap, sgw->dist); } else if (sgw->flag[r] == SP_GROW_TARGET) { /* target reached */ //Int_Arraylist_Add(result, r); stop = TRUE; } else if (sgw->flag[r] == SP_GROW_CONDUCTOR) { /* 0-distance region (super conductor) */ int nbound = Stack_Neighbor_Bound_Test_I(sgw->conn, width, height, depth, r, is_in_bound); size_t tail_index = r; size_t old_tail_index = tail_index; size_t cur_index = r; #ifdef _DEBUG_2 printf("r: %lu\n", r); #endif #define UPDATE_SUPER_CONDUCTOR \ size_t nbr_index = cur_index + neighbors[j]; \ if (sgw->flag[nbr_index] == 4) { \ if (sgw->checked[nbr_index] > 1) { \ Int_Heap_Remove_I_At(heap, nbr_index, sgw->dist, \ sgw->checked); \ } \ tail_index = update_neighbor(cur_index, tail_index, nbr_index,sgw); \ } else { \ update_waiting(stack, cur_index, nbr_index, dist[j], heap, result,sgw); \ } if (nbound == sgw->conn) { /* all neighbors are in bound */ for (j = 0; j < sgw->conn; j++) { UPDATE_SUPER_CONDUCTOR } } else if (nbound > 0) { for (j = 0; j < sgw->conn; j++) { if (is_in_bound[j]) { UPDATE_SUPER_CONDUCTOR } } } int count = 0; while (tail_index != old_tail_index) { old_tail_index = tail_index; size_t cur_index = tail_index; while (sgw->checked[cur_index] != 1) { int nbound = Stack_Neighbor_Bound_Test_I(sgw->conn, width, height, depth, cur_index, is_in_bound); if (nbound == sgw->conn) { /* all neighbors are in bound */ for (j = 0; j < sgw->conn; j++) { UPDATE_SUPER_CONDUCTOR } } else if (nbound > 0) { for (j = 0; j < sgw->conn; j++) { if (is_in_bound[j]) { UPDATE_SUPER_CONDUCTOR } } } sgw->checked[cur_index] = 1; size_t tmp_index = cur_index; cur_index = sgw->path[cur_index]; sgw->path[tmp_index] = r; count++; } }
Graph* Stack_Graph_W(const Stack *stack, Stack_Graph_Workspace *sgw) { int x, y, z; int offset = 0; int is_in_bound[26]; int nbound; int i; int stack_range[6]; int *range = sgw->range; if (range == NULL) { stack_range[0] = 0; stack_range[1] = stack->width - 1; stack_range[2] = 0; stack_range[3] = stack->height - 1; stack_range[4] = 0; stack_range[5] = stack->depth - 1; } else { stack_range[0] = imax2(0, range[0]); stack_range[1] = imin2(stack->width - 1, range[1]); stack_range[2] = imax2(0, range[2]); stack_range[3] = imin2(stack->height - 1, range[3]); stack_range[4] = imax2(0, range[4]); stack_range[5] = imin2(stack->depth - 1, range[5]); } int cdepth = stack_range[5] - stack_range[4]; int cheight = stack_range[3] - stack_range[2]; int cwidth = stack_range[1] - stack_range[0]; int nvertex = (cwidth + 1) * (cheight + 1) * (cdepth + 1); sgw->virtualVertex = nvertex; BOOL weighted = TRUE; if (sgw->sp_option == 1) { weighted = FALSE; sgw->intensity = darray_malloc(nvertex + 1); sgw->intensity[nvertex] = Infinity; } Graph *graph = Make_Graph(nvertex, nvertex, weighted); int neighbor[26]; int scan_mask[26]; Stack_Neighbor_Offset(sgw->conn, cwidth + 1, cheight + 1, neighbor); int org_neighbor[26]; Stack_Neighbor_Offset(sgw->conn, Stack_Width(stack), Stack_Height(stack), org_neighbor); double dist[26]; Stack_Neighbor_Dist_R(sgw->conn, sgw->resolution, dist); //const double *dist = Stack_Neighbor_Dist(sgw->conn); const int *x_offset = Stack_Neighbor_X_Offset(sgw->conn); const int *y_offset = Stack_Neighbor_Y_Offset(sgw->conn); const int *z_offset = Stack_Neighbor_Z_Offset(sgw->conn); /* go forward */ for (i = 0; i < sgw->conn; i++) { scan_mask[i] = (neighbor[i] > 0); } #define STACK_GRAPH_ADD_EDGE(cond) \ for (i = 0; i < sgw->conn; i++) { \ if (cond) { \ int nx = x + stack_range[0]; \ int ny = y + stack_range[2]; \ int nz = z + stack_range[4]; \ if (Graph_Is_Weighted(graph)) { \ double weight = dist[i]; \ if (sgw->wf != NULL) { \ sgw->argv[0] = dist[i]; \ \ sgw->argv[1] = Get_Stack_Pixel((Stack *)stack, nx, ny, nz, 0); \ sgw->argv[2] = \ Get_Stack_Pixel((Stack *)stack, nx + x_offset[i], \ ny + y_offset[i], nz + z_offset[i], 0); \ weight = sgw->wf(sgw->argv); \ } \ Graph_Add_Weighted_Edge(graph, offset, offset + neighbor[i], \ weight); \ } else { \ Graph_Add_Edge(graph, offset, offset + neighbor[i]); \ sgw->intensity[offset] = Get_Stack_Pixel((Stack*) stack, \ nx, ny, nz, 0); \ } \ } \ } int groupVertexMap[256]; for (i = 0; i < 256; ++i) { groupVertexMap[i] = 0; } int swidth = cwidth + 1; int sarea = (cwidth + 1) * (cheight + 1); int area = stack->width * stack->height; for (z = 0; z <= cdepth; z++) { for (y = 0; y <= cheight; y++) { for (x = 0; x <= cwidth; x++) { nbound = Stack_Neighbor_Bound_Test_S(sgw->conn, cwidth, cheight, cdepth, x, y, z, is_in_bound); size_t offset2 = Stack_Subindex((size_t) offset, stack_range[0], stack_range[2], stack_range[4], swidth, sarea, stack->width, area); #ifdef _DEBUG_2 if (offset == 36629) { printf("debug here\n"); } #endif if (nbound == sgw->conn) { STACK_GRAPH_ADD_EDGE((scan_mask[i] == 1) && (sgw->signal_mask == NULL ? 1 : ((sgw->signal_mask->array[offset2] > 0) && (sgw->signal_mask->array[offset2+org_neighbor[i]] > 0)))) } else { STACK_GRAPH_ADD_EDGE((scan_mask[i] == 1) && is_in_bound[i] && (sgw->signal_mask == NULL ? 1 : ((sgw->signal_mask->array[offset2] > 0) && (sgw->signal_mask->array[offset2+org_neighbor[i]]) > 0))) } if (sgw->group_mask != NULL) { int groupId = sgw->group_mask->array[offset2]; if (groupId > 0) { #ifdef _DEBUG_2 sgw->group_mask->array[offset2] = 2; #endif int groupVertex = groupVertexMap[groupId]; if (groupVertex <= 0) { groupVertex = nvertex++; groupVertexMap[groupId] = groupVertex; } Graph_Add_Weighted_Edge(graph, groupVertex, offset, 0.0); } } offset++; } } } return graph; }