Changeset View
Changeset View
Standalone View
Standalone View
source/blender/bmesh/intern/bmesh_operators.c
| Context not available. | |||||
| va_end(list); | va_end(list); | ||||
| return true; | return true; | ||||
| } | } | ||||
| /* PE/connectivity distances tools --- here for the lack of a better place */ | |||||
| #include "BLI_linklist_stack.h" | |||||
| #include "MEM_guardedalloc.h" | |||||
| bool bmesh_test_dist_add(BMVert *v, BMVert *v_other, | |||||
| float *dists, const float *dists_prev, | |||||
| float mtx[3][3]) | |||||
| { | |||||
| if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) && | |||||
| (BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0)) | |||||
| { | |||||
| const int i = BM_elem_index_get(v); | |||||
| const int i_other = BM_elem_index_get(v_other); | |||||
| float vec[3]; | |||||
| float dist_other; | |||||
| sub_v3_v3v3(vec, v->co, v_other->co); | |||||
| mul_m3_v3(mtx, vec); | |||||
| dist_other = dists_prev[i] + len_v3(vec); | |||||
| if (dist_other < dists[i_other]) { | |||||
| dists[i_other] = dist_other; | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| void BM_calc_connectivity_distance(BMesh *bm, float TransformMtx[3][3], float *dists) | |||||
| { | |||||
| /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */ | |||||
| float *dists_prev = MEM_mallocN(bm->totvert * sizeof(float), __func__); | |||||
| BLI_LINKSTACK_DECLARE(queue, BMVert *); | |||||
| /* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */ | |||||
| BLI_LINKSTACK_DECLARE(queue_next, BMVert *); | |||||
| BLI_LINKSTACK_INIT(queue); | |||||
| BLI_LINKSTACK_INIT(queue_next); | |||||
| { | |||||
| BMIter viter; | |||||
| BMVert *v; | |||||
| int i; | |||||
| BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { | |||||
| BM_elem_index_set(v, i); /* set_inline */ | |||||
| BM_elem_flag_disable(v, BM_ELEM_TAG); | |||||
| if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { | |||||
| dists[i] = FLT_MAX; | |||||
| } | |||||
| else { | |||||
| BLI_LINKSTACK_PUSH(queue, v); | |||||
| dists[i] = 0.0f; | |||||
| } | |||||
| } | |||||
| } | |||||
| do { | |||||
| BMVert *v; | |||||
| LinkNode *lnk; | |||||
| memcpy(dists_prev, dists, sizeof(float) * bm->totvert); | |||||
| while ((v = BLI_LINKSTACK_POP(queue))) { | |||||
| BMIter iter; | |||||
| BMEdge *e; | |||||
| BMLoop *l; | |||||
| /* connected edge-verts */ | |||||
| BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { | |||||
| if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == 0) { | |||||
| BMVert *v_other = BM_edge_other_vert(e, v); | |||||
| if (bmesh_test_dist_add(v, v_other, dists, dists_prev, TransformMtx)) { | |||||
| if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { | |||||
| BM_elem_flag_enable(v_other, BM_ELEM_TAG); | |||||
| BLI_LINKSTACK_PUSH(queue_next, v_other); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /* connected face-verts (excluding adjacent verts) */ | |||||
| BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { | |||||
| if ((BM_elem_flag_test(l->f, BM_ELEM_HIDDEN) == 0) && (l->f->len > 3)) { | |||||
| BMLoop *l_end = l->prev; | |||||
| l = l->next->next; | |||||
| do { | |||||
| BMVert *v_other = l->v; | |||||
| if (bmesh_test_dist_add(v, v_other, dists, dists_prev, TransformMtx)) { | |||||
| if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { | |||||
| BM_elem_flag_enable(v_other, BM_ELEM_TAG); | |||||
| BLI_LINKSTACK_PUSH(queue_next, v_other); | |||||
| } | |||||
| } | |||||
| } while ((l = l->next) != l_end); | |||||
| } | |||||
| } | |||||
| } | |||||
| /* clear for the next loop */ | |||||
| for (lnk = queue_next; lnk; lnk = lnk->next) { | |||||
| BM_elem_flag_disable((BMVert *)lnk->link, BM_ELEM_TAG); | |||||
| } | |||||
| BLI_LINKSTACK_SWAP(queue, queue_next); | |||||
| /* none should be tagged now since 'queue_next' is empty */ | |||||
| BLI_assert(BM_iter_mesh_count_flag(BM_VERTS_OF_MESH, bm, BM_ELEM_TAG, true) == 0); | |||||
| } while (BLI_LINKSTACK_SIZE(queue)); | |||||
| BLI_LINKSTACK_FREE(queue); | |||||
| BLI_LINKSTACK_FREE(queue_next); | |||||
| MEM_freeN(dists_prev); | |||||
| } | |||||
| Context not available. | |||||