refactor bmesh edge loop walker,
authorCampbell Barton <ideasman42@gmail.com>
Tue, 14 May 2013 04:09:02 +0000 (04:09 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 14 May 2013 04:09:02 +0000 (04:09 +0000)
was getting too complicated handing different cases at once, split out boundary case into its own branch.

source/blender/bmesh/intern/bmesh_walkers_impl.c

index 187c808de4161d1892f63ad00e6d8f5f15e7459c..c966ee337db67dbfd4b42b1b298ec7b8ba61579d 100644 (file)
@@ -538,52 +538,56 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
                        }
                }
        }
-       else if (l) { /* NORMAL EDGE WITH FACES */
-               int vert_edge_tot;
-               int stopi = 0;
+       else if (l == NULL) {  /* WIRE EDGE */
+               BMIter eiter;
 
-               v = BM_edge_other_vert(e, lwalk->lastv);
+               /* match trunk: mark all connected wire edges */
+               for (i = 0; i < 2; i++) {
+                       v = i ? e->v2 : e->v1;
 
-               vert_edge_tot = BM_vert_edge_count_nonwire(v);
+                       BM_ITER_ELEM (nexte, &eiter, v, BM_EDGES_OF_VERT) {
+                               if ((nexte->l == NULL) &&
+                                   bmw_mask_check_edge(walker, nexte) &&
+                                   !BLI_ghash_haskey(walker->visithash, nexte))
+                               {
+                                       lwalk = BMW_state_add(walker);
+                                       lwalk->cur = nexte;
+                                       lwalk->lastv = v;
 
-               if (/* check if we should step, this is fairly involved */
+                                       lwalk->is_boundary = owalk.is_boundary;
+                                       lwalk->is_single = owalk.is_single;
+                                       lwalk->f_hub = owalk.f_hub;
 
-                       /* typical loopiong over edges in the middle of a mesh */
-                       /* 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_boundary == false) ||
+                                       BLI_ghash_insert(walker->visithash, nexte, NULL);
+                               }
+                       }
+               }
+       }
+       else if (owalk.is_boundary == false) {  /* NORMAL EDGE WITH FACES */
+               int vert_edge_tot;
 
-                       /* walk over boundary of faces but stop at corners */
-                       (owalk.is_boundary == true && owalk.is_single == false && vert_edge_tot > 2) ||
+               v = BM_edge_other_vert(e, lwalk->lastv);
 
-                       /* initial edge was a boundary, so is this edge and vertex is only apart of this face
-                        * this lets us walk over the the boundary of an ngon which is handy */
-                       (owalk.is_boundary == true && owalk.is_single == true && vert_edge_tot == 2 && BM_edge_is_boundary(e)))
-               {
-                       i = 0;
-                       stopi = vert_edge_tot / 2;
-                       while (1) {
-                               if ((owalk.is_boundary == false) && (i == stopi)) {
-                                       break;
-                               }
+               vert_edge_tot = BM_vert_edge_count_nonwire(v);
 
+               /* typical loopiong over edges in the middle of a mesh */
+               /* however, why use 2 here at all? I guess for internal ngon loops it can be useful. Antony R. */
+               if (vert_edge_tot == 4 || vert_edge_tot == 2) {
+                       int i_opposite = vert_edge_tot / 2;
+                       int i = 0;
+                       do {
                                l = BM_loop_other_edge_loop(l, v);
-
-                               if (l == NULL) {
-                                       break;
+                               if (BM_edge_is_manifold(l->e)) {
+                                       l = l->radial_next;
                                }
                                else {
-                                       BMLoop *l_next;
-
-                                       l_next = l->radial_next;
-
-                                       if ((l_next == l) || (l_next == NULL)) {
-                                               break;
-                                       }
-
-                                       l = l_next;
-                                       i++;
+                                       l = NULL;
+                                       break;
                                }
-                       }
+                       } while ((++i != i_opposite));
+               }
+               else {
+                       l = NULL;
                }
 
                if (l != NULL) {
@@ -591,42 +595,64 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
                            bmw_mask_check_edge(walker, l->e) &&
                            !BLI_ghash_haskey(walker->visithash, l->e))
                        {
-                               if (!(owalk.is_boundary == false && i != stopi)) {
-                                       lwalk = BMW_state_add(walker);
-                                       lwalk->cur = l->e;
-                                       lwalk->lastv = v;
+                               lwalk = BMW_state_add(walker);
+                               lwalk->cur = l->e;
+                               lwalk->lastv = v;
 
-                                       lwalk->is_boundary = owalk.is_boundary;
-                                       lwalk->is_single = owalk.is_single;
-                                       lwalk->f_hub = owalk.f_hub;
+                               lwalk->is_boundary = owalk.is_boundary;
+                               lwalk->is_single = owalk.is_single;
+                               lwalk->f_hub = owalk.f_hub;
 
-                                       BLI_ghash_insert(walker->visithash, l->e, NULL);
-                               }
+                               BLI_ghash_insert(walker->visithash, l->e, NULL);
                        }
                }
        }
-       else {  /* WIRE EDGE */
-               BMIter eiter;
+       else if (owalk.is_boundary == true) {  /* BOUNDARY EDGE WITH FACES */
+               int vert_edge_tot;
 
-               /* match trunk: mark all connected wire edges */
-               for (i = 0; i < 2; i++) {
-                       v = i ? e->v2 : e->v1;
+               v = BM_edge_other_vert(e, lwalk->lastv);
 
-                       BM_ITER_ELEM (nexte, &eiter, v, BM_EDGES_OF_VERT) {
-                               if ((nexte->l == NULL) &&
-                                   bmw_mask_check_edge(walker, nexte) &&
-                                   !BLI_ghash_haskey(walker->visithash, nexte))
-                               {
-                                       lwalk = BMW_state_add(walker);
-                                       lwalk->cur = nexte;
-                                       lwalk->lastv = v;
+               vert_edge_tot = BM_vert_edge_count_nonwire(v);
 
-                                       lwalk->is_boundary = owalk.is_boundary;
-                                       lwalk->is_single = owalk.is_single;
-                                       lwalk->f_hub = owalk.f_hub;
+               /* check if we should step, this is fairly involved */
+               if (
+                       /* walk over boundary of faces but stop at corners */
+                       (owalk.is_single == false && vert_edge_tot > 2) ||
 
-                                       BLI_ghash_insert(walker->visithash, nexte, NULL);
+                       /* initial edge was a boundary, so is this edge and vertex is only apart of this face
+                        * this lets us walk over the the boundary of an ngon which is handy */
+                       (owalk.is_single == true && vert_edge_tot == 2 && BM_edge_is_boundary(e)))
+               {
+                       /* find next boundary edge in the fan */
+                       do {
+                               l = BM_loop_other_edge_loop(l, v);
+                               if (BM_edge_is_manifold(l->e)) {
+                                       l = l->radial_next;
+                               }
+                               else if (BM_edge_is_boundary(l->e)) {
+                                       break;
+                               }
+                               else {
+                                       l = NULL;
+                                       break;
                                }
+                       } while (true);
+               }
+
+               if (l != NULL) {
+                       if (l != e->l &&
+                           bmw_mask_check_edge(walker, l->e) &&
+                           !BLI_ghash_haskey(walker->visithash, l->e))
+                       {
+                               lwalk = BMW_state_add(walker);
+                               lwalk->cur = l->e;
+                               lwalk->lastv = v;
+
+                               lwalk->is_boundary = owalk.is_boundary;
+                               lwalk->is_single = owalk.is_single;
+                               lwalk->f_hub = owalk.f_hub;
+
+                               BLI_ghash_insert(walker->visithash, l->e, NULL);
                        }
                }
        }