From 27d43f3fd3a6fbda95cdb87e4672fe34f19c2205 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Mar 2012 00:01:38 +0000 Subject: added API function to C and python * C: BM_vert_separate(...) * py: bmesh.utils.vert_separate(vert, edges) This splits off regions around the vertex, splitting on connected edges passed in a sequence. also made minor changes - rename python api functions _rip to _separate - fixed bmesh iterator being iterable its self (some parts of python expect this) - fix memory leak in bmesh python api. --- source/blender/bmesh/intern/bmesh_core.c | 70 ++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 25 deletions(-) (limited to 'source/blender/bmesh/intern/bmesh_core.c') diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 31c8e1f8119..3ca7750f571 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -41,7 +41,7 @@ * TESTING ONLY! */ // #define USE_DEBUG_INDEX_MEMCHECK -int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget); +static int bm_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep); #ifdef USE_DEBUG_INDEX_MEMCHECK #define DEBUG_MEMCHECK_INDEX_INVALIDATE(ele) \ @@ -1739,14 +1739,16 @@ static int bm_vert_splice(BMesh *bm, BMVert *v, BMVert *vtarget) } /** - * \brief Cut Vert + * \brief Separate Vert * - * Cut all disjoint fans that meet at a vertex, making a unique + * Separates all disjoint fans that meet at a vertex, making a unique * vertex for each region. returns an array of all resulting vertices. * + * \note this is a low level function, bm_edge_separate needs to run on edges first + * * \return Success */ -static int bm_vert_cut(BMesh *bm, BMVert *v, BMVert ***vout, int *len) +int bm_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len) { BMEdge **stack = NULL; BLI_array_declare(stack); @@ -1758,7 +1760,7 @@ static int bm_vert_cut(BMesh *bm, BMVert *v, BMVert ***vout, int *len) int i, maxindex; BMLoop *nl; - visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh_vert_cut visithash"); + visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); maxindex = 0; BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) { @@ -1786,7 +1788,7 @@ static int bm_vert_cut(BMesh *bm, BMVert *v, BMVert ***vout, int *len) } /* Make enough verts to split v for each group */ - verts = MEM_callocN(sizeof(BMVert *) * maxindex, "bmesh_vert_cut"); + verts = MEM_callocN(sizeof(BMVert *) * maxindex, __func__); verts[0] = v; for (i = 1; i < maxindex; i++) { verts[i] = BM_vert_create(bm, v->co, v); @@ -1829,12 +1831,12 @@ static int bm_vert_cut(BMesh *bm, BMVert *v, BMVert ***vout, int *len) BM_CHECK_ELEMENT(bm, verts[i]); } - if (len != NULL) { - *len = maxindex; + if (r_vout_len != NULL) { + *r_vout_len = maxindex; } - if (vout != NULL) { - *vout = verts; + if (r_vout != NULL) { + *r_vout = verts; } else { MEM_freeN(verts); @@ -1843,6 +1845,24 @@ static int bm_vert_cut(BMesh *bm, BMVert *v, BMVert ***vout, int *len) return TRUE; } +/** + * High level function which wraps both #bm_vert_separate and #bm_edge_separate + */ +int BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, + BMEdge **e_in, int e_in_len) +{ + int i; + + for (i = 0; i < e_in_len; i++) { + BMEdge *e = e_in[i]; + if (e->l && BM_vert_in_edge(e, v)) { + bm_edge_separate(bm, e, e->l); + } + } + + return bm_vert_separate(bm, v, r_vout, r_vout_len); +} + /** * \brief Splice Edge * @@ -1881,22 +1901,22 @@ int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget) } /** - * \brief Cut Edge + * \brief Separate Edge * - * Cuts a single edge into two edge: the original edge and - * a new edge that has only \a cutl in its radial. + * Separates a single edge into two edge: the original edge and + * a new edge that has only \a l_sep in its radial. * * \return Success * - * \note Does nothing if \a cutl is already the only loop in the + * \note Does nothing if \a l_sep is already the only loop in the * edge radial. */ -static int bm_edge_cut(BMesh *bm, BMEdge *e, BMLoop *cutl) +static int bm_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep) { BMEdge *ne; int radlen; - BLI_assert(cutl->e == e); + BLI_assert(l_sep->e == e); BLI_assert(e->l); radlen = bmesh_radial_length(e->l); @@ -1905,14 +1925,14 @@ static int bm_edge_cut(BMesh *bm, BMEdge *e, BMLoop *cutl) return TRUE; } - if (cutl == e->l) { - e->l = cutl->radial_next; + if (l_sep == e->l) { + e->l = l_sep->radial_next; } ne = BM_edge_create(bm, e->v1, e->v2, e, FALSE); - bmesh_radial_loop_remove(cutl, e); - bmesh_radial_append(ne, cutl); - cutl->e = ne; + bmesh_radial_loop_remove(l_sep, e); + bmesh_radial_append(ne, l_sep); + l_sep->e = ne; BLI_assert(bmesh_radial_length(e->l) == radlen - 1); BLI_assert(bmesh_radial_length(ne->l) == 1); @@ -1939,8 +1959,8 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl) /* peel the face from the edge radials on both sides of the * loop vert, disconnecting the face from its fan */ - bm_edge_cut(bm, sl->e, sl); - bm_edge_cut(bm, sl->prev->e, sl->prev); + bm_edge_separate(bm, sl->e, sl); + bm_edge_separate(bm, sl->prev->e, sl->prev); if (bmesh_disk_count(sv) == 2) { /* If there are still only two edges out of sv, then @@ -1949,7 +1969,7 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl) } /* Update the disk start, so that v->e points to an edge - * not touching the split loop. This is so that bmesh_vert_cut + * not touching the split loop. This is so that BM_vert_split * will leave the original sv on some *other* fan (not the * one-face fan that holds the unglue face). */ while (sv->e == sl->e || sv->e == sl->prev->e) { @@ -1958,7 +1978,7 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl) /* Split all fans connected to the vert, duplicating it for * each fans. */ - bm_vert_cut(bm, sv, &vtar, &len); + bm_vert_separate(bm, sv, &vtar, &len); /* There should have been at least two fans cut apart here, * otherwise the early exit would have kicked in. */ -- cgit v1.2.3