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 }