static void curve_select_shortest_path_surf(Nurb *nu, int vert_src, int vert_dst) { Heap *heap; int i, vert_curr; int totu = nu->pntsu; int totv = nu->pntsv; int vert_num = totu * totv; /* custom data */ struct PointAdj { int vert, vert_prev; float cost; } *data; /* init connectivity data */ data = MEM_mallocN(sizeof(*data) * vert_num, __func__); for (i = 0; i < vert_num; i++) { data[i].vert = i; data[i].vert_prev = -1; data[i].cost = FLT_MAX; } /* init heap */ heap = BLI_heap_new(); BLI_heap_insert(heap, 0.0f, &data[vert_src].vert); data[vert_src].cost = 0.0f; data[vert_src].vert_prev = vert_src; /* nop */ while (!BLI_heap_is_empty(heap)) { int axis, sign; int u, v; vert_curr = *((int *)BLI_heap_popmin(heap)); if (vert_curr == vert_dst) { break; } BKE_nurb_index_to_uv(nu, vert_curr, &u, &v); /* loop over 4 adjacent verts */ for (sign = -1; sign != 3; sign += 2) { for (axis = 0; axis != 2; axis += 1) { int uv_other[2] = {u, v}; int vert_other; uv_other[axis] += sign; vert_other = BKE_nurb_index_from_uv(nu, uv_other[0], uv_other[1]); if (vert_other != -1) { const float dist = data[vert_curr].cost + curve_calc_dist_pair(nu, vert_curr, vert_other); if (data[vert_other].cost > dist) { data[vert_other].cost = dist; if (data[vert_other].vert_prev == -1) { BLI_heap_insert(heap, data[vert_other].cost, &data[vert_other].vert); } data[vert_other].vert_prev = vert_curr; } } } } } BLI_heap_free(heap, NULL); if (vert_curr == vert_dst) { i = 0; while (vert_curr != vert_src && i++ < vert_num) { if (nu->type == CU_BEZIER) { select_beztriple(&nu->bezt[vert_curr], SELECT, SELECT, HIDDEN); } else { select_bpoint(&nu->bp[vert_curr], SELECT, SELECT, HIDDEN); } vert_curr = data[vert_curr].vert_prev; } } MEM_freeN(data); }
int seam_shortest_path(int source, int target) { Heap *heap; EdgeHash *ehash; float *cost; MEdge *med; int a, *nedges, *edges, *prevedge, mednum = -1, nedgeswap = 0; TFace *tf; MFace *mf; Mesh* me = &gCloseMesh; /* mark hidden edges as done, so we don't use them */ ehash = BLI_edgehash_new(); for (a=0, mf=me->mface, tf=me->tface; a<me->totface; a++, tf++, mf++) { if (!(tf->flag & TF_HIDE)) { BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL); BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL); if (mf->v4) { BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL); BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL); } else BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL); } } for (a=0, med=me->medge; a<me->totedge; a++, med++) { if (!BLI_edgehash_haskey(ehash, med->v1, med->v2)) { med->flag |= ME_SEAM_DONE; } } BLI_edgehash_free(ehash, NULL); /* alloc */ nedges = (int*)MEM_callocN(sizeof(*nedges)*me->totvert+1, "SeamPathNEdges"); edges = (int*)MEM_mallocN(sizeof(*edges)*me->totedge*2, "SeamPathEdges"); prevedge = (int*)MEM_mallocN(sizeof(*prevedge)*me->totedge, "SeamPathPrevious"); cost = (float*)MEM_mallocN(sizeof(*cost)*me->totedge, "SeamPathCost"); /* count edges, compute adjacent edges offsets and fill adjacent edges */ for (a=0, med=me->medge; a<me->totedge; a++, med++) { nedges[med->v1+1]++; nedges[med->v2+1]++; } for (a=1; a<me->totvert; a++) { int newswap = nedges[a+1]; nedges[a+1] = nedgeswap + nedges[a]; nedgeswap = newswap; } nedges[0] = nedges[1] = 0; for (a=0, med=me->medge; a<me->totedge; a++, med++) { edges[nedges[med->v1+1]++] = a; edges[nedges[med->v2+1]++] = a; cost[a] = 1e20f; prevedge[a] = -1; } /* regular dijkstra shortest path, but over edges instead of vertices */ heap = BLI_heap_new(); BLI_heap_insert(heap, 0.0f, (void*)source); cost[source] = 0.0f; while (!BLI_heap_empty(heap)) { mednum = (int)BLI_heap_popmin(heap); med = me->medge + mednum; if (mednum == target) break; if (med->flag & ME_SEAM_DONE) continue; med->flag |= ME_SEAM_DONE; seam_add_adjacent(me, heap, mednum, med->v1, nedges, edges, prevedge, cost, target); seam_add_adjacent(me, heap, mednum, med->v2, nedges, edges, prevedge, cost, target); } MEM_freeN(nedges); MEM_freeN(edges); MEM_freeN(cost); BLI_heap_free(heap, NULL); for (a=0, med=me->medge; a<me->totedge; a++, med++) { med->flag &= ~ME_SEAM_DONE; } if (mednum != target) { MEM_freeN(prevedge); return 0; } /* follow path back to source and mark as seam */ if (mednum == target) { short allseams = 1; mednum = target; do { med = me->medge + mednum; if (!(med->flag & ME_SEAM)) { allseams = 0; break; } mednum = prevedge[mednum]; } while (mednum != source); mednum = target; do { med = me->medge + mednum; if (allseams) med->flag &= ~ME_SEAM; else med->flag |= ME_SEAM; mednum = prevedge[mednum]; } while (mednum != -1); } MEM_freeN(prevedge); return 1; }
static void colorband_init_from_table_rgba_resample( ColorBand *coba, const float (*array)[4], const int array_len, bool filter_samples) { BLI_assert(array_len >= 2); const float eps_2x = ((1.0f / 255.0f) + 1e-6f); struct ColorResampleElem *c, *carr = MEM_mallocN(sizeof(*carr) * array_len, __func__); int carr_len = array_len; c = carr; { const float step_size = 1.0f / (float)(array_len - 1); for (int i = 0; i < array_len; i++, c++) { copy_v4_v4(carr[i].rgba, array[i]); c->next = c + 1; c->prev = c - 1; c->pos = i * step_size; } } carr[0].prev = NULL; carr[array_len - 1].next = NULL; /* -2 to remove endpoints. */ Heap *heap = BLI_heap_new_ex(array_len - 2); c = carr; for (int i = 0; i < array_len; i++, c++) { float cost = color_sample_remove_cost(c); if (cost != -1.0f) { c->node = BLI_heap_insert(heap, cost, c); } else { c->node = NULL; } } while ((carr_len > 1 && !BLI_heap_is_empty(heap)) && ((carr_len >= MAXCOLORBAND) || (BLI_heap_node_value(BLI_heap_top(heap)) <= eps_2x))) { c = BLI_heap_pop_min(heap); struct ColorResampleElem *c_next = c->next, *c_prev = c->prev; c_prev->next = c_next; c_next->prev = c_prev; /* Clear data (not essential, avoid confusion). */ c->prev = c->next = NULL; c->node = NULL; /* Update adjacent */ for (int i = 0; i < 2; i++) { struct ColorResampleElem *c_other = i ? c_next : c_prev; if (c_other->node != NULL) { const float cost = color_sample_remove_cost(c_other); if (cost != -1.0) { BLI_heap_node_value_update(heap, c_other->node, cost); } else { BLI_heap_remove(heap, c_other->node); c_other->node = NULL; } } } carr_len -= 1; } BLI_heap_free(heap, NULL); /* First member is never removed. */ int i = 0; BLI_assert(carr_len < MAXCOLORBAND); if (filter_samples == false) { for (c = carr; c != NULL; c = c->next, i++) { copy_v4_v4(&coba->data[i].r, c->rgba); coba->data[i].pos = c->pos; coba->data[i].cur = i; } } else { for (c = carr; c != NULL; c = c->next, i++) { const int steps_prev = c->prev ? (c - c->prev) - 1 : 0; const int steps_next = c->next ? (c->next - c) - 1 : 0; if (steps_prev == 0 && steps_next == 0) { copy_v4_v4(&coba->data[i].r, c->rgba); } else { float rgba[4]; float rgba_accum = 1; copy_v4_v4(rgba, c->rgba); if (steps_prev) { const float step_size = 1.0 / (float)(steps_prev + 1); int j = steps_prev; for (struct ColorResampleElem *c_other = c - 1; c_other != c->prev; c_other--, j--) { const float step_pos = (float)j * step_size; BLI_assert(step_pos > 0.0f && step_pos < 1.0f); const float f = filter_gauss(step_pos); madd_v4_v4fl(rgba, c_other->rgba, f); rgba_accum += f; } } if (steps_next) { const float step_size = 1.0 / (float)(steps_next + 1); int j = steps_next; for (struct ColorResampleElem *c_other = c + 1; c_other != c->next; c_other++, j--) { const float step_pos = (float)j * step_size; BLI_assert(step_pos > 0.0f && step_pos < 1.0f); const float f = filter_gauss(step_pos); madd_v4_v4fl(rgba, c_other->rgba, f); rgba_accum += f; } } mul_v4_v4fl(&coba->data[i].r, rgba, 1.0f / rgba_accum); } coba->data[i].pos = c->pos; coba->data[i].cur = i; } } BLI_assert(i == carr_len); coba->tot = i; coba->cur = 0; MEM_freeN(carr); }
/** * \note This function sets the edge indices to invalid values. */ void BM_mesh_beautify_fill( BMesh *bm, BMEdge **edge_array, const int edge_array_len, const short flag, const short method, const short oflag_edge, const short oflag_face) { Heap *eheap; /* edge heap */ HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */ GSet **edge_state_arr = MEM_callocN((size_t)edge_array_len * sizeof(GSet *), __func__); BLI_mempool *edge_state_pool = BLI_mempool_create(sizeof(EdRotState), 0, 512, BLI_MEMPOOL_NOP); int i; #ifdef DEBUG_TIME TIMEIT_START(beautify_fill); #endif eheap = BLI_heap_new_ex((uint)edge_array_len); eheap_table = MEM_mallocN(sizeof(HeapNode *) * (size_t)edge_array_len, __func__); /* build heap */ for (i = 0; i < edge_array_len; i++) { BMEdge *e = edge_array[i]; const float cost = bm_edge_calc_rotate_beauty(e, flag, method); if (cost < 0.0f) { eheap_table[i] = BLI_heap_insert(eheap, cost, e); } else { eheap_table[i] = NULL; } BM_elem_index_set(e, i); /* set_dirty */ } bm->elem_index_dirty |= BM_EDGE; while (BLI_heap_is_empty(eheap) == false) { BMEdge *e = BLI_heap_popmin(eheap); i = BM_elem_index_get(e); eheap_table[i] = NULL; BLI_assert(BM_edge_face_count_is_equal(e, 2)); e = BM_edge_rotate(bm, e, false, BM_EDGEROT_CHECK_EXISTS); BLI_assert(e == NULL || BM_edge_face_count_is_equal(e, 2)); if (LIKELY(e)) { GSet *e_state_set = edge_state_arr[i]; /* add the new state into the set so we don't move into this state again * note: we could add the previous state too but this isn't essential) * for avoiding eternal loops */ EdRotState *e_state = BLI_mempool_alloc(edge_state_pool); erot_state_current(e, e_state); if (UNLIKELY(e_state_set == NULL)) { edge_state_arr[i] = e_state_set = erot_gset_new(); /* store previous state */ } BLI_assert(BLI_gset_haskey(e_state_set, (void *)e_state) == false); BLI_gset_insert(e_state_set, e_state); // printf(" %d -> %d, %d\n", i, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2)); /* maintain the index array */ edge_array[i] = e; BM_elem_index_set(e, i); /* recalculate faces connected on the heap */ bm_edge_update_beauty_cost(e, eheap, eheap_table, edge_state_arr, (const BMEdge **)edge_array, edge_array_len, flag, method); /* update flags */ if (oflag_edge) { BMO_edge_flag_enable(bm, e, oflag_edge); } if (oflag_face) { BMO_face_flag_enable(bm, e->l->f, oflag_face); BMO_face_flag_enable(bm, e->l->radial_next->f, oflag_face); } } } BLI_heap_free(eheap, NULL); MEM_freeN(eheap_table); for (i = 0; i < edge_array_len; i++) { if (edge_state_arr[i]) { BLI_gset_free(edge_state_arr[i], NULL); } } MEM_freeN(edge_state_arr); BLI_mempool_destroy(edge_state_pool); #ifdef DEBUG_TIME TIMEIT_END(beautify_fill); #endif }