/** * 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 */ }
/** * Wraps #BLI_edgehash_clear_ex with zero entries reserved. */ void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp) { BLI_edgehash_clear_ex(eh, valfreefp, 0); }