bmesh py api, new functions:

* bmesh.utils.face_vert_rip(f, v)
* bmesh.utils.loop_rip(l)
This commit is contained in:
Campbell Barton 2012-03-08 20:00:37 +00:00
parent 284fcd2df2
commit c82c456247
10 changed files with 146 additions and 43 deletions

@ -1930,7 +1930,7 @@ static int bm_edge_cut(BMesh *bm, BMEdge *e, BMLoop *cutl)
*
* \return The newly created BMVert
*/
static BMVert *bm_urmv_loop(BMesh *bm, BMLoop *sl)
BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl)
{
BMVert **vtar;
int len, i;
@ -2007,20 +2007,6 @@ static BMVert *bm_urmv_loop(BMesh *bm, BMLoop *sl)
*/
BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv)
{
BMLoop *l_first;
BMLoop *l_iter;
l_iter = l_first = BM_FACE_FIRST_LOOP(sf);
do {
if (l_iter->v == sv) {
break;
}
} while ((l_iter = l_iter->next) != l_first);
if (l_iter->v != sv) {
/* sv is not part of sf */
return NULL;
}
return bm_urmv_loop(bm, l_iter);
BMLoop *l = BM_face_vert_share_loop(sf, sv);
return bmesh_urmv_loop(bm, l);
}

@ -60,5 +60,6 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e);
BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_splice);
BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e);
BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv);
BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl);
#endif /* __BMESH_CORE_H__ */

@ -1073,7 +1073,17 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const short ccw, const short check_
/**
* \brief Rip a single face from a vertex fan
*/
BMVert *BM_vert_rip(BMesh *bm, BMFace *sf, BMVert *sv)
BMVert *BM_face_vert_rip(BMesh *bm, BMFace *sf, BMVert *sv)
{
return bmesh_urmv(bm, sf, sv);
}
/**
* \brief Rip a single face from a vertex fan
*
* \note same as #BM_face_vert_rip but faster (avoids a loop lookup)
*/
BMVert *BM_face_loop_rip(BMesh *bm, BMLoop *sl)
{
return bmesh_urmv_loop(bm, sl);
}

@ -77,6 +77,7 @@ enum {
};
BMVert *BM_vert_rip(BMesh *bm, BMFace *sf, BMVert *sv);
BMVert *BM_face_vert_rip(BMesh *bm, BMFace *sf, BMVert *sv);
BMVert *BM_face_loop_rip(BMesh *bm, BMLoop *sl);
#endif /* __BMESH_MODS_H__ */

@ -556,6 +556,29 @@ BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2)
}
}
/**
* \brief Radial Find a Vertex Loop in Face
*
* Finds the loop used which uses \a v in face loop \a l
*
* \note currenly this just uses simple loop in future may be speeded up
* using radial vars
*/
BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v)
{
BMLoop *l_first;
BMLoop *l_iter;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
if (l_iter->v == v) {
return l_iter;
}
} while ((l_iter = l_iter->next) != l_first);
return NULL;
}
/**
* Returns the verts of an edge as used in a face
* if used in a face at all, otherwise just assign as used in the edge.

@ -72,6 +72,7 @@ int BM_edge_share_face_count(BMEdge *e1, BMEdge *e2);
int BM_edge_share_vert_count(BMEdge *e1, BMEdge *e2);
BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2);
BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v);
void BM_edge_ordered_verts(BMEdge *edge, BMVert **r_v1, BMVert **r_v2);

@ -450,27 +450,6 @@ BMLoop *bmesh_radial_faceloop_find_next(BMLoop *l, BMVert *v)
return l;
}
/* NOTE: this function has not been used or tested - so take care but it should work ok,
* I wrote it for some tool that ended up not using it, however this seems like a reasonable
* thing to be able to find the loop between a vertex and a face so keeping - campbell */
/**
* \brief Radial Find a Vertex Loop in Face
*
* Finds the loop used which uses \a v in face loop \a l
*/
BMLoop *bmesh_radial_faceloop_find_vert(BMFace *f, BMVert *v) /* name is a bit awkward */
{
BMLoop *l_iter, *l_first;
if (v->e && (l_iter = l_first = v->e->l)) {
do {
if (l_iter->v == v && l_iter->f == f) {
return l_iter;
}
} while ((l_iter = l_iter->radial_next) != l_first);
}
return NULL;
}
int bmesh_radial_length(BMLoop *l)
{
BMLoop *l_iter = l;

@ -2409,7 +2409,7 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
/* rip two adjacent edges */
if (BM_edge_face_count(e2) == 1 || BM_vert_face_count(v) == 2) {
l = e2->l;
ripvert = BM_vert_rip(bm, l->f, v);
ripvert = BM_face_vert_rip(bm, l->f, v);
BLI_assert(ripvert);
if (!ripvert) {

@ -961,7 +961,7 @@ static PyObject *bpy_bmedge_other_vert(BPy_BMEdge *self, BPy_BMVert *value)
BPY_BM_CHECK_OBJ(value);
if (self->bm != value->bm) {
PyErr_SetString(PyExc_TypeError,
PyErr_SetString(PyExc_ValueError,
"BMEdge.other_vert(vert): vert is from another mesh");
return NULL;
}
@ -2625,7 +2625,7 @@ void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_
/* trick so we can ensure all items have the same mesh,
* and allows us to pass the 'bm' as NULL. */
else if (do_bm_check && (bm && bm != item->bm)) {
PyErr_Format(PyExc_TypeError,
PyErr_Format(PyExc_ValueError,
"%s: %d %s is from another mesh",
error_prefix, i, type->tp_name);
goto err_cleanup;

@ -417,6 +417,68 @@ static PyObject *bpy_bm_utils_face_join(PyObject *UNUSED(self), PyObject *value)
}
PyDoc_STRVAR(bpy_bm_utils_face_vert_rip_doc,
".. method:: face_vert_rip(face, vert)\n"
"\n"
" Rip a vertex in a face away and add a new vertex.\n"
"\n"
" :arg face: The face to rip.\n"
" :type face: :class:`BMFace`\n"
" :arg vert: A vertex in the face to rip.\n"
" :type vert: :class:`BMVert`\n"
" :return vert: The newly created vertex or None of failure.\n"
" :rtype vert: :class:`BMVert`\n"
"\n"
" .. note::\n"
"\n"
" This is the same as loop_rip, and has only been added for convenience.\n"
);
static PyObject *bpy_bm_utils_face_vert_rip(PyObject *UNUSED(self), PyObject *args)
{
BPy_BMFace *py_face;
BPy_BMVert *py_vert;
BMesh *bm;
BMLoop *l;
BMVert *v_new;
if (!PyArg_ParseTuple(args, "O!O!:face_vert_rip",
&BPy_BMFace_Type, &py_face,
&BPy_BMVert_Type, &py_vert))
{
return NULL;
}
BPY_BM_CHECK_OBJ(py_face);
BPY_BM_CHECK_OBJ(py_vert);
bm = py_face->bm;
if (bm != py_vert->bm) {
PyErr_SetString(PyExc_ValueError,
"mesh elements are from different meshes");
return NULL;
}
l = BM_face_vert_share_loop(py_face->f, py_vert->v);
if (l == NULL) {
PyErr_SetString(PyExc_ValueError,
"vertex not found in face");
return NULL;
}
v_new = BM_face_loop_rip(bm, l);
if (v_new != l->v) {
return BPy_BMVert_CreatePyObject(bm, v_new);
}
else {
Py_RETURN_NONE;
}
}
PyDoc_STRVAR(bpy_bm_utils_face_flip_doc,
".. method:: face_flip(faces)\n"
"\n"
@ -442,6 +504,44 @@ static PyObject *bpy_bm_utils_face_flip(PyObject *UNUSED(self), BPy_BMFace *valu
}
PyDoc_STRVAR(bpy_bm_utils_loop_rip_doc,
".. method:: loop_rip(loop)\n"
"\n"
" Rip a vertex in a face away and add a new vertex.\n"
"\n"
" :arg loop: The to rip.\n"
" :type loop: :class:`BMFace`\n"
" :return vert: The newly created vertex or None of failure.\n"
" :rtype vert: :class:`BMVert`\n"
);
static PyObject *bpy_bm_utils_loop_rip(PyObject *UNUSED(self), BPy_BMLoop *value)
{
BMesh *bm;
BMVert *v_new;
if (!BPy_BMLoop_Check(value)) {
PyErr_Format(PyExc_TypeError,
"loop_rip(loop): BMLoop expected, not '%.200s'",
Py_TYPE(value)->tp_name);
return NULL;
}
BPY_BM_CHECK_OBJ(value);
bm = value->bm;
v_new = BM_face_loop_rip(bm, value->l);
if (v_new != value->l->v) {
return BPy_BMVert_CreatePyObject(bm, v_new);
}
else {
Py_RETURN_NONE;
}
}
static struct PyMethodDef BPy_BM_utils_methods[] = {
{"vert_collapse_edge", (PyCFunction)bpy_bm_utils_vert_collapse_edge, METH_VARARGS, bpy_bm_utils_vert_collapse_edge_doc},
{"vert_collapse_faces", (PyCFunction)bpy_bm_utils_vert_collapse_faces, METH_VARARGS, bpy_bm_utils_vert_collapse_faces_doc},
@ -450,7 +550,9 @@ static struct PyMethodDef BPy_BM_utils_methods[] = {
{"edge_rotate", (PyCFunction)bpy_bm_utils_edge_rotate, METH_VARARGS, bpy_bm_utils_edge_rotate_doc},
{"face_split", (PyCFunction)bpy_bm_utils_face_split, METH_VARARGS, bpy_bm_utils_face_split_doc},
{"face_join", (PyCFunction)bpy_bm_utils_face_join, METH_O, bpy_bm_utils_face_join_doc},
{"face_vert_rip", (PyCFunction)bpy_bm_utils_face_vert_rip, METH_VARARGS, bpy_bm_utils_face_vert_rip_doc},
{"face_flip", (PyCFunction)bpy_bm_utils_face_flip, METH_O, bpy_bm_utils_face_flip_doc},
{"loop_rip", (PyCFunction)bpy_bm_utils_loop_rip, METH_O, bpy_bm_utils_loop_rip_doc},
{NULL, NULL, 0, NULL}
};