/**
 * The intention is that this calculates the output of #BLI_polyfill_calc
 *
 *
 * \note assumes the \a coords form a boundary,
 * so any edges running along contiguous (wrapped) indices,
 * are ignored since the edges wont share 2 faces.
 */
void BLI_polyfill_beautify(
    const float (*coords)[2],
    const unsigned int coords_tot,
    unsigned int (*tris)[3],

    /* structs for reuse */
    MemArena *arena, Heap *eheap, EdgeHash *ehash)
{
    const unsigned int coord_last = coords_tot - 1;
    const unsigned int tris_tot = coords_tot - 2;
    /* internal edges only (between 2 tris) */
    const unsigned int edges_tot = tris_tot - 1;
    unsigned int edges_tot_used = 0;
    unsigned int i;

    HeapNode **eheap_table;

    struct PolyEdge *edges = BLI_memarena_alloc(arena, edges_tot * sizeof(*edges));

    BLI_assert(BLI_heap_size(eheap) == 0);
    BLI_assert(BLI_edgehash_size(ehash) == 0);

    /* first build edges */
    for (i = 0; i < tris_tot; i++) {
        unsigned int j_prev, j_curr, j_next;
        j_prev = 2;
        j_next = 1;
        for (j_curr = 0; j_curr < 3; j_next = j_prev, j_prev = j_curr++) {
            int e_index;

            unsigned int e_pair[2] = {
                tris[i][j_prev],
                tris[i][j_curr],
            };

            if (e_pair[0] > e_pair[1]) {
                SWAP(unsigned int, e_pair[0], e_pair[1]);
                e_index = 1;
            }
            else {
                e_index = 0;
            }

            if (!is_boundary_edge(e_pair[0], e_pair[1], coord_last)) {
                struct PolyEdge *e;
                void **val_p;

                if (!BLI_edgehash_ensure_p(ehash, e_pair[0], e_pair[1], &val_p)) {
                    e = &edges[edges_tot_used++];
                    *val_p = e;
                    memcpy(e->verts, e_pair, sizeof(e->verts));
#ifndef NDEBUG
                    e->faces[!e_index] = (unsigned int)-1;
#endif
                }
                else {
                    e = *val_p;
                    /* ensure each edge only ever has 2x users */
#ifndef NDEBUG
                    BLI_assert(e->faces[e_index] == (unsigned int)-1);
                    BLI_assert((e->verts[0] == e_pair[0]) &&
                               (e->verts[1] == e_pair[1]));
#endif
                }

                e->faces[e_index] = i;
                e->faces_other_v[e_index] = j_next;
            }
        }
    }

    /* now perform iterative rotations */
    eheap_table = BLI_memarena_alloc(arena, sizeof(HeapNode *) * (size_t)edges_tot);

    // for (i = 0; i < tris_tot; i++) { polyfill_validate_tri(tris, i, eh); }

    /* build heap */
    for (i = 0; i < edges_tot; i++) {
        struct PolyEdge *e = &edges[i];
        const float cost = polyedge_rotate_beauty_calc(coords, (const unsigned int (*)[3])tris, e);
        if (cost < 0.0f) {
            eheap_table[i] = BLI_heap_insert(eheap, cost, e);
        }
        else {
            eheap_table[i] = NULL;
        }
    }

    while (BLI_heap_is_empty(eheap) == false) {
        struct PolyEdge *e = BLI_heap_popmin(eheap);
        i = (unsigned int)(e - edges);
        eheap_table[i] = NULL;

        polyedge_rotate(tris, e, ehash);

        /* recalculate faces connected on the heap */
        polyedge_beauty_cost_update(
            coords, (const unsigned int (*)[3])tris, edges,
            e,
            eheap, eheap_table, ehash);
    }

    BLI_heap_clear(eheap, NULL);
    BLI_edgehash_clear_ex(ehash, NULL, BLI_POLYFILL_ALLOC_NGON_RESERVE);

    /* MEM_freeN(eheap_table); */  /* arena */
}
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);
}
Example #3
0
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;
}
Example #4
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);
}
Example #5
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
}