예제 #1
0
    /**
     * \fn inline unsigned get_boundary_id( unsigned i ) const
     *
     * \brief Returns  the index of the  i-th edge in  the sequence of
     * boundary edges.
     *
     * \param i The index of a surface patch edge.
     *
     * \return The index of the i-th edge of this surface patch in the
     * sequence of boundary edges.
     */
    inline unsigned get_boundary_id( unsigned i ) const
    {
      assert( i < _patch_egs.size() ) ;
      assert( is_boundary_edge( i ) ) ;

      return _patch_egs[ i ].get_mate() ;
    }
예제 #2
0
    /**
     * \fn void get_vertex_star( unsigned i , std::vector< unsigned >& star ) const
     *
     * \brief Gets a list with the indices of all edges incident to
     * the i-th vertex.
     *
     * \param i The index of a surface patch vertex.
     * \param star A reference to a vector of edge indices.
     *
     */
    void get_vertex_star( unsigned i , std::vector< unsigned >& star ) const
    {
      assert( i < _patch_vts.size() ) ;

      unsigned eg1 = _patch_vts[ i ].get_edge() ;
      unsigned eg2 = eg1 ;
      bool endloop = false ;
      do {
	star.push_back( eg2 ) ;
	eg2 = get_prev( eg2 ) ;
	if ( is_boundary_edge( eg2 ) ) {
	  star.push_back( eg2 ) ;
	  endloop = true ;
	}
	else {
	  eg2 = get_mate( eg2 ) ;
	}
      }
      while ( ( eg2 != eg1 ) && !endloop ) ;

      return ;  
    }
/**
 * 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 */
}