Esempio n. 1
0
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);
}
Esempio n. 2
0
/**
 * \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
}