[Bf-blender-cvs] [5e5211c] master: BMesh: add BM_vert_splice_check_double

Campbell Barton noreply at git.blender.org
Mon Aug 18 07:42:37 CEST 2014


Commit: 5e5211c8a1b9f270773abebf72773b98e25afd80
Author: Campbell Barton
Date:   Mon Aug 18 15:41:54 2014 +1000
Branches: master
https://developer.blender.org/rB5e5211c8a1b9f270773abebf72773b98e25afd80

BMesh: add BM_vert_splice_check_double

checks if splicing verts creates duplicate edges

===================================================================

M	source/blender/bmesh/CMakeLists.txt
M	source/blender/bmesh/intern/bmesh_core.c
M	source/blender/bmesh/intern/bmesh_core.h
M	source/blender/bmesh/intern/bmesh_mods.c
M	source/blender/editors/mesh/editmesh_intersect.c
M	source/blender/editors/mesh/mesh_intern.h
M	source/blender/editors/mesh/mesh_ops.c

===================================================================

diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index 2cd256e..a43e835 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -136,6 +136,8 @@ set(SRC
 	tools/bmesh_edgenet.h
 	tools/bmesh_edgesplit.c
 	tools/bmesh_edgesplit.h
+	tools/bmesh_intersect.c
+	tools/bmesh_intersect.h
 	tools/bmesh_path.c
 	tools/bmesh_path.h
 	tools/bmesh_triangulate.c
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 6f886ed..99dd9c2 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -1940,6 +1940,44 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
 }
 
 /**
+ * Check if splicing vertices would create any double edges.
+ *
+ * \note assume caller will handle case where verts share an edge.
+ */
+bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b)
+{
+	bool is_double = false;
+
+	BLI_assert(BM_edge_exists(v_a, v_b) == false);
+
+	if (v_a->e && v_b->e) {
+		SmallHash visit;
+		BMEdge *e, *e_first;
+
+		BLI_smallhash_init(&visit);
+
+		e = e_first = v_a->e;
+		do {
+			BMVert *v_other = BM_edge_other_vert(e, v_a);
+			BLI_smallhash_insert(&visit, (uintptr_t)v_other, NULL);
+		} while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first);
+
+		e = e_first = v_b->e;
+		do {
+			BMVert *v_other = BM_edge_other_vert(e, v_b);
+			if (BLI_smallhash_haskey(&visit, (uintptr_t)v_other)) {
+				is_double = true;
+				break;
+			}
+		} while ((e = BM_DISK_EDGE_NEXT(e, v_b)) != e_first);
+
+		BLI_smallhash_release(&visit);
+	}
+
+	return is_double;
+}
+
+/**
  * \brief Splice Vert
  *
  * Merges two verts into one (\a v into \a vtarget).
diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h
index 4a2b4b7..ab847fc 100644
--- a/source/blender/bmesh/intern/bmesh_core.h
+++ b/source/blender/bmesh/intern/bmesh_core.h
@@ -61,6 +61,7 @@ void    bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep,
                             const bool copy_select);
 bool    BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target);
 bool    BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target);
+bool    BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b);
 
 void    bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
                             const bool copy_select);
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index 43f33a9..a0fa659 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -796,6 +796,7 @@ bool BM_face_split_edgenet(
 #ifdef DEBUG
 	for (i = 0; i < edge_net_len; i++) {
 		BLI_assert(BM_ELEM_API_FLAG_TEST(edge_net[i], EDGE_NET) == 0);
+		BLI_assert(BM_edge_in_face(edge_net[i], f) == false);
 	}
 	l_iter = l_first = BM_FACE_FIRST_LOOP(f);
 	do {
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index f11ef66..20581d3 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -34,6 +34,8 @@
 #include "BKE_context.h"
 #include "BKE_editmesh.h"
 
+#include "RNA_access.h"
+#include "RNA_define.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
@@ -45,6 +47,122 @@
 
 #include "mesh_intern.h"  /* own include */
 
+#include "tools/bmesh_intersect.h"
+
+/**
+ * Compare selected with its self.
+ */
+static int bm_face_isect_self(BMFace *f, void *UNUSED(user_data))
+{
+	if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+		return 0;
+	}
+	else {
+		return -1;
+	}
+}
+
+/**
+ * Compare selected/unselected.
+ */
+static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data))
+{
+	if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+		return -1;
+	}
+	else if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+		return 0;
+	}
+	else {
+		return 1;
+	}
+}
+
+enum {
+	ISECT_SEL           = 0,
+	ISECT_SEL_UNSEL     = 1,
+};
+
+/* defines for rearranging channels */
+static EnumPropertyItem intersect_types[] = {
+	{ISECT_SEL, "SELECT", 0, "Self",
+	 "Self intersect selected geometry"},
+	{ISECT_SEL_UNSEL, "SELECT_UNSELECT", 0, "Select/Unselected",
+	 "Intersect selected with unselected geometry"},
+	{0, NULL, 0, NULL, NULL}
+};
+
+static int edbm_intersect_exec(bContext *C, wmOperator *op)
+{
+	Object *obedit = CTX_data_edit_object(C);
+	BMEditMesh *em = BKE_editmesh_from_object(obedit);
+	BMesh *bm = em->bm;
+	const int mode = RNA_enum_get(op->ptr, "mode");
+	int (*test_fn)(BMFace *, void *);
+	bool use_separate = RNA_boolean_get(op->ptr, "use_separate");
+	const float eps = RNA_float_get(op->ptr, "threshold");
+	bool use_self;
+	bool has_isect;
+
+	switch (mode) {
+		case ISECT_SEL:
+			test_fn = bm_face_isect_self;
+			use_self = true;
+			break;
+		default:  /* ISECT_SEL_UNSEL */
+			test_fn = bm_face_isect_pair;
+			use_self = false;
+			break;
+	}
+
+
+	has_isect = BM_mesh_intersect(
+	        bm,
+	        em->looptris, em->tottri,
+	        test_fn, NULL,
+	        use_self, use_separate,
+	        eps);
+
+	BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
+
+	if (has_isect && (em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE))) {
+		BMIter iter;
+		BMEdge *e;
+
+		BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+			if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+				BM_edge_select_set(bm, e, true);
+			}
+		}
+	}
+
+	EDBM_mesh_normals_update(em);
+	EDBM_update_generic(em, true, true);
+
+	return OPERATOR_FINISHED;
+}
+
+void MESH_OT_intersect(struct wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Intersect";
+	ot->description = "";
+	ot->idname = "MESH_OT_intersect";
+
+	/* api callbacks */
+	ot->exec = edbm_intersect_exec;
+	ot->poll = ED_operator_editmesh;
+
+	/* props */
+	RNA_def_boolean(ot->srna, "use_separate", true, "Separate", "");
+	RNA_def_float(ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001);
+	RNA_def_enum(ot->srna, "mode", intersect_types, ISECT_SEL_UNSEL, "Source", "");
+
+	/* flags */
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
 
 
 /* -------------------------------------------------------------------- */
@@ -84,7 +202,6 @@ static void bm_face_split_by_edges(BMesh *bm, BMFace *f, const char hflag)
 			if (BM_elem_flag_test(e, hflag) &&
 			    (BM_elem_index_get(e) == f_index))
 			{
-				BMVert *v;
 				v = BM_edge_other_vert(e, l_iter->v);
 				v->e = e;
 
@@ -180,7 +297,6 @@ static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op))
 	BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
 		if (BM_elem_flag_test(e, hflag)) {
 			BMIter viter;
-			BMVert *v;
 			BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
 				BMIter liter;
 				BMLoop *l;
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 2ce19fe..76f6cb5 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -113,6 +113,7 @@ void MESH_OT_screw(struct wmOperatorType *ot);
 void MESH_OT_inset(struct wmOperatorType *ot);
 
 /* *** editmesh_intersect.c *** */
+void MESH_OT_intersect(struct wmOperatorType *ot);
 void MESH_OT_face_split_by_edges(struct wmOperatorType *ot);
 
 
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 55dd97d..31653ef 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -170,6 +170,7 @@ void ED_operatortypes_mesh(void)
 
 	WM_operatortype_append(MESH_OT_bridge_edge_loops);
 	WM_operatortype_append(MESH_OT_inset);
+	WM_operatortype_append(MESH_OT_intersect);
 	WM_operatortype_append(MESH_OT_face_split_by_edges);
 	WM_operatortype_append(MESH_OT_poke);
 	WM_operatortype_append(MESH_OT_wireframe);




More information about the Bf-blender-cvs mailing list