Blender  V2.93
bmesh_walkers_impl.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
23 #include <string.h>
24 
25 #include "BLI_utildefines.h"
26 
27 #include "BKE_customdata.h"
28 
29 #include "bmesh.h"
31 
32 /* Pop into stack memory (common operation). */
33 #define BMW_state_remove_r(walker, owalk) \
34  { \
35  memcpy(owalk, BMW_current_state(walker), sizeof(*(owalk))); \
36  BMW_state_remove(walker); \
37  } \
38  (void)0
39 
40 /* -------------------------------------------------------------------- */
44 static bool bmw_mask_check_vert(BMWalker *walker, BMVert *v)
45 {
47  return false;
48  }
49  if (walker->mask_vert && !BMO_vert_flag_test(walker->bm, v, walker->mask_vert)) {
50  return false;
51  }
52  return true;
53 }
54 
55 static bool bmw_mask_check_edge(BMWalker *walker, BMEdge *e)
56 {
58  return false;
59  }
60  if (walker->mask_edge && !BMO_edge_flag_test(walker->bm, e, walker->mask_edge)) {
61  return false;
62  }
63  return true;
64 }
65 
66 static bool bmw_mask_check_face(BMWalker *walker, BMFace *f)
67 {
69  return false;
70  }
71  if (walker->mask_face && !BMO_face_flag_test(walker->bm, f, walker->mask_face)) {
72  return false;
73  }
74  return true;
75 }
76 
79 /* -------------------------------------------------------------------- */
86 static bool bmw_edge_is_wire(const BMWalker *walker, const BMEdge *e)
87 {
88  if (walker->flag & BMW_FLAG_TEST_HIDDEN) {
89  /* Check if this is a wire edge, ignoring hidden faces. */
90  if (BM_edge_is_wire(e)) {
91  return true;
92  }
94  }
95  return BM_edge_is_wire(e);
96 }
99 /* -------------------------------------------------------------------- */
111 {
112  BMwShellWalker *shellWalk = NULL;
113 
114  if (BLI_gset_haskey(walker->visit_set, e)) {
115  return;
116  }
117 
118  if (!bmw_mask_check_edge(walker, e)) {
119  return;
120  }
121 
122  shellWalk = BMW_state_add(walker);
123  shellWalk->curedge = e;
124  BLI_gset_insert(walker->visit_set, e);
125 }
126 
127 static void bmw_VertShellWalker_begin(BMWalker *walker, void *data)
128 {
129  BMIter eiter;
130  BMHeader *h = data;
131  BMEdge *e;
132  BMVert *v;
133 
134  if (UNLIKELY(h == NULL)) {
135  return;
136  }
137 
138  switch (h->htype) {
139  case BM_VERT: {
140  /* Starting the walk at a vert, add all the edges to the work-list. */
141  v = (BMVert *)h;
142  BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
144  }
145  break;
146  }
147 
148  case BM_EDGE: {
149  /* Starting the walk at an edge, add the single edge to the work-list. */
150  e = (BMEdge *)h;
152  break;
153  }
154  default:
155  BLI_assert(0);
156  }
157 }
158 
159 static void *bmw_VertShellWalker_yield(BMWalker *walker)
160 {
161  BMwShellWalker *shellWalk = BMW_current_state(walker);
162  return shellWalk->curedge;
163 }
164 
165 static void *bmw_VertShellWalker_step(BMWalker *walker)
166 {
167  BMwShellWalker *swalk, owalk;
168  BMEdge *e, *e2;
169  BMVert *v;
170  BMIter iter;
171  int i;
172 
173  BMW_state_remove_r(walker, &owalk);
174  swalk = &owalk;
175 
176  e = swalk->curedge;
177 
178  for (i = 0; i < 2; i++) {
179  v = i ? e->v2 : e->v1;
180  BM_ITER_ELEM (e2, &iter, v, BM_EDGES_OF_VERT) {
181  bmw_VertShellWalker_visitEdge(walker, e2);
182  }
183  }
184 
185  return e;
186 }
187 
188 #if 0
189 static void *bmw_VertShellWalker_step(BMWalker *walker)
190 {
191  BMEdge *curedge, *next = NULL;
192  BMVert *v_old = NULL;
193  bool restrictpass = true;
194  BMwShellWalker shellWalk = *((BMwShellWalker *)BMW_current_state(walker));
195 
196  if (!BLI_gset_haskey(walker->visit_set, shellWalk.base)) {
197  BLI_gset_insert(walker->visit_set, shellWalk.base);
198  }
199 
200  BMW_state_remove(walker);
201 
202  /* Find the next edge whose other vertex has not been visited. */
203  curedge = shellWalk.curedge;
204  do {
205  if (!BLI_gset_haskey(walker->visit_set, curedge)) {
206  if (!walker->restrictflag ||
207  (walker->restrictflag &&
208  BMO_edge_flag_test(walker->bm, curedge, walker->restrictflag))) {
209  BMwShellWalker *newstate;
210 
211  v_old = BM_edge_other_vert(curedge, shellWalk.base);
212 
213  /* Push a new state onto the stack. */
214  newState = BMW_state_add(walker);
215  BLI_gset_insert(walker->visit_set, curedge);
216 
217  /* Populate the new state. */
218 
219  newState->base = v_old;
220  newState->curedge = curedge;
221  }
222  }
223  } while ((curedge = bmesh_disk_edge_next(curedge, shellWalk.base)) != shellWalk.curedge);
224 
225  return shellWalk.curedge;
226 }
227 #endif
228 
231 /* -------------------------------------------------------------------- */
240 {
241  BMwLoopShellWalker *shellWalk = NULL;
242 
243  if (BLI_gset_haskey(walker->visit_set, l)) {
244  return;
245  }
246 
247  if (!bmw_mask_check_face(walker, l->f)) {
248  return;
249  }
250 
251  shellWalk = BMW_state_add(walker);
252  shellWalk->curloop = l;
253  BLI_gset_insert(walker->visit_set, l);
254 }
255 
256 static void bmw_LoopShellWalker_begin(BMWalker *walker, void *data)
257 {
258  BMIter iter;
259  BMHeader *h = data;
260 
261  if (UNLIKELY(h == NULL)) {
262  return;
263  }
264 
265  switch (h->htype) {
266  case BM_LOOP: {
267  /* Starting the walk at a vert, add all the edges to the work-list. */
268  BMLoop *l = (BMLoop *)h;
270  break;
271  }
272 
273  case BM_VERT: {
274  BMVert *v = (BMVert *)h;
275  BMLoop *l;
276  BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
278  }
279  break;
280  }
281  case BM_EDGE: {
282  BMEdge *e = (BMEdge *)h;
283  BMLoop *l;
284  BM_ITER_ELEM (l, &iter, e, BM_LOOPS_OF_EDGE) {
286  }
287  break;
288  }
289  case BM_FACE: {
290  BMFace *f = (BMFace *)h;
292  /* Walker will handle other loops within the face. */
294  break;
295  }
296  default:
297  BLI_assert(0);
298  }
299 }
300 
301 static void *bmw_LoopShellWalker_yield(BMWalker *walker)
302 {
303  BMwLoopShellWalker *shellWalk = BMW_current_state(walker);
304  return shellWalk->curloop;
305 }
306 
308 {
309  BMEdge *e_edj_pair[2];
310  int i;
311 
312  /* Seems paranoid, but one caller also walks edges. */
314 
317 
318  e_edj_pair[0] = l->e;
319  e_edj_pair[1] = l->prev->e;
320 
321  for (i = 0; i < 2; i++) {
322  BMEdge *e = e_edj_pair[i];
323  if (bmw_mask_check_edge(walker, e)) {
324  BMLoop *l_iter, *l_first;
325 
326  l_iter = l_first = e->l;
327  do {
328  BMLoop *l_radial = (l_iter->v == l->v) ? l_iter : l_iter->next;
329  BLI_assert(l_radial->v == l->v);
330  if (l != l_radial) {
331  bmw_LoopShellWalker_visitLoop(walker, l_radial);
332  }
333  } while ((l_iter = l_iter->radial_next) != l_first);
334  }
335  }
336 }
337 
338 static void *bmw_LoopShellWalker_step(BMWalker *walker)
339 {
340  BMwLoopShellWalker *swalk, owalk;
341  BMLoop *l;
342 
343  BMW_state_remove_r(walker, &owalk);
344  swalk = &owalk;
345 
346  l = swalk->curloop;
348 
349  return l;
350 }
351 
354 /* -------------------------------------------------------------------- */
368 {
369  BMwLoopShellWireWalker *shellWalk = NULL;
370 
371  BLI_assert(bmw_edge_is_wire(walker, e));
372 
373  if (BLI_gset_haskey(walker->visit_set_alt, e)) {
374  return;
375  }
376 
377  if (!bmw_mask_check_edge(walker, e)) {
378  return;
379  }
380 
381  shellWalk = BMW_state_add(walker);
382  shellWalk->curelem = (BMElem *)e;
383  BLI_gset_insert(walker->visit_set_alt, e);
384 }
385 
386 static void bmw_LoopShellWireWalker_visitVert(BMWalker *walker, BMVert *v, const BMEdge *e_from)
387 {
388  BMEdge *e;
389 
391 
392  if (BLI_gset_haskey(walker->visit_set_alt, v)) {
393  return;
394  }
395 
396  if (!bmw_mask_check_vert(walker, v)) {
397  return;
398  }
399 
400  e = v->e;
401  do {
402  if (bmw_edge_is_wire(walker, e) && (e != e_from)) {
403  BMVert *v_other;
404  BMIter iter;
405  BMLoop *l;
406 
408 
409  /* Check if we step onto a non-wire vertex. */
410  v_other = BM_edge_other_vert(e, v);
411  BM_ITER_ELEM (l, &iter, v_other, BM_LOOPS_OF_VERT) {
412 
414  }
415  }
416  } while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
417 
418  BLI_gset_insert(walker->visit_set_alt, v);
419 }
420 
421 static void bmw_LoopShellWireWalker_begin(BMWalker *walker, void *data)
422 {
423  BMHeader *h = data;
424 
425  if (UNLIKELY(h == NULL)) {
426  return;
427  }
428 
430 
431  switch (h->htype) {
432  case BM_LOOP: {
433  BMLoop *l = (BMLoop *)h;
435  break;
436  }
437 
438  case BM_VERT: {
439  BMVert *v = (BMVert *)h;
440  if (v->e) {
442  }
443  break;
444  }
445  case BM_EDGE: {
446  BMEdge *e = (BMEdge *)h;
447  if (bmw_mask_check_edge(walker, e)) {
450  }
451  else if (e->l) {
452  BMLoop *l_iter, *l_first;
453 
454  l_iter = l_first = e->l;
455  do {
456  bmw_LoopShellWalker_visitLoop(walker, l_iter);
457  bmw_LoopShellWalker_visitLoop(walker, l_iter->next);
458  } while ((l_iter = l_iter->radial_next) != l_first);
459  }
460  break;
461  }
462  case BM_FACE: {
463  /* Wire verts will be walked over. */
464  break;
465  }
466  default:
467  BLI_assert(0);
468  }
469 }
470 
472 {
473  BMwLoopShellWireWalker *shellWalk = BMW_current_state(walker);
474  return shellWalk->curelem;
475 }
476 
478 {
479  BMwLoopShellWireWalker *swalk, owalk;
480 
481  BMW_state_remove_r(walker, &owalk);
482  swalk = &owalk;
483 
484  if (swalk->curelem->head.htype == BM_LOOP) {
485  BMLoop *l = (BMLoop *)swalk->curelem;
486 
488 
490 
491  return l;
492  }
493 
494  BMEdge *e = (BMEdge *)swalk->curelem;
495 
497 
498  bmw_LoopShellWireWalker_visitVert(walker, e->v1, e);
499  bmw_LoopShellWireWalker_visitVert(walker, e->v2, e);
500 
501  return e;
502 }
503 
506 /* -------------------------------------------------------------------- */
513 {
514  BMwShellWalker *shellWalk = NULL;
515 
516  if (BLI_gset_haskey(walker->visit_set, e)) {
517  return;
518  }
519 
520  if (!bmw_mask_check_edge(walker, e)) {
521  return;
522  }
523 
524  shellWalk = BMW_state_add(walker);
525  shellWalk->curedge = e;
526  BLI_gset_insert(walker->visit_set, e);
527 }
528 
529 static void bmw_FaceShellWalker_begin(BMWalker *walker, void *data)
530 {
531  BMEdge *e = data;
533 }
534 
535 static void *bmw_FaceShellWalker_yield(BMWalker *walker)
536 {
537  BMwShellWalker *shellWalk = BMW_current_state(walker);
538  return shellWalk->curedge;
539 }
540 
541 static void *bmw_FaceShellWalker_step(BMWalker *walker)
542 {
543  BMwShellWalker *swalk, owalk;
544  BMEdge *e, *e2;
545  BMIter iter;
546 
547  BMW_state_remove_r(walker, &owalk);
548  swalk = &owalk;
549 
550  e = swalk->curedge;
551 
552  if (e->l) {
553  BMLoop *l_iter, *l_first;
554 
555  l_iter = l_first = e->l;
556  do {
557  BM_ITER_ELEM (e2, &iter, l_iter->f, BM_EDGES_OF_FACE) {
558  if (e2 != e) {
559  bmw_FaceShellWalker_visitEdge(walker, e2);
560  }
561  }
562  } while ((l_iter = l_iter->radial_next) != l_first);
563  }
564 
565  return e;
566 }
569 /* -------------------------------------------------------------------- */
577 {
579 
580  if (BLI_gset_haskey(walker->visit_set, v)) {
581  /* Already visited. */
582  return;
583  }
584 
585  if (!bmw_mask_check_vert(walker, v)) {
586  /* Not flagged for walk. */
587  return;
588  }
589 
590  vwalk = BMW_state_add(walker);
591  vwalk->curvert = v;
592  BLI_gset_insert(walker->visit_set, v);
593 }
594 
595 static void bmw_ConnectedVertexWalker_begin(BMWalker *walker, void *data)
596 {
597  BMVert *v = data;
599 }
600 
602 {
604  return vwalk->curvert;
605 }
606 
608 {
609  BMwConnectedVertexWalker *vwalk, owalk;
610  BMVert *v, *v2;
611  BMEdge *e;
612  BMIter iter;
613 
614  BMW_state_remove_r(walker, &owalk);
615  vwalk = &owalk;
616 
617  v = vwalk->curvert;
618 
619  BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
620  v2 = BM_edge_other_vert(e, v);
621  if (!BLI_gset_haskey(walker->visit_set, v2)) {
623  }
624  }
625 
626  return v;
627 }
628 
631 /* -------------------------------------------------------------------- */
643 static void bmw_IslandboundWalker_begin(BMWalker *walker, void *data)
644 {
645  BMLoop *l = data;
646  BMwIslandboundWalker *iwalk = NULL;
647 
648  iwalk = BMW_state_add(walker);
649 
650  iwalk->base = iwalk->curloop = l;
651  iwalk->lastv = l->v;
652 
653  BLI_gset_insert(walker->visit_set, data);
654 }
655 
657 {
658  BMwIslandboundWalker *iwalk = BMW_current_state(walker);
659 
660  return iwalk->curloop;
661 }
662 
664 {
665  BMwIslandboundWalker *iwalk, owalk;
666  BMVert *v;
667  BMEdge *e;
668  BMFace *f;
669  BMLoop *l;
670 
671  memcpy(&owalk, BMW_current_state(walker), sizeof(owalk));
672  /* Normally we'd remove here, but delay until after error checking. */
673  iwalk = &owalk;
674 
675  l = iwalk->curloop;
676  e = l->e;
677 
678  v = BM_edge_other_vert(e, iwalk->lastv);
679 
680  /* Pop off current state. */
681  BMW_state_remove(walker);
682 
683  f = l->f;
684 
685  while (1) {
687  if (BM_loop_is_manifold(l)) {
688  l = l->radial_next;
689  f = l->f;
690  e = l->e;
691 
692  if (!bmw_mask_check_face(walker, f)) {
693  l = l->radial_next;
694  break;
695  }
696  }
697  else {
698  /* Treat non-manifold edges as boundaries. */
699  f = l->f;
700  e = l->e;
701  break;
702  }
703  }
704 
705  if (l == owalk.curloop) {
706  return NULL;
707  }
708  if (BLI_gset_haskey(walker->visit_set, l)) {
709  return owalk.curloop;
710  }
711 
712  BLI_gset_insert(walker->visit_set, l);
713  iwalk = BMW_state_add(walker);
714  iwalk->base = owalk.base;
715 
716 #if 0
717  if (!BMO_face_flag_test(walker->bm, l->f, walker->restrictflag)) {
718  iwalk->curloop = l->radial_next;
719  }
720  else {
721  iwalk->curloop = l;
722  }
723 #else
724  iwalk->curloop = l;
725 #endif
726  iwalk->lastv = v;
727 
728  return owalk.curloop;
729 }
730 
731 /* -------------------------------------------------------------------- */
738 static void bmw_IslandWalker_begin(BMWalker *walker, void *data)
739 {
740  BMwIslandWalker *iwalk = NULL;
741 
742  if (!bmw_mask_check_face(walker, data)) {
743  return;
744  }
745 
746  iwalk = BMW_state_add(walker);
747  BLI_gset_insert(walker->visit_set, data);
748 
749  iwalk->cur = data;
750 }
751 
752 static void *bmw_IslandWalker_yield(BMWalker *walker)
753 {
754  BMwIslandWalker *iwalk = BMW_current_state(walker);
755 
756  return iwalk->cur;
757 }
758 
759 static void *bmw_IslandWalker_step_ex(BMWalker *walker, bool only_manifold)
760 {
761  BMwIslandWalker *iwalk, owalk;
762  BMLoop *l_iter, *l_first;
763 
764  BMW_state_remove_r(walker, &owalk);
765  iwalk = &owalk;
766 
767  l_iter = l_first = BM_FACE_FIRST_LOOP(iwalk->cur);
768  do {
769  /* Could skip loop here too, but don't add unless we need it. */
770  if (!bmw_mask_check_edge(walker, l_iter->e)) {
771  continue;
772  }
773 
774  BMLoop *l_radial_iter;
775 
776  if (only_manifold && (l_iter->radial_next != l_iter)) {
777  int face_count = 1;
778  /* Check other faces (not this one), ensure only one other Can be walked onto. */
779  l_radial_iter = l_iter->radial_next;
780  do {
781  if (bmw_mask_check_face(walker, l_radial_iter->f)) {
782  face_count++;
783  if (face_count == 3) {
784  break;
785  }
786  }
787  } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter);
788 
789  if (face_count != 2) {
790  continue;
791  }
792  }
793 
794  l_radial_iter = l_iter;
795  while ((l_radial_iter = l_radial_iter->radial_next) != l_iter) {
796  BMFace *f = l_radial_iter->f;
797 
798  if (!bmw_mask_check_face(walker, f)) {
799  continue;
800  }
801 
802  /* Saves checking #BLI_gset_haskey below (manifold edges there's a 50% chance). */
803  if (f == iwalk->cur) {
804  continue;
805  }
806 
807  if (BLI_gset_haskey(walker->visit_set, f)) {
808  continue;
809  }
810 
811  iwalk = BMW_state_add(walker);
812  iwalk->cur = f;
813  BLI_gset_insert(walker->visit_set, f);
814  break;
815  }
816  } while ((l_iter = l_iter->next) != l_first);
817 
818  return owalk.cur;
819 }
820 
821 static void *bmw_IslandWalker_step(BMWalker *walker)
822 {
823  return bmw_IslandWalker_step_ex(walker, false);
824 }
825 
830 {
831  return bmw_IslandWalker_step_ex(walker, true);
832 }
833 
836 /* -------------------------------------------------------------------- */
842 /* utility function to see if an edge is a part of an ngon boundary */
844 {
845  return ((BM_edge_is_boundary(e)) && (e->l->f->len > 4) &&
846  (BM_edge_is_boundary(e->l->next->e) || BM_edge_is_boundary(e->l->prev->e)));
847 }
848 
849 static void bmw_EdgeLoopWalker_begin(BMWalker *walker, void *data)
850 {
851  BMwEdgeLoopWalker *lwalk = NULL, owalk, *owalk_pt;
852  BMEdge *e = data;
853  BMVert *v;
854  const int vert_edge_count[2] = {
857  };
858  const int vert_face_count[2] = {
859  BM_vert_face_count(e->v1),
860  BM_vert_face_count(e->v2),
861  };
862 
863  v = e->v1;
864 
865  lwalk = BMW_state_add(walker);
866  BLI_gset_insert(walker->visit_set, e);
867 
868  lwalk->cur = lwalk->start = e;
869  lwalk->lastv = lwalk->startv = v;
871  lwalk->is_single = (lwalk->is_boundary && bm_edge_is_single(e));
872 
937  if ((lwalk->is_boundary == false) &&
938  /* Without checking the face count, the 3 edges could be this edge
939  * plus two boundary edges (which would not be stepped over), see T84906. */
940  ((vert_edge_count[0] == 3 && vert_face_count[0] == 3) ||
941  (vert_edge_count[1] == 3 && vert_face_count[1] == 3))) {
942  BMIter iter;
943  BMFace *f_iter;
944  BMFace *f_best = NULL;
945 
946  BM_ITER_ELEM (f_iter, &iter, e, BM_FACES_OF_EDGE) {
947  if (f_best == NULL || f_best->len < f_iter->len) {
948  f_best = f_iter;
949  }
950  }
951 
952  if (f_best) {
953  /* Only use hub selection for 5+ sides else this could
954  * conflict with normal edge loop selection. */
955  lwalk->f_hub = f_best->len > 4 ? f_best : NULL;
956  }
957  else {
958  /* Edge doesn't have any faces connected to it. */
959  lwalk->f_hub = NULL;
960  }
961  }
962  else {
963  lwalk->f_hub = NULL;
964  }
965 
966  /* Rewind. */
967  while ((owalk_pt = BMW_current_state(walker))) {
968  owalk = *((BMwEdgeLoopWalker *)owalk_pt);
969  BMW_walk(walker);
970  }
971 
972  lwalk = BMW_state_add(walker);
973  *lwalk = owalk;
974 
975  lwalk->lastv = lwalk->startv = BM_edge_other_vert(owalk.cur, lwalk->lastv);
976 
977  BLI_gset_clear(walker->visit_set, NULL);
978  BLI_gset_insert(walker->visit_set, owalk.cur);
979 }
980 
981 static void *bmw_EdgeLoopWalker_yield(BMWalker *walker)
982 {
983  BMwEdgeLoopWalker *lwalk = BMW_current_state(walker);
984 
985  return lwalk->cur;
986 }
987 
988 static void *bmw_EdgeLoopWalker_step(BMWalker *walker)
989 {
990  BMwEdgeLoopWalker *lwalk, owalk;
991  BMEdge *e, *nexte = NULL;
992  BMLoop *l;
993  BMVert *v;
994 
995  BMW_state_remove_r(walker, &owalk);
996  lwalk = &owalk;
997 
998  e = lwalk->cur;
999  l = e->l;
1000 
1001  if (owalk.f_hub) { /* NGON EDGE */
1002  int vert_edge_tot;
1003 
1004  v = BM_edge_other_vert(e, lwalk->lastv);
1005 
1006  vert_edge_tot = BM_vert_edge_count_nonwire(v);
1007 
1008  if (vert_edge_tot == 3) {
1009  l = BM_face_other_vert_loop(owalk.f_hub, lwalk->lastv, v);
1010  nexte = BM_edge_exists(v, l->v);
1011 
1012  if (bmw_mask_check_edge(walker, nexte) && !BLI_gset_haskey(walker->visit_set, nexte) &&
1013  /* Never step onto a boundary edge, this gives odd-results. */
1014  (BM_edge_is_boundary(nexte) == false)) {
1015  lwalk = BMW_state_add(walker);
1016  lwalk->cur = nexte;
1017  lwalk->lastv = v;
1018 
1019  lwalk->is_boundary = owalk.is_boundary;
1020  lwalk->is_single = owalk.is_single;
1021  lwalk->f_hub = owalk.f_hub;
1022 
1023  BLI_gset_insert(walker->visit_set, nexte);
1024  }
1025  }
1026  }
1027  else if (l == NULL) { /* WIRE EDGE */
1028  BMIter eiter;
1029 
1030  /* Match trunk: mark all connected wire edges. */
1031  for (int i = 0; i < 2; i++) {
1032  v = i ? e->v2 : e->v1;
1033 
1034  BM_ITER_ELEM (nexte, &eiter, v, BM_EDGES_OF_VERT) {
1035  if ((nexte->l == NULL) && bmw_mask_check_edge(walker, nexte) &&
1036  !BLI_gset_haskey(walker->visit_set, nexte)) {
1037  lwalk = BMW_state_add(walker);
1038  lwalk->cur = nexte;
1039  lwalk->lastv = v;
1040 
1041  lwalk->is_boundary = owalk.is_boundary;
1042  lwalk->is_single = owalk.is_single;
1043  lwalk->f_hub = owalk.f_hub;
1044 
1045  BLI_gset_insert(walker->visit_set, nexte);
1046  }
1047  }
1048  }
1049  }
1050  else if (owalk.is_boundary == false) { /* NORMAL EDGE WITH FACES */
1051  int vert_edge_tot;
1052 
1053  v = BM_edge_other_vert(e, lwalk->lastv);
1054 
1055  vert_edge_tot = BM_vert_edge_count_nonwire(v);
1056 
1057  /* Typical looping over edges in the middle of a mesh.
1058  * Why use 2 here at all? - for internal ngon loops it can be useful. */
1059  if (ELEM(vert_edge_tot, 4, 2)) {
1060  int i_opposite = vert_edge_tot / 2;
1061  int i = 0;
1062  do {
1064  if (BM_edge_is_manifold(l->e)) {
1065  l = l->radial_next;
1066  }
1067  else {
1068  l = NULL;
1069  break;
1070  }
1071  } while ((++i != i_opposite));
1072  }
1073  else {
1074  l = NULL;
1075  }
1076 
1077  if (l != NULL) {
1078  if (l != e->l && bmw_mask_check_edge(walker, l->e) &&
1079  !BLI_gset_haskey(walker->visit_set, l->e)) {
1080  lwalk = BMW_state_add(walker);
1081  lwalk->cur = l->e;
1082  lwalk->lastv = v;
1083 
1084  lwalk->is_boundary = owalk.is_boundary;
1085  lwalk->is_single = owalk.is_single;
1086  lwalk->f_hub = owalk.f_hub;
1087 
1088  BLI_gset_insert(walker->visit_set, l->e);
1089  }
1090  }
1091  }
1092  else if (owalk.is_boundary == true) { /* BOUNDARY EDGE WITH FACES */
1093  int vert_edge_tot;
1094 
1095  v = BM_edge_other_vert(e, lwalk->lastv);
1096 
1097  vert_edge_tot = BM_vert_edge_count_nonwire(v);
1098 
1099  /* Check if we should step, this is fairly involved. */
1100  if (
1101  /* Walk over boundary of faces but stop at corners. */
1102  (owalk.is_single == false && vert_edge_tot > 2) ||
1103 
1104  /* Initial edge was a boundary, so is this edge and vertex is only a part of this face
1105  * this lets us walk over the boundary of an ngon which is handy. */
1106  (owalk.is_single == true && vert_edge_tot == 2 && BM_edge_is_boundary(e))) {
1107  /* Find next boundary edge in the fan. */
1108  do {
1110  if (BM_edge_is_manifold(l->e)) {
1111  l = l->radial_next;
1112  }
1113  else if (BM_edge_is_boundary(l->e)) {
1114  break;
1115  }
1116  else {
1117  l = NULL;
1118  break;
1119  }
1120  } while (true);
1121  }
1122 
1123  if (owalk.is_single == false && l && bm_edge_is_single(l->e)) {
1124  l = NULL;
1125  }
1126 
1127  if (l != NULL) {
1128  if (l != e->l && bmw_mask_check_edge(walker, l->e) &&
1129  !BLI_gset_haskey(walker->visit_set, l->e)) {
1130  lwalk = BMW_state_add(walker);
1131  lwalk->cur = l->e;
1132  lwalk->lastv = v;
1133 
1134  lwalk->is_boundary = owalk.is_boundary;
1135  lwalk->is_single = owalk.is_single;
1136  lwalk->f_hub = owalk.f_hub;
1137 
1138  BLI_gset_insert(walker->visit_set, l->e);
1139  }
1140  }
1141  }
1142 
1143  return owalk.cur;
1144 }
1145 
1148 /* -------------------------------------------------------------------- */
1161 {
1162  /* Face must have degree 4. */
1163  if (l->f->len != 4) {
1164  return false;
1165  }
1166 
1167  if (!bmw_mask_check_face(walker, l->f)) {
1168  return false;
1169  }
1170 
1171  /* The face must not have been already visited. */
1172  if (BLI_gset_haskey(walker->visit_set, l->f) && BLI_gset_haskey(walker->visit_set_alt, l->e)) {
1173  return false;
1174  }
1175 
1176  return true;
1177 }
1178 
1179 /* Check whether the face loop can start from the given edge. */
1181 {
1182  /* There is no face loop starting from a wire edge. */
1183  if (BM_edge_is_wire(e)) {
1184  return false;
1185  }
1186 
1187  /* Don't start a loop from a boundary edge if it cannot be extended to cover any faces. */
1188  if (BM_edge_is_boundary(e)) {
1189  if (!bmw_FaceLoopWalker_include_face(walker, e->l)) {
1190  return false;
1191  }
1192  }
1193 
1194  /* Don't start a face loop from non-manifold edges. */
1195  if (!BM_edge_is_manifold(e)) {
1196  return false;
1197  }
1198 
1199  return true;
1200 }
1201 
1202 static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data)
1203 {
1204  BMwFaceLoopWalker *lwalk, owalk, *owalk_pt;
1205  BMEdge *e = data;
1206  /* BMesh *bm = walker->bm; */ /* UNUSED */
1207  /* int fcount = BM_edge_face_count(e); */ /* UNUSED */
1208 
1209  if (!bmw_FaceLoopWalker_edge_begins_loop(walker, e)) {
1210  return;
1211  }
1212 
1213  lwalk = BMW_state_add(walker);
1214  lwalk->l = e->l;
1215  lwalk->no_calc = false;
1216  BLI_gset_insert(walker->visit_set, lwalk->l->f);
1217 
1218  /* Rewind. */
1219  while ((owalk_pt = BMW_current_state(walker))) {
1220  owalk = *((BMwFaceLoopWalker *)owalk_pt);
1221  BMW_walk(walker);
1222  }
1223 
1224  lwalk = BMW_state_add(walker);
1225  *lwalk = owalk;
1226  lwalk->no_calc = false;
1227 
1228  BLI_gset_clear(walker->visit_set_alt, NULL);
1229  BLI_gset_insert(walker->visit_set_alt, lwalk->l->e);
1230 
1231  BLI_gset_clear(walker->visit_set, NULL);
1232  BLI_gset_insert(walker->visit_set, lwalk->l->f);
1233 }
1234 
1235 static void *bmw_FaceLoopWalker_yield(BMWalker *walker)
1236 {
1237  BMwFaceLoopWalker *lwalk = BMW_current_state(walker);
1238 
1239  if (!lwalk) {
1240  return NULL;
1241  }
1242 
1243  return lwalk->l->f;
1244 }
1245 
1246 static void *bmw_FaceLoopWalker_step(BMWalker *walker)
1247 {
1248  BMwFaceLoopWalker *lwalk, owalk;
1249  BMFace *f;
1250  BMLoop *l;
1251 
1252  BMW_state_remove_r(walker, &owalk);
1253  lwalk = &owalk;
1254 
1255  f = lwalk->l->f;
1256  l = lwalk->l->radial_next;
1257 
1258  if (lwalk->no_calc) {
1259  return f;
1260  }
1261 
1262  if (!bmw_FaceLoopWalker_include_face(walker, l)) {
1263  l = lwalk->l;
1264  l = l->next->next;
1265  if (!BM_edge_is_manifold(l->e)) {
1266  l = l->prev->prev;
1267  }
1268  l = l->radial_next;
1269  }
1270 
1271  if (bmw_FaceLoopWalker_include_face(walker, l)) {
1272  lwalk = BMW_state_add(walker);
1273  lwalk->l = l;
1274 
1275  if (l->f->len != 4) {
1276  lwalk->no_calc = true;
1277  lwalk->l = owalk.l;
1278  }
1279  else {
1280  lwalk->no_calc = false;
1281  }
1282 
1283  /* Both may already exist. */
1284  BLI_gset_add(walker->visit_set_alt, l->e);
1285  BLI_gset_add(walker->visit_set, l->f);
1286  }
1287 
1288  return f;
1289 }
1290 
1293 // #define BMW_EDGERING_NGON
1294 
1295 /* -------------------------------------------------------------------- */
1302 static void bmw_EdgeringWalker_begin(BMWalker *walker, void *data)
1303 {
1304  BMwEdgeringWalker *lwalk, owalk, *owalk_pt;
1305  BMEdge *e = data;
1306 
1307  lwalk = BMW_state_add(walker);
1308  lwalk->l = e->l;
1309 
1310  if (!lwalk->l) {
1311  lwalk->wireedge = e;
1312  return;
1313  }
1314  lwalk->wireedge = NULL;
1315 
1316  BLI_gset_insert(walker->visit_set, lwalk->l->e);
1317 
1318  /* Rewind. */
1319  while ((owalk_pt = BMW_current_state(walker))) {
1320  owalk = *((BMwEdgeringWalker *)owalk_pt);
1321  BMW_walk(walker);
1322  }
1323 
1324  lwalk = BMW_state_add(walker);
1325  *lwalk = owalk;
1326 
1327 #ifdef BMW_EDGERING_NGON
1328  if (lwalk->l->f->len % 2 != 0)
1329 #else
1330  if (lwalk->l->f->len != 4)
1331 #endif
1332  {
1333  lwalk->l = lwalk->l->radial_next;
1334  }
1335 
1336  BLI_gset_clear(walker->visit_set, NULL);
1337  BLI_gset_insert(walker->visit_set, lwalk->l->e);
1338 }
1339 
1340 static void *bmw_EdgeringWalker_yield(BMWalker *walker)
1341 {
1342  BMwEdgeringWalker *lwalk = BMW_current_state(walker);
1343 
1344  if (!lwalk) {
1345  return NULL;
1346  }
1347 
1348  if (lwalk->l) {
1349  return lwalk->l->e;
1350  }
1351  return lwalk->wireedge;
1352 }
1353 
1354 static void *bmw_EdgeringWalker_step(BMWalker *walker)
1355 {
1356  BMwEdgeringWalker *lwalk, owalk;
1357  BMEdge *e;
1358  BMLoop *l;
1359 #ifdef BMW_EDGERING_NGON
1360  int i, len;
1361 #endif
1362 
1363 #define EDGE_CHECK(e) \
1364  (bmw_mask_check_edge(walker, e) && (BM_edge_is_boundary(e) || BM_edge_is_manifold(e)))
1365 
1366  BMW_state_remove_r(walker, &owalk);
1367  lwalk = &owalk;
1368 
1369  l = lwalk->l;
1370  if (!l) {
1371  return lwalk->wireedge;
1372  }
1373 
1374  e = l->e;
1375  if (!EDGE_CHECK(e)) {
1376  /* Walker won't traverse to a non-manifold edge, but may
1377  * be started on one, and should not traverse *away* from
1378  * a non-manifold edge (non-manifold edges are never in an
1379  * edge ring with manifold edges. */
1380  return e;
1381  }
1382 
1383 #ifdef BMW_EDGERING_NGON
1384  l = l->radial_next;
1385 
1386  i = len = l->f->len;
1387  while (i > 0) {
1388  l = l->next;
1389  i -= 2;
1390  }
1391 
1392  if ((len <= 0) || (len % 2 != 0) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) {
1393  l = owalk.l;
1394  i = len;
1395  while (i > 0) {
1396  l = l->next;
1397  i -= 2;
1398  }
1399  }
1400  /* Only walk to manifold edge. */
1401  if ((l->f->len % 2 == 0) && EDGE_CHECK(l->e) && !BLI_gset_haskey(walker->visit_set, l->e))
1402 #else
1403 
1404  l = l->radial_next;
1405  l = l->next->next;
1406 
1407  if ((l->f->len != 4) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) {
1408  l = owalk.l->next->next;
1409  }
1410  /* Only walk to manifold edge. */
1411  if ((l->f->len == 4) && EDGE_CHECK(l->e) && !BLI_gset_haskey(walker->visit_set, l->e))
1412 #endif
1413  {
1414  lwalk = BMW_state_add(walker);
1415  lwalk->l = l;
1416  lwalk->wireedge = NULL;
1417 
1418  BLI_gset_insert(walker->visit_set, l->e);
1419  }
1420 
1421  return e;
1422 
1423 #undef EDGE_CHECK
1424 }
1425 
1428 /* -------------------------------------------------------------------- */
1432 static void bmw_EdgeboundaryWalker_begin(BMWalker *walker, void *data)
1433 {
1434  BMwEdgeboundaryWalker *lwalk;
1435  BMEdge *e = data;
1436 
1438 
1439  if (BLI_gset_haskey(walker->visit_set, e)) {
1440  return;
1441  }
1442 
1443  lwalk = BMW_state_add(walker);
1444  lwalk->e = e;
1445  BLI_gset_insert(walker->visit_set, e);
1446 }
1447 
1449 {
1450  BMwEdgeboundaryWalker *lwalk = BMW_current_state(walker);
1451 
1452  if (!lwalk) {
1453  return NULL;
1454  }
1455 
1456  return lwalk->e;
1457 }
1458 
1460 {
1461  BMwEdgeboundaryWalker *lwalk, owalk;
1462  BMEdge *e, *e_other;
1463  BMVert *v;
1464  BMIter eiter;
1465  BMIter viter;
1466 
1467  BMW_state_remove_r(walker, &owalk);
1468  lwalk = &owalk;
1469 
1470  e = lwalk->e;
1471 
1472  if (!bmw_mask_check_edge(walker, e)) {
1473  return e;
1474  }
1475 
1476  BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
1477  BM_ITER_ELEM (e_other, &eiter, v, BM_EDGES_OF_VERT) {
1478  if (e != e_other && BM_edge_is_boundary(e_other)) {
1479  if (BLI_gset_haskey(walker->visit_set, e_other)) {
1480  continue;
1481  }
1482 
1483  if (!bmw_mask_check_edge(walker, e_other)) {
1484  continue;
1485  }
1486 
1487  lwalk = BMW_state_add(walker);
1488  BLI_gset_insert(walker->visit_set, e_other);
1489 
1490  lwalk->e = e_other;
1491  }
1492  }
1493  }
1494 
1495  return e;
1496 }
1497 
1500 /* -------------------------------------------------------------------- */
1510 static void bmw_UVEdgeWalker_begin(BMWalker *walker, void *data)
1511 {
1512  BMwUVEdgeWalker *lwalk;
1513  BMLoop *l = data;
1514 
1515  if (BLI_gset_haskey(walker->visit_set, l)) {
1516  return;
1517  }
1518 
1519  lwalk = BMW_state_add(walker);
1520  lwalk->l = l;
1521  BLI_gset_insert(walker->visit_set, l);
1522 }
1523 
1524 static void *bmw_UVEdgeWalker_yield(BMWalker *walker)
1525 {
1526  BMwUVEdgeWalker *lwalk = BMW_current_state(walker);
1527 
1528  if (!lwalk) {
1529  return NULL;
1530  }
1531 
1532  return lwalk->l;
1533 }
1534 
1535 static void *bmw_UVEdgeWalker_step(BMWalker *walker)
1536 {
1537  const int type = walker->bm->ldata.layers[walker->layer].type;
1538  const int offset = walker->bm->ldata.layers[walker->layer].offset;
1539 
1540  BMwUVEdgeWalker *lwalk, owalk;
1541  BMLoop *l;
1542  int i;
1543 
1544  BMW_state_remove_r(walker, &owalk);
1545  lwalk = &owalk;
1546 
1547  l = lwalk->l;
1548 
1549  if (!bmw_mask_check_edge(walker, l->e)) {
1550  return l;
1551  }
1552 
1553  /* Go over loops around `l->v` and `l->next->v` and see which ones share `l` and `l->next`
1554  * UV's coordinates. in addition, push on `l->next` if necessary. */
1555  for (i = 0; i < 2; i++) {
1556  BMIter liter;
1557  BMLoop *l_pivot, *l_radial;
1558 
1559  l_pivot = i ? l->next : l;
1560  BM_ITER_ELEM (l_radial, &liter, l_pivot->v, BM_LOOPS_OF_VERT) {
1561  BMLoop *l_radial_first = l_radial;
1562  void *data_pivot = BM_ELEM_CD_GET_VOID_P(l_pivot, offset);
1563 
1564  do {
1565  BMLoop *l_other;
1566  void *data_other;
1567 
1568  if (BLI_gset_haskey(walker->visit_set, l_radial)) {
1569  continue;
1570  }
1571 
1572  if (l_radial->v != l_pivot->v) {
1573  if (!bmw_mask_check_edge(walker, l_radial->e)) {
1574  continue;
1575  }
1576  }
1577 
1578  l_other = (l_radial->v != l_pivot->v) ? l_radial->next : l_radial;
1579  data_other = BM_ELEM_CD_GET_VOID_P(l_other, offset);
1580 
1581  if (!CustomData_data_equals(type, data_pivot, data_other)) {
1582  continue;
1583  }
1584 
1585  lwalk = BMW_state_add(walker);
1586  BLI_gset_insert(walker->visit_set, l_radial);
1587 
1588  lwalk->l = l_radial;
1589 
1590  } while ((l_radial = l_radial->radial_next) != l_radial_first);
1591  }
1592  }
1593 
1594  return l;
1595 }
1596 
1599 /* -------------------------------------------------------------------- */
1603 static void bmw_NonManifoldedgeWalker_begin(BMWalker *walker, void *data)
1604 {
1606  BMEdge *e = data;
1607 
1608  if (BLI_gset_haskey(walker->visit_set, e)) {
1609  return;
1610  }
1611 
1612  lwalk = BMW_state_add(walker);
1613  lwalk->start = e;
1614  lwalk->cur = e;
1615  lwalk->startv = e->v1;
1616  lwalk->lastv = e->v1;
1617  lwalk->face_count = BM_edge_face_count(e);
1618  BLI_gset_insert(walker->visit_set, e);
1619 }
1620 
1622 {
1624 
1625  if (!lwalk) {
1626  return NULL;
1627  }
1628  return lwalk->cur;
1629 }
1630 
1636 {
1637  BLI_assert(!BM_loop_is_manifold(l));
1638  do {
1640  if (BM_loop_is_manifold(l)) {
1641  l = l->radial_next;
1642  }
1643  else if (BM_edge_face_count_is_equal(l->e, face_count)) {
1644  return l;
1645  }
1646  else {
1647  break;
1648  }
1649  } while (true);
1650  return NULL;
1651 }
1652 
1654 {
1655  BMwNonManifoldEdgeLoopWalker *lwalk, owalk;
1656  BMW_state_remove_r(walker, &owalk);
1657  lwalk = &owalk;
1658  BMLoop *l_cur = NULL;
1659  const int face_count = lwalk->face_count;
1660 
1661  BMVert *v = NULL;
1662 
1663  /* Use the second pass is unlikely, only needed to walk back in the opposite direction. */
1664  for (int pass = 0; pass < 2; pass++) {
1665 
1666  BMEdge *e = lwalk->cur;
1667  v = BM_edge_other_vert(e, lwalk->lastv);
1668 
1669  /* If `lwalk.lastv` can't be walked along, start walking in the opposite direction
1670  * on the initial edge, do this at most one time during this walk operation. */
1671  if (UNLIKELY(pass == 1)) {
1672  e = lwalk->start;
1673  v = lwalk->startv;
1674  }
1675 
1676  BMLoop *l = e->l;
1677  do {
1678  BMLoop *l_next = bmw_NonManifoldLoop_find_next_around_vertex(l, v, face_count);
1679  if ((l_next != NULL) && !BLI_gset_haskey(walker->visit_set, l_next->e)) {
1680  if (l_cur == NULL) {
1681  l_cur = l_next;
1682  }
1683  else if (l_cur->e != l_next->e) {
1684  /* If there are more than one possible edge to step onto (unlikely but possible),
1685  * treat as a junction and stop walking as there is no correct answer in this case. */
1686  l_cur = NULL;
1687  break;
1688  }
1689  }
1690  } while ((l = l->radial_next) != e->l);
1691 
1692  if (l_cur != NULL) {
1693  break;
1694  }
1695  }
1696 
1697  if (l_cur != NULL) {
1698  BLI_assert(!BLI_gset_haskey(walker->visit_set, l_cur->e));
1699  BLI_assert(BM_edge_face_count(l_cur->e) == face_count);
1700  lwalk = BMW_state_add(walker);
1701  lwalk->lastv = v;
1702  lwalk->cur = l_cur->e;
1703  lwalk->face_count = face_count;
1704  BLI_gset_insert(walker->visit_set, l_cur->e);
1705  }
1706  return owalk.cur;
1707 }
1708 
1712  BM_VERT | BM_EDGE,
1716  sizeof(BMwShellWalker),
1718  BM_EDGE, /* Valid restrict masks. */
1719 };
1720 
1726  sizeof(BMwLoopShellWalker),
1728  BM_EDGE, /* Valid restrict masks. */
1729 };
1730 
1736  sizeof(BMwLoopShellWireWalker),
1738  BM_EDGE, /* Valid restrict masks. */
1739 };
1740 
1742  BM_EDGE,
1746  sizeof(BMwShellWalker),
1748  BM_EDGE, /* Valid restrict masks. */
1749 };
1750 
1752  BM_LOOP,
1756  sizeof(BMwIslandboundWalker),
1758  BM_FACE, /* Valid restrict masks. */
1759 };
1760 
1762  BM_FACE,
1766  sizeof(BMwIslandWalker),
1768  BM_EDGE | BM_FACE, /* Valid restrict masks. */
1769 };
1770 
1772  BM_FACE,
1774  bmw_IslandManifoldWalker_step, /* Only difference with #BMW_ISLAND. */
1776  sizeof(BMwIslandWalker),
1778  BM_EDGE | BM_FACE, /* Valid restrict masks. */
1779 };
1780 
1782  BM_EDGE,
1786  sizeof(BMwEdgeLoopWalker),
1788  0,
1789  /* Valid restrict masks. */ /* Could add flags here but so far none are used. */
1790 };
1791 
1793  BM_EDGE,
1797  sizeof(BMwFaceLoopWalker),
1799  0,
1800  /* Valid restrict masks. */ /* Could add flags here but so far none are used. */
1801 };
1802 
1804  BM_EDGE,
1808  sizeof(BMwEdgeringWalker),
1810  BM_EDGE, /* Valid restrict masks. */
1811 };
1812 
1814  BM_EDGE,
1818  sizeof(BMwEdgeboundaryWalker),
1820  0,
1821 };
1822 
1824  BM_EDGE,
1830  0,
1831 };
1832 
1834  BM_LOOP,
1838  sizeof(BMwUVEdgeWalker),
1840  BM_EDGE, /* Valid restrict masks. */
1841 };
1842 
1844  BM_VERT,
1848  sizeof(BMwConnectedVertexWalker),
1850  BM_VERT, /* Valid restrict masks. */
1851 };
1852 
1854  &bmw_VertShellWalker_Type, /* #BMW_VERT_SHELL */
1855  &bmw_LoopShellWalker_Type, /* #BMW_LOOP_SHELL */
1856  &bmw_LoopShellWireWalker_Type, /* #BMW_LOOP_SHELL_WIRE */
1857  &bmw_FaceShellWalker_Type, /* #BMW_FACE_SHELL */
1858  &bmw_EdgeLoopWalker_Type, /* #BMW_EDGELOOP */
1859  &bmw_FaceLoopWalker_Type, /* #BMW_FACELOOP */
1860  &bmw_EdgeringWalker_Type, /* #BMW_EDGERING */
1861  &bmw_EdgeboundaryWalker_Type, /* #BMW_EDGEBOUNDARY */
1862  &bmw_NonManifoldedgeWalker_type, /* #BMW_EDGELOOP_NONMANIFOLD */
1863  &bmw_UVEdgeWalker_Type, /* #BMW_LOOPDATA_ISLAND */
1864  &bmw_IslandboundWalker_Type, /* #BMW_ISLANDBOUND */
1865  &bmw_IslandWalker_Type, /* #BMW_ISLAND */
1866  &bmw_IslandManifoldWalker_Type, /* #BMW_ISLAND_MANIFOLD */
1867  &bmw_ConnectedVertexWalker_Type, /* #BMW_CONNECTED_VERTEX */
1868 };
1869 
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_data_equals(int type, const void *data1, const void *data2)
Definition: customdata.c:3929
#define BLI_assert(a)
Definition: BLI_assert.h:58
void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1248
void BLI_gset_insert(GSet *gs, void *key)
Definition: BLI_ghash.c:1147
bool BLI_gset_haskey(GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:1216
bool BLI_gset_add(GSet *gs, void *key)
Definition: BLI_ghash.c:1160
#define ARRAY_SIZE(arr)
#define UNLIKELY(x)
#define ELEM(...)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
#define BM_DISK_EDGE_NEXT(e, v)
Definition: bmesh_class.h:556
@ BM_LOOP
Definition: bmesh_class.h:385
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_HIDDEN
Definition: bmesh_class.h:472
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:553
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:530
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:26
#define BM_ITER_ELEM(ele, iter, data, itype)
@ BM_FACES_OF_EDGE
@ BM_VERTS_OF_EDGE
@ BM_LOOPS_OF_VERT
@ BM_LOOPS_OF_EDGE
@ BM_EDGES_OF_VERT
@ BM_EDGES_OF_FACE
#define BMO_edge_flag_test(bm, e, oflag)
#define BMO_vert_flag_test(bm, e, oflag)
#define BMO_face_flag_test(bm, e, oflag)
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:1995
bool BM_edge_is_all_face_flag_test(const BMEdge *e, const char hflag, const bool respect_hide)
Definition: bmesh_query.c:2446
BMLoop * BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v)
Other Loop in Face Sharing a Vertex.
Definition: bmesh_query.c:97
int BM_vert_face_count(const BMVert *v)
Definition: bmesh_query.c:886
int BM_edge_face_count(const BMEdge *e)
Definition: bmesh_query.c:847
BMLoop * BM_loop_other_edge_loop(BMLoop *l, BMVert *v)
Definition: bmesh_query.c:69
int BM_vert_edge_count_nonwire(const BMVert *v)
Definition: bmesh_query.c:832
BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
#define BM_edge_face_count_is_equal(e, n)
Definition: bmesh_query.h:96
BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
BLI_INLINE BMEdge * bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void * BMW_current_state(BMWalker *walker)
Current Walker State.
void * BMW_walk(BMWalker *walker)
Main Walking Function.
void * BMW_state_add(BMWalker *walker)
Add a new Walker State.
void BMW_state_remove(BMWalker *walker)
Remove Current Walker State.
@ BMW_DEPTH_FIRST
Definition: bmesh_walkers.h:28
@ BMW_BREADTH_FIRST
Definition: bmesh_walkers.h:29
@ BMW_FLAG_TEST_HIDDEN
Definition: bmesh_walkers.h:34
static void * bmw_IslandManifoldWalker_step(BMWalker *walker)
static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data)
static void bmw_VertShellWalker_begin(BMWalker *walker, void *data)
static bool bmw_edge_is_wire(const BMWalker *walker, const BMEdge *e)
static BMWalker bmw_UVEdgeWalker_Type
static void bmw_ConnectedVertexWalker_begin(BMWalker *walker, void *data)
static void * bmw_VertShellWalker_yield(BMWalker *walker)
static bool bmw_FaceLoopWalker_edge_begins_loop(BMWalker *walker, BMEdge *e)
static void bmw_FaceShellWalker_begin(BMWalker *walker, void *data)
static bool bmw_FaceLoopWalker_include_face(BMWalker *walker, BMLoop *l)
static void * bmw_FaceLoopWalker_step(BMWalker *walker)
static void * bmw_FaceLoopWalker_yield(BMWalker *walker)
static bool bm_edge_is_single(BMEdge *e)
static BMWalker bmw_FaceLoopWalker_Type
static void * bmw_EdgeboundaryWalker_step(BMWalker *walker)
static void * bmw_LoopShellWireWalker_step(BMWalker *walker)
static void bmw_IslandboundWalker_begin(BMWalker *walker, void *data)
static void bmw_LoopShellWalker_step_impl(BMWalker *walker, BMLoop *l)
static void bmw_IslandWalker_begin(BMWalker *walker, void *data)
static void bmw_EdgeboundaryWalker_begin(BMWalker *walker, void *data)
static BMWalker bmw_ConnectedVertexWalker_Type
static void * bmw_UVEdgeWalker_step(BMWalker *walker)
static BMWalker bmw_FaceShellWalker_Type
static BMWalker bmw_EdgeboundaryWalker_Type
static void bmw_EdgeringWalker_begin(BMWalker *walker, void *data)
static void * bmw_EdgeringWalker_yield(BMWalker *walker)
static void bmw_VertShellWalker_visitEdge(BMWalker *walker, BMEdge *e)
#define EDGE_CHECK(e)
static void bmw_LoopShellWalker_visitLoop(BMWalker *walker, BMLoop *l)
static BMLoop * bmw_NonManifoldLoop_find_next_around_vertex(BMLoop *l, BMVert *v, int face_count)
static void * bmw_EdgeLoopWalker_yield(BMWalker *walker)
static void * bmw_FaceShellWalker_yield(BMWalker *walker)
#define BMW_state_remove_r(walker, owalk)
const int bm_totwalkers
static bool bmw_mask_check_edge(BMWalker *walker, BMEdge *e)
static BMWalker bmw_LoopShellWireWalker_Type
static void * bmw_ConnectedVertexWalker_yield(BMWalker *walker)
static void bmw_NonManifoldedgeWalker_begin(BMWalker *walker, void *data)
static void bmw_LoopShellWalker_visitEdgeWire(BMWalker *walker, BMEdge *e)
static void * bmw_LoopShellWalker_step(BMWalker *walker)
static void * bmw_FaceShellWalker_step(BMWalker *walker)
static void bmw_ConnectedVertexWalker_visitVertex(BMWalker *walker, BMVert *v)
static BMWalker bmw_IslandboundWalker_Type
static void * bmw_IslandWalker_step(BMWalker *walker)
static void * bmw_IslandboundWalker_step(BMWalker *walker)
static bool bmw_mask_check_face(BMWalker *walker, BMFace *f)
static void * bmw_UVEdgeWalker_yield(BMWalker *walker)
static void bmw_LoopShellWireWalker_visitVert(BMWalker *walker, BMVert *v, const BMEdge *e_from)
static void bmw_EdgeLoopWalker_begin(BMWalker *walker, void *data)
static void * bmw_NonManifoldedgeWalker_yield(BMWalker *walker)
static BMWalker bmw_EdgeringWalker_Type
static void * bmw_IslandboundWalker_yield(BMWalker *walker)
static bool bmw_mask_check_vert(BMWalker *walker, BMVert *v)
static void bmw_FaceShellWalker_visitEdge(BMWalker *walker, BMEdge *e)
static void * bmw_NonManifoldedgeWalker_step(BMWalker *walker)
static void bmw_LoopShellWireWalker_begin(BMWalker *walker, void *data)
static void * bmw_VertShellWalker_step(BMWalker *walker)
static void * bmw_LoopShellWireWalker_yield(BMWalker *walker)
static void bmw_UVEdgeWalker_begin(BMWalker *walker, void *data)
static BMWalker bmw_LoopShellWalker_Type
static void * bmw_ConnectedVertexWalker_step(BMWalker *walker)
static void * bmw_IslandWalker_step_ex(BMWalker *walker, bool only_manifold)
static void * bmw_IslandWalker_yield(BMWalker *walker)
static void * bmw_EdgeLoopWalker_step(BMWalker *walker)
static BMWalker bmw_EdgeLoopWalker_Type
static BMWalker bmw_VertShellWalker_Type
static BMWalker bmw_IslandManifoldWalker_Type
static void bmw_LoopShellWalker_begin(BMWalker *walker, void *data)
static BMWalker bmw_NonManifoldedgeWalker_type
static BMWalker bmw_IslandWalker_Type
static void * bmw_LoopShellWalker_yield(BMWalker *walker)
static void * bmw_EdgeringWalker_step(BMWalker *walker)
static void * bmw_EdgeboundaryWalker_yield(BMWalker *walker)
BMWalker * bm_walker_types[]
struct BMwNonManifoldEdgeLoopWalker BMwNonManifoldEdgeLoopWalker
struct BMwIslandWalker BMwIslandWalker
struct BMwFaceLoopWalker BMwFaceLoopWalker
struct BMwEdgeLoopWalker BMwEdgeLoopWalker
struct BMwIslandboundWalker BMwIslandboundWalker
struct BMwEdgeringWalker BMwEdgeringWalker
struct BMwConnectedVertexWalker BMwConnectedVertexWalker
struct BMwLoopShellWalker BMwLoopShellWalker
struct BMwEdgeboundaryWalker BMwEdgeboundaryWalker
struct BMwLoopShellWireWalker BMwLoopShellWireWalker
struct BMwShellWalker BMwShellWalker
struct BMwUVEdgeWalker BMwUVEdgeWalker
static ulong * next
struct BMLoop * l
Definition: bmesh_class.h:140
BMHeader head
Definition: bmesh_class.h:255
int len
Definition: bmesh_class.h:279
char htype
Definition: bmesh_class.h:76
BMHeader head
Definition: bmesh_class.h:157
struct BMVert * v
Definition: bmesh_class.h:165
struct BMEdge * e
Definition: bmesh_class.h:176
struct BMLoop * radial_next
Definition: bmesh_class.h:216
struct BMLoop * prev
Definition: bmesh_class.h:245
struct BMFace * f
Definition: bmesh_class.h:183
struct BMLoop * next
Definition: bmesh_class.h:245
struct BMEdge * e
Definition: bmesh_class.h:109
BMHeader head
Definition: bmesh_class.h:97
struct GSet * visit_set_alt
Definition: bmesh_walkers.h:63
BMWFlag flag
Definition: bmesh_walkers.h:60
short mask_face
Definition: bmesh_walkers.h:58
struct GSet * visit_set
Definition: bmesh_walkers.h:62
BMesh * bm
Definition: bmesh_walkers.h:50
short mask_edge
Definition: bmesh_walkers.h:57
short mask_vert
Definition: bmesh_walkers.h:56
CustomData ldata
Definition: bmesh_class.h:337
CustomDataLayer * layers
uint len