[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [44756] trunk/blender/source/blender: added API function to C and python

Campbell Barton ideasman42 at gmail.com
Fri Mar 9 01:01:46 CET 2012


Revision: 44756
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=44756
Author:   campbellbarton
Date:     2012-03-09 00:01:38 +0000 (Fri, 09 Mar 2012)
Log Message:
-----------
added API function to C and python

* C:  BM_vert_separate(...)
* py: bmesh.utils.vert_separate(vert, edges)

This splits off regions around the vertex, splitting on connected edges passed in a sequence.

also made minor changes
- rename python api functions _rip to _separate
- fixed bmesh iterator being iterable its self (some parts of python expect this)
- fix memory leak in bmesh python api.

Modified Paths:
--------------
    trunk/blender/source/blender/bmesh/intern/bmesh_core.c
    trunk/blender/source/blender/bmesh/intern/bmesh_core.h
    trunk/blender/source/blender/python/bmesh/bmesh_py_types.c
    trunk/blender/source/blender/python/bmesh/bmesh_py_types.h
    trunk/blender/source/blender/python/bmesh/bmesh_py_utils.c
    trunk/blender/source/blender/python/generic/idprop_py_api.c

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_core.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_core.c	2012-03-08 22:33:34 UTC (rev 44755)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_core.c	2012-03-09 00:01:38 UTC (rev 44756)
@@ -41,7 +41,7 @@
  * TESTING ONLY! */
 // #define USE_DEBUG_INDEX_MEMCHECK
 
-int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget);
+static int bm_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep);
 
 #ifdef USE_DEBUG_INDEX_MEMCHECK
 #define DEBUG_MEMCHECK_INDEX_INVALIDATE(ele)               \
@@ -1739,14 +1739,16 @@
 }
 
 /**
- * \brief Cut Vert
+ * \brief Separate Vert
  *
- * Cut all disjoint fans that meet at a vertex, making a unique
+ * Separates all disjoint fans that meet at a vertex, making a unique
  * vertex for each region. returns an array of all resulting vertices.
  *
+ * \note this is a low level function, bm_edge_separate needs to run on edges first
+ *
  * \return Success
  */
-static int bm_vert_cut(BMesh *bm, BMVert *v, BMVert ***vout, int *len)
+int bm_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len)
 {
 	BMEdge **stack = NULL;
 	BLI_array_declare(stack);
@@ -1758,7 +1760,7 @@
 	int i, maxindex;
 	BMLoop *nl;
 
-	visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh_vert_cut visithash");
+	visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
 
 	maxindex = 0;
 	BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
@@ -1786,7 +1788,7 @@
 	}
 
 	/* Make enough verts to split v for each group */
-	verts = MEM_callocN(sizeof(BMVert *) * maxindex, "bmesh_vert_cut");
+	verts = MEM_callocN(sizeof(BMVert *) * maxindex, __func__);
 	verts[0] = v;
 	for (i = 1; i < maxindex; i++) {
 		verts[i] = BM_vert_create(bm, v->co, v);
@@ -1829,12 +1831,12 @@
 		BM_CHECK_ELEMENT(bm, verts[i]);
 	}
 
-	if (len != NULL) {
-		*len = maxindex;
+	if (r_vout_len != NULL) {
+		*r_vout_len = maxindex;
 	}
 
-	if (vout != NULL) {
-		*vout = verts;
+	if (r_vout != NULL) {
+		*r_vout = verts;
 	}
 	else {
 		MEM_freeN(verts);
@@ -1844,6 +1846,24 @@
 }
 
 /**
+ * High level function which wraps both #bm_vert_separate and #bm_edge_separate
+ */
+int BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
+                     BMEdge **e_in, int e_in_len)
+{
+	int i;
+
+	for (i = 0; i < e_in_len; i++) {
+		BMEdge *e = e_in[i];
+		if (e->l && BM_vert_in_edge(e, v)) {
+			bm_edge_separate(bm, e, e->l);
+		}
+	}
+
+	return bm_vert_separate(bm, v, r_vout, r_vout_len);
+}
+
+/**
  * \brief Splice Edge
  *
  * Splice two unique edges which share the same two vertices into one edge.
@@ -1881,22 +1901,22 @@
 }
 
 /**
- * \brief Cut Edge
+ * \brief Separate Edge
  *
- * Cuts a single edge into two edge: the original edge and
- * a new edge that has only \a cutl in its radial.
+ * Separates a single edge into two edge: the original edge and
+ * a new edge that has only \a l_sep in its radial.
  *
  * \return Success
  *
- * \note Does nothing if \a cutl is already the only loop in the
+ * \note Does nothing if \a l_sep is already the only loop in the
  * edge radial.
  */
-static int bm_edge_cut(BMesh *bm, BMEdge *e, BMLoop *cutl)
+static int bm_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep)
 {
 	BMEdge *ne;
 	int radlen;
 
-	BLI_assert(cutl->e == e);
+	BLI_assert(l_sep->e == e);
 	BLI_assert(e->l);
 	
 	radlen = bmesh_radial_length(e->l);
@@ -1905,14 +1925,14 @@
 		return TRUE;
 	}
 
-	if (cutl == e->l) {
-		e->l = cutl->radial_next;
+	if (l_sep == e->l) {
+		e->l = l_sep->radial_next;
 	}
 
 	ne = BM_edge_create(bm, e->v1, e->v2, e, FALSE);
-	bmesh_radial_loop_remove(cutl, e);
-	bmesh_radial_append(ne, cutl);
-	cutl->e = ne;
+	bmesh_radial_loop_remove(l_sep, e);
+	bmesh_radial_append(ne, l_sep);
+	l_sep->e = ne;
 
 	BLI_assert(bmesh_radial_length(e->l) == radlen - 1);
 	BLI_assert(bmesh_radial_length(ne->l) == 1);
@@ -1939,8 +1959,8 @@
 
 	/* peel the face from the edge radials on both sides of the
 	 * loop vert, disconnecting the face from its fan */
-	bm_edge_cut(bm, sl->e, sl);
-	bm_edge_cut(bm, sl->prev->e, sl->prev);
+	bm_edge_separate(bm, sl->e, sl);
+	bm_edge_separate(bm, sl->prev->e, sl->prev);
 
 	if (bmesh_disk_count(sv) == 2) {
 		/* If there are still only two edges out of sv, then
@@ -1949,7 +1969,7 @@
 	}
 
 	/* Update the disk start, so that v->e points to an edge
-	 * not touching the split loop. This is so that bmesh_vert_cut
+	 * not touching the split loop. This is so that BM_vert_split
 	 * will leave the original sv on some *other* fan (not the
 	 * one-face fan that holds the unglue face). */
 	while (sv->e == sl->e || sv->e == sl->prev->e) {
@@ -1958,7 +1978,7 @@
 
 	/* Split all fans connected to the vert, duplicating it for
 	 * each fans. */
-	bm_vert_cut(bm, sv, &vtar, &len);
+	bm_vert_separate(bm, sv, &vtar, &len);
 
 	/* There should have been at least two fans cut apart here,
 	 * otherwise the early exit would have kicked in. */

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_core.h
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_core.h	2012-03-08 22:33:34 UTC (rev 44755)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_core.h	2012-03-09 00:01:38 UTC (rev 44756)
@@ -33,18 +33,20 @@
 BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, int nodouble);
 BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, int nodouble);
 
-void BM_face_edges_kill(BMesh *bm, BMFace *f);
-void BM_face_verts_kill(BMesh *bm, BMFace *f);
+void    BM_face_edges_kill(BMesh *bm, BMFace *f);
+void    BM_face_verts_kill(BMesh *bm, BMFace *f);
 
-void BM_face_kill(BMesh *bm, BMFace *f);
-void BM_edge_kill(BMesh *bm, BMEdge *e);
-void BM_vert_kill(BMesh *bm, BMVert *v);
+void    BM_face_kill(BMesh *bm, BMFace *f);
+void    BM_edge_kill(BMesh *bm, BMEdge *e);
+void    BM_vert_kill(BMesh *bm, BMVert *v);
 
-int  BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget);
+int     BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget);
 
-int  bmesh_loop_reverse(BMesh *bm, BMFace *f);
+int     bmesh_loop_reverse(BMesh *bm, BMFace *f);
 
 BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface);
+int     BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
+                         BMEdge **e_in, int e_in_len);
 
 /* EULER API - For modifying structure */
 BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1,

Modified: trunk/blender/source/blender/python/bmesh/bmesh_py_types.c
===================================================================
--- trunk/blender/source/blender/python/bmesh/bmesh_py_types.c	2012-03-08 22:33:34 UTC (rev 44755)
+++ trunk/blender/source/blender/python/bmesh/bmesh_py_types.c	2012-03-09 00:01:38 UTC (rev 44756)
@@ -2309,6 +2309,7 @@
 
 	/* only 1 iteratir so far */
 	BPy_BMIter_Type.tp_iternext = (iternextfunc)bpy_bmiter_next;
+	BPy_BMIter_Type.tp_iter     = PyObject_SelfIter;
 
 	BPy_BMesh_Type.tp_dealloc     = (destructor)bpy_bmesh_dealloc;
 	BPy_BMVert_Type.tp_dealloc    = (destructor)bpy_bmvert_dealloc;
@@ -2673,3 +2674,15 @@
 		return NULL;
 	}
 }
+
+
+PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len)
+{
+	Py_ssize_t i;
+	PyObject *ret = PyTuple_New(elem_len);
+	for (i = 0; i < elem_len; i++) {
+		PyTuple_SET_ITEM(ret, i, BPy_BMElem_CreatePyObject(bm, elem[i]));
+	}
+
+	return ret;
+}

Modified: trunk/blender/source/blender/python/bmesh/bmesh_py_types.h
===================================================================
--- trunk/blender/source/blender/python/bmesh/bmesh_py_types.h	2012-03-08 22:33:34 UTC (rev 44755)
+++ trunk/blender/source/blender/python/bmesh/bmesh_py_types.h	2012-03-09 00:01:38 UTC (rev 44756)
@@ -137,6 +137,9 @@
                                 const char do_unique_check, const char do_bm_check,
                                 const char *error_prefix);
 
+PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len);
+
+
 #define BPY_BM_CHECK_OBJ(obj) if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return NULL; } (void)0
 #define BPY_BM_CHECK_INT(obj) if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return -1; }   (void)0
 

Modified: trunk/blender/source/blender/python/bmesh/bmesh_py_utils.c
===================================================================
--- trunk/blender/source/blender/python/bmesh/bmesh_py_utils.c	2012-03-08 22:33:34 UTC (rev 44755)
+++ trunk/blender/source/blender/python/bmesh/bmesh_py_utils.c	2012-03-09 00:01:38 UTC (rev 44756)
@@ -38,6 +38,8 @@
 
 #include "BLI_utildefines.h"
 
+#include "MEM_guardedalloc.h"
+
 #include "bmesh_py_utils.h" /* own include */
 
 
@@ -196,7 +198,68 @@
 	return PyBool_FromLong((BM_vert_dissolve(bm, py_vert->v)));
 }
 
+PyDoc_STRVAR(bpy_bm_utils_vert_separate_doc,
+".. method:: vert_separate(vert, edges)\n"
+"\n"
+"   Separate this vertex at every edge.\n"
+"\n"
+"   :arg vert: The vert to be separated.\n"
+"   :type vert: :class:`BMVert`\n"
+"   :arg edges: The edges to separated.\n"
+"   :type edges: :class:`BMEdge`\n"
+"   :return: The newly separated verts (including the vertex passed).\n"
+"   :rtype: tuple of :class:`BMVert`\n"
+);
+static PyObject *bpy_bm_utils_vert_separate(PyObject *UNUSED(self), PyObject *args)
+{
+	BPy_BMVert *py_vert;
+	PyObject *edge_seq;
 
+	BMesh *bm;
+	BMVert **elem;
+	int elem_len;
+
+	/* edges to split */
+	BMEdge **edge_array;
+	Py_ssize_t edge_array_len;
+
+	PyObject *ret;
+
+
+	if (!PyArg_ParseTuple(args, "O!O:vert_separate",
+	                      &BPy_BMVert_Type, &py_vert,
+	                      &edge_seq))
+	{
+		return NULL;
+	}
+
+	BPY_BM_CHECK_OBJ(py_vert);
+
+	bm = py_vert->bm;
+
+	edge_array = BPy_BMElem_PySeq_As_Array(&bm, edge_seq, 0, PY_SSIZE_T_MAX,
+	                                       &edge_array_len, &BPy_BMEdge_Type,
+	                                       TRUE, TRUE, "vert_separate(...)");
+
+	if (edge_array == NULL) {
+		return NULL;
+	}
+
+	if (BM_vert_separate(bm, py_vert->v, &elem, &elem_len, edge_array, edge_array_len)) {
+		/* return collected verts */
+		ret = BPy_BMElem_Array_As_Tuple(bm, (BMHeader **)elem, elem_len);
+		MEM_freeN(elem);
+	}
+	else {
+		ret = PyTuple_New(0);
+	}
+
+	PyMem_FREE(edge_array);
+
+	return ret;
+}
+
+
 PyDoc_STRVAR(bpy_bm_utils_edge_split_doc,
 ".. method:: edge_split(edge, vert, fac)\n"
 "\n"
@@ -408,6 +471,8 @@

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list