[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