bmesh: edge loop select
add support for loop selecting boundry edges only - handy for loop selecting the side of an ngon.
This commit is contained in:
@@ -291,20 +291,15 @@ int BM_vert_edge_count(BMVert *v)
|
|||||||
return bmesh_disk_count(v);
|
return bmesh_disk_count(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
int BM_vert_edge_count_nonwire( BMesh *bm, BMVert *v)
|
int BM_vert_edge_count_nonwire(BMVert *v)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
BMIter eiter;
|
BMIter eiter;
|
||||||
BMEdge *edge;
|
BMEdge *edge;
|
||||||
BM_ITER(edge, &eiter, bm, BM_EDGES_OF_VERT, v){
|
BM_ITER(edge, &eiter, NULL, BM_EDGES_OF_VERT, v){
|
||||||
if (!edge) return count;
|
if(edge->l) {
|
||||||
|
count++;
|
||||||
if (count >= (1 << 20)) {
|
|
||||||
printf(" bmesh error: infinite loop in disk cycle!\n");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(edge->l) count++;
|
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ BMVert *BM_edge_other_vert(BMEdge *e, BMVert *v);
|
|||||||
BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v);
|
BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v);
|
||||||
BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v);
|
BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v);
|
||||||
|
|
||||||
|
int BM_vert_edge_count_nonwire(BMVert *v);
|
||||||
int BM_vert_edge_count(BMVert *v);
|
int BM_vert_edge_count(BMVert *v);
|
||||||
int BM_edge_face_count(BMEdge *e);
|
int BM_edge_face_count(BMEdge *e);
|
||||||
int BM_vert_face_count(BMVert *v);
|
int BM_vert_face_count(BMVert *v);
|
||||||
@@ -49,8 +50,6 @@ int BM_vert_face_count(BMVert *v);
|
|||||||
int BM_vert_is_wire(BMesh *bm, BMVert *v);
|
int BM_vert_is_wire(BMesh *bm, BMVert *v);
|
||||||
int BM_edge_is_wire(BMesh *bm, BMEdge *e);
|
int BM_edge_is_wire(BMesh *bm, BMEdge *e);
|
||||||
|
|
||||||
int BM_vert_edge_count_nonwire( BMesh *bm, BMVert *v);
|
|
||||||
|
|
||||||
int BM_vert_is_manifold(BMesh *bm, BMVert *v);
|
int BM_vert_is_manifold(BMesh *bm, BMVert *v);
|
||||||
int BM_edge_is_manifold(BMesh *bm, BMEdge *e);
|
int BM_edge_is_manifold(BMesh *bm, BMEdge *e);
|
||||||
int BM_edge_is_boundary(BMEdge *e);
|
int BM_edge_is_boundary(BMEdge *e);
|
||||||
|
|||||||
@@ -398,7 +398,9 @@ static void bmw_LoopWalker_begin(BMWalker *walker, void *data)
|
|||||||
lwalk->cur = lwalk->start = e;
|
lwalk->cur = lwalk->start = e;
|
||||||
lwalk->lastv = lwalk->startv = v;
|
lwalk->lastv = lwalk->startv = v;
|
||||||
lwalk->stage2 = 0;
|
lwalk->stage2 = 0;
|
||||||
lwalk->startrad = BM_edge_face_count(e);
|
lwalk->is_boundry = BM_edge_is_boundary(e);
|
||||||
|
lwalk->is_single = (BM_vert_edge_count_nonwire(e->v1) == 2 &&
|
||||||
|
BM_vert_edge_count_nonwire(e->v2) == 2);
|
||||||
|
|
||||||
/* rewin */
|
/* rewin */
|
||||||
while (BMW_current_state(walker)) {
|
while (BMW_current_state(walker)) {
|
||||||
@@ -433,7 +435,9 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
|
|||||||
BMEdge *e = lwalk->cur, *nexte = NULL;
|
BMEdge *e = lwalk->cur, *nexte = NULL;
|
||||||
BMLoop *l, *l2;
|
BMLoop *l, *l2;
|
||||||
BMVert *v;
|
BMVert *v;
|
||||||
int val, rlen /* , found = 0 */, i = 0, stopi;
|
int vert_edge_tot;
|
||||||
|
int i = 0, stopi;
|
||||||
|
/* int found = 0; */ /* UNUSED */
|
||||||
|
|
||||||
owalk = *lwalk;
|
owalk = *lwalk;
|
||||||
BMW_state_remove(walker);
|
BMW_state_remove(walker);
|
||||||
@@ -452,7 +456,8 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
|
|||||||
lwalk = BMW_state_add(walker);
|
lwalk = BMW_state_add(walker);
|
||||||
lwalk->cur = nexte;
|
lwalk->cur = nexte;
|
||||||
lwalk->lastv = v;
|
lwalk->lastv = v;
|
||||||
lwalk->startrad = owalk.startrad;
|
lwalk->is_boundry = owalk.is_boundry;
|
||||||
|
lwalk->is_single = owalk.is_single;
|
||||||
|
|
||||||
BLI_ghash_insert(walker->visithash, nexte, NULL);
|
BLI_ghash_insert(walker->visithash, nexte, NULL);
|
||||||
}
|
}
|
||||||
@@ -462,18 +467,27 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
|
|||||||
return owalk.cur;
|
return owalk.cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
v = (e->v1 == lwalk->lastv) ? e->v2 : e->v1;
|
v = BM_edge_other_vert(e, lwalk->lastv);
|
||||||
|
|
||||||
rlen = owalk.startrad;
|
vert_edge_tot = BM_vert_edge_count_nonwire(v);
|
||||||
|
|
||||||
val = BM_vert_edge_count_nonwire(walker->bm, v);
|
if (/* check if we should step, this is fairly involved */
|
||||||
|
|
||||||
/* however, why use 2 here at all? I guess for internal ngon loops it can be useful. Antony R. */
|
/* typical loopiong over edges in the middle of a mesh */
|
||||||
if (((val == 4 || val == 2) && rlen > 1) || (rlen == 1 && val > 2)) {
|
/* however, why use 2 here at all? I guess for internal ngon loops it can be useful. Antony R. */
|
||||||
|
((vert_edge_tot == 4 || vert_edge_tot == 2) && owalk.is_boundry == FALSE) ||
|
||||||
|
|
||||||
|
/* walk over boundry of faces but stop at corners */
|
||||||
|
(owalk.is_boundry == TRUE && owalk.is_single == FALSE && vert_edge_tot > 2) ||
|
||||||
|
|
||||||
|
/* initial edge was a boundry, so is this edge and vertex is only apart of this face
|
||||||
|
* this lets us walk over the the boundry of an ngon which is handy */
|
||||||
|
(owalk.is_boundry == TRUE && owalk.is_single == TRUE && vert_edge_tot == 2 && BM_edge_is_boundary(e)))
|
||||||
|
{
|
||||||
i = 0;
|
i = 0;
|
||||||
stopi = val / 2;
|
stopi = vert_edge_tot / 2;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (rlen != 1 && i == stopi) break;
|
if (owalk.is_boundry == FALSE && i == stopi) break;
|
||||||
|
|
||||||
l = BM_face_other_edge_loop(l->f, l->e, v);
|
l = BM_face_other_edge_loop(l->f, l->e, v);
|
||||||
|
|
||||||
@@ -496,11 +510,12 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (l != e->l && !BLI_ghash_haskey(walker->visithash, l->e)) {
|
if (l != e->l && !BLI_ghash_haskey(walker->visithash, l->e)) {
|
||||||
if (!(rlen != 1 && i != stopi)) {
|
if (!(owalk.is_boundry == FALSE && i != stopi)) {
|
||||||
lwalk = BMW_state_add(walker);
|
lwalk = BMW_state_add(walker);
|
||||||
lwalk->cur = l->e;
|
lwalk->cur = l->e;
|
||||||
lwalk->lastv = v;
|
lwalk->lastv = v;
|
||||||
lwalk->startrad = owalk.startrad;
|
lwalk->is_boundry = owalk.is_boundry;
|
||||||
|
lwalk->is_single = owalk.is_single;
|
||||||
BLI_ghash_insert(walker->visithash, l->e, NULL);
|
BLI_ghash_insert(walker->visithash, l->e, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,9 @@ typedef struct BMwLoopWalker {
|
|||||||
BMwGenericWalker header;
|
BMwGenericWalker header;
|
||||||
BMEdge *cur, *start;
|
BMEdge *cur, *start;
|
||||||
BMVert *lastv, *startv;
|
BMVert *lastv, *startv;
|
||||||
int startrad, stage2;
|
int stage2;
|
||||||
|
short is_boundry; /* boundry looping changes behavior */
|
||||||
|
short is_single; /* single means the edge verts are only connected to 1 face */
|
||||||
} BMwLoopWalker;
|
} BMwLoopWalker;
|
||||||
|
|
||||||
typedef struct BMwFaceLoopWalker {
|
typedef struct BMwFaceLoopWalker {
|
||||||
|
|||||||
Reference in New Issue
Block a user