static void polyedge_beauty_cost_update_single(
    const float (*coords)[2],
    const unsigned int (*tris)[3],
    const struct PolyEdge *edges,
    struct PolyEdge *e,
    Heap *eheap, HeapNode **eheap_table)
{
    const unsigned int i = (unsigned int)(e - edges);

    if (eheap_table[i]) {
        BLI_heap_remove(eheap, eheap_table[i]);
        eheap_table[i] = NULL;
    }

    {
        /* recalculate edge */
        const float cost = polyedge_rotate_beauty_calc(coords, tris, e);
        /* We can get cases where both choices generate very small negative costs, which leads to infinite loop.
         * Anyway, costs above that are not worth recomputing, maybe we could even optimize it to a smaller limit?
         * See T43578. */
        if (cost < -FLT_EPSILON) {
            eheap_table[i] = BLI_heap_insert(eheap, cost, e);
        }
        else {
            eheap_table[i] = NULL;
        }
    }
}
Example #2
0
/* recalc an edge in the heap (surrounding geometry has changed) */
static void bm_edge_update_beauty_cost_single(
        BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr,
        /* only for testing the edge is in the array */
        const BMEdge **edge_array, const int edge_array_len,

        const short flag, const short method)
{
	if (edge_in_array(e, edge_array, edge_array_len)) {
		const int i = BM_elem_index_get(e);
		GSet *e_state_set = edge_state_arr[i];

		if (eheap_table[i]) {
			BLI_heap_remove(eheap, eheap_table[i]);
			eheap_table[i] = NULL;
		}

		/* check if we can add it back */
		BLI_assert(BM_edge_is_manifold(e) == true);

		/* check we're not moving back into a state we have been in before */
		if (e_state_set != NULL) {
			EdRotState e_state_alt;
			erot_state_alternate(e, &e_state_alt);
			if (BLI_gset_haskey(e_state_set, (void *)&e_state_alt)) {
				// printf("  skipping, we already have this state\n");
				return;
			}
		}

		{
			/* recalculate edge */
			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;
			}
		}
	}
}
Example #3
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);
}