コード例 #1
0
static void laplacian_increase_edge_count(EdgeHash *edgehash, int v1, int v2)
{
	void **p;

	if (BLI_edgehash_ensure_p(edgehash, v1, v2, &p))
		*p = (void *)((intptr_t)*p + (intptr_t)1);
	else
		*p = (void *)((intptr_t)1);
}
コード例 #2
0
/**
 * 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 */
}