18 #include "../mathutils/mathutils.h"
24 #include "../generic/py_capi_utils.h"
25 #include "../generic/python_utildefines.h"
28 ".. method:: vert_collapse_edge(vert, edge)\n"
30 " Collapse a vertex into an edge.\n"
32 " :arg vert: The vert that will be collapsed.\n"
33 " :type vert: :class:`bmesh.types.BMVert`\n"
34 " :arg edge: The edge to collapse into.\n"
35 " :type edge: :class:`bmesh.types.BMEdge`\n"
36 " :return: The resulting edge from the collapse operation.\n"
37 " :rtype: :class:`bmesh.types.BMEdge`\n");
46 if (!PyArg_ParseTuple(args,
47 "O!O!:vert_collapse_edge",
59 if (!(py_edge->
e->
v1 == py_vert->
v || py_edge->
e->
v2 == py_vert->
v)) {
60 PyErr_SetString(PyExc_ValueError,
61 "vert_collapse_edge(vert, edge): the vertex is not found in the edge");
66 PyErr_SetString(PyExc_ValueError,
67 "vert_collapse_edge(vert, edge): vert has more than 2 connected edges");
79 PyErr_SetString(PyExc_ValueError,
80 "vert_collapse_edge(vert, edge): no new edge created, internal error");
85 ".. method:: vert_collapse_faces(vert, edge, fac, join_faces)\n"
87 " Collapses a vertex that has only two manifold edges onto a vertex it shares an "
90 " :arg vert: The vert that will be collapsed.\n"
91 " :type vert: :class:`bmesh.types.BMVert`\n"
92 " :arg edge: The edge to collapse into.\n"
93 " :type edge: :class:`bmesh.types.BMEdge`\n"
94 " :arg fac: The factor to use when merging customdata [0 - 1].\n"
96 " :arg join_faces: When true the faces around the vertex will be joined otherwise "
97 "collapse the vertex by merging the 2 edges this vertex connects to into one.\n"
98 " :type join_faces: bool\n"
99 " :return: The resulting edge from the collapse operation.\n"
100 " :rtype: :class:`bmesh.types.BMEdge`\n");
112 if (!PyArg_ParseTuple(args,
113 "O!O!fi:vert_collapse_faces",
127 if (!(py_edge->
e->
v1 == py_vert->
v || py_edge->
e->
v2 == py_vert->
v)) {
128 PyErr_SetString(PyExc_ValueError,
129 "vert_collapse_faces(vert, edge): the vertex is not found in the edge");
134 PyErr_SetString(PyExc_ValueError,
135 "vert_collapse_faces(vert, edge): vert has more than 2 connected edges");
142 bm, py_edge->
e, py_vert->
v,
clamp_f(fac, 0.0f, 1.0f),
true, do_join_faces,
true,
true);
148 PyErr_SetString(PyExc_ValueError,
149 "vert_collapse_faces(vert, edge): no new edge created, internal error");
154 ".. method:: vert_dissolve(vert)\n"
156 " Dissolve this vertex (will be removed).\n"
158 " :arg vert: The vert to be dissolved.\n"
159 " :type vert: :class:`bmesh.types.BMVert`\n"
160 " :return: True when the vertex dissolve is successful.\n"
161 " :rtype: boolean\n");
168 if (!PyArg_ParseTuple(args,
"O!:vert_dissolve", &
BPy_BMVert_Type, &py_vert)) {
180 ".. method:: vert_splice(vert, vert_target)\n"
182 " Splice vert into vert_target.\n"
184 " :arg vert: The vertex to be removed.\n"
185 " :type vert: :class:`bmesh.types.BMVert`\n"
186 " :arg vert_target: The vertex to use.\n"
187 " :type vert_target: :class:`bmesh.types.BMVert`\n"
189 " .. note:: The verts mustn't share an edge or face.\n");
199 if (!PyArg_ParseTuple(args,
214 if (py_vert->
v == py_vert_target->
v) {
215 PyErr_SetString(PyExc_ValueError,
"vert_splice(...): vert arguments match");
220 PyErr_SetString(PyExc_ValueError,
"vert_splice(...): verts can't share an edge");
225 PyErr_SetString(PyExc_ValueError,
"vert_splice(...): verts can't share a face");
238 ".. method:: vert_separate(vert, edges)\n"
240 " Separate this vertex at every edge.\n"
242 " :arg vert: The vert to be separated.\n"
243 " :type vert: :class:`bmesh.types.BMVert`\n"
244 " :arg edges: The edges to separated.\n"
245 " :type edges: :class:`bmesh.types.BMEdge`\n"
246 " :return: The newly separated verts (including the vertex passed).\n"
247 " :rtype: tuple of :class:`bmesh.types.BMVert`\n");
259 Py_ssize_t edge_array_len;
263 if (!PyArg_ParseTuple(args,
"O!O:vert_separate", &
BPy_BMVert_Type, &py_vert, &edge_seq)) {
279 "vert_separate(...)");
281 if (edge_array ==
NULL) {
290 PyMem_FREE(edge_array);
296 ".. method:: edge_split(edge, vert, fac)\n"
298 " Split an edge, return the newly created data.\n"
300 " :arg edge: The edge to split.\n"
301 " :type edge: :class:`bmesh.types.BMEdge`\n"
302 " :arg vert: One of the verts on the edge, defines the split direction.\n"
303 " :type vert: :class:`bmesh.types.BMVert`\n"
304 " :arg fac: The point on the edge where the new vert will be created [0 - 1].\n"
305 " :type fac: float\n"
306 " :return: The newly created (edge, vert) pair.\n"
318 if (!PyArg_ParseTuple(args,
332 if (!(py_edge->
e->
v1 == py_vert->
v || py_edge->
e->
v2 == py_vert->
v)) {
333 PyErr_SetString(PyExc_ValueError,
334 "edge_split(edge, vert): the vertex is not found in the edge");
342 if (v_new && e_new) {
343 PyObject *
ret = PyTuple_New(2);
349 PyErr_SetString(PyExc_ValueError,
350 "edge_split(edge, vert): couldn't split the edge, internal error");
355 ".. method:: edge_rotate(edge, ccw=False)\n"
357 " Rotate the edge and return the newly created edge.\n"
358 " If rotating the edge fails, None will be returned.\n"
360 " :arg edge: The edge to rotate.\n"
361 " :type edge: :class:`bmesh.types.BMEdge`\n"
362 " :arg ccw: When True the edge will be rotated counter clockwise.\n"
363 " :type ccw: boolean\n"
364 " :return: The newly rotated edge.\n"
365 " :rtype: :class:`bmesh.types.BMEdge`\n");
374 if (!PyArg_ParseTuple(
393 bpy_bm_utils_face_split_doc,
394 ".. method:: face_split(face, vert_a, vert_b, coords=(), use_exist=True, example=None)\n"
396 " Face split with optional intermediate points.\n"
398 " :arg face: The face to cut.\n"
399 " :type face: :class:`bmesh.types.BMFace`\n"
400 " :arg vert_a: First vertex to cut in the face (face must contain the vert).\n"
401 " :type vert_a: :class:`bmesh.types.BMVert`\n"
402 " :arg vert_b: Second vertex to cut in the face (face must contain the vert).\n"
403 " :type vert_b: :class:`bmesh.types.BMVert`\n"
404 " :arg coords: Optional argument to define points in between *vert_a* and *vert_b*.\n"
405 " :type coords: sequence of float triplets\n"
406 " :arg use_exist: .Use an existing edge if it exists (Only used when *coords* argument is "
407 "empty or omitted)\n"
408 " :type use_exist: boolean\n"
409 " :arg example: Newly created edge will copy settings from this one.\n"
410 " :type example: :class:`bmesh.types.BMEdge`\n"
411 " :return: The newly created face or None on failure.\n"
412 " :rtype: (:class:`bmesh.types.BMFace`, :class:`bmesh.types.BMLoop`) pair\n");
415 static const char *kwlist[] = {
416 "face",
"vert_a",
"vert_b",
"coords",
"use_exist",
"example",
NULL};
423 PyObject *py_coords =
NULL;
424 bool edge_exists =
true;
435 if (!PyArg_ParseTupleAndKeywords(args,
437 "O!O!O!|$OO&O!:face_split",
457 if (py_edge_example) {
467 PyErr_SetString(PyExc_ValueError,
468 "face_split(...): one of the verts passed is not found in the face");
472 if (py_vert_a->
v == py_vert_b->
v) {
473 PyErr_SetString(PyExc_ValueError,
"face_split(...): vert arguments must differ");
485 PyErr_SetString(PyExc_ValueError,
"face_split(...): verts are adjacent in the face");
501 py_edge_example ? py_edge_example->
e :
NULL);
510 py_edge_example ? py_edge_example->
e :
NULL,
514 if (f_new && l_new) {
515 PyObject *
ret = PyTuple_New(2);
521 PyErr_SetString(PyExc_ValueError,
"face_split(...): couldn't split the face, internal error");
526 ".. method:: face_split_edgenet(face, edgenet)\n"
528 " Splits a face into any number of regions defined by an edgenet.\n"
530 " :arg face: The face to split.\n"
531 " :type face: :class:`bmesh.types.BMFace`\n"
532 " :arg face: The face to split.\n"
533 " :type face: :class:`bmesh.types.BMFace`\n"
534 " :arg edgenet: Sequence of edges.\n"
535 " :type edgenet: :class:`bmesh.types.BMEdge`\n"
536 " :return: The newly created faces.\n"
537 " :rtype: tuple of (:class:`bmesh.types.BMFace`)\n"
541 " Regions defined by edges need to connect to the face, otherwise they're "
542 "ignored as loose edges.\n");
547 static const char *kwlist[] = {
"face",
"edgenet",
NULL};
553 Py_ssize_t edge_array_len;
561 if (!PyArg_ParseTupleAndKeywords(args,
563 "O!O:face_split_edgenet",
583 "face_split_edgenet(...)");
585 if (edge_array ==
NULL) {
593 PyMem_FREE(edge_array);
603 PyErr_SetString(PyExc_ValueError,
604 "face_split_edgenet(...): couldn't split the face, internal error");
609 ".. method:: face_join(faces, remove=True)\n"
611 " Joins a sequence of faces.\n"
613 " :arg faces: Sequence of faces.\n"
614 " :type faces: :class:`bmesh.types.BMFace`\n"
615 " :arg remove: Remove the edges and vertices between the faces.\n"
616 " :type remove: boolean\n"
617 " :return: The newly created face or None on failure.\n"
618 " :rtype: :class:`bmesh.types.BMFace`\n");
622 PyObject *py_face_array;
624 Py_ssize_t face_seq_len = 0;
626 bool do_remove =
true;
628 if (!PyArg_ParseTuple(args,
"O|O&:face_join", &py_face_array,
PyC_ParseBool, &do_remove)) {
633 &
bm, py_face_array, 2, PY_SSIZE_T_MAX, &face_seq_len,
BM_FACE,
true,
true,
"face_join(...)");
635 if (face_array ==
NULL) {
643 PyMem_FREE(face_array);
653 bpy_bm_utils_face_vert_separate_doc,
654 ".. method:: face_vert_separate(face, vert)\n"
656 " Rip a vertex in a face away and add a new vertex.\n"
658 " :arg face: The face to separate.\n"
659 " :type face: :class:`bmesh.types.BMFace`\n"
660 " :arg vert: A vertex in the face to separate.\n"
661 " :type vert: :class:`bmesh.types.BMVert`\n"
662 " :return vert: The newly created vertex or None on failure.\n"
663 " :rtype vert: :class:`bmesh.types.BMVert`\n"
667 " This is the same as loop_separate, and has only been added for convenience.\n");
677 if (!PyArg_ParseTuple(args,
678 "O!O!:face_vert_separate",
694 PyErr_SetString(PyExc_ValueError,
"vertex not found in face");
701 if (v_new != v_old) {
709 ".. method:: face_flip(faces)\n"
711 " Flip the faces direction.\n"
713 " :arg face: Face to flip.\n"
714 " :type face: :class:`bmesh.types.BMFace`\n");
718 PyErr_Format(PyExc_TypeError,
719 "face_flip(face): BMFace expected, not '%.200s'",
720 Py_TYPE(value)->tp_name);
732 ".. method:: loop_separate(loop)\n"
734 " Rip a vertex in a face away and add a new vertex.\n"
736 " :arg loop: The loop to separate.\n"
737 " :type loop: :class:`bmesh.types.BMLoop`\n"
738 " :return vert: The newly created vertex or None on failure.\n"
739 " :rtype vert: :class:`bmesh.types.BMVert`\n");
747 PyErr_Format(PyExc_TypeError,
748 "loop_separate(loop): BMLoop expected, not '%.200s'",
749 Py_TYPE(value)->tp_name);
761 if (v_new != v_old) {
769 {
"vert_collapse_edge",
772 bpy_bm_utils_vert_collapse_edge_doc},
773 {
"vert_collapse_faces",
776 bpy_bm_utils_vert_collapse_faces_doc},
780 bpy_bm_utils_vert_dissolve_doc},
784 bpy_bm_utils_vert_splice_doc},
788 bpy_bm_utils_vert_separate_doc},
792 bpy_bm_utils_edge_split_doc},
796 bpy_bm_utils_edge_rotate_doc},
799 METH_VARARGS | METH_KEYWORDS,
800 bpy_bm_utils_face_split_doc},
801 {
"face_split_edgenet",
803 METH_VARARGS | METH_KEYWORDS,
804 bpy_bm_utils_face_split_edgenet_doc},
806 {
"face_vert_separate",
809 bpy_bm_utils_face_vert_separate_doc},
814 bpy_bm_utils_loop_separate_doc},
818 PyDoc_STRVAR(BPy_BM_utils_doc,
"This module provides access to blenders bmesh data structures.");
820 PyModuleDef_HEAD_INIT,
MINLINE float clamp_f(float value, float min, float max)
#define UNUSED_VARS_NDEBUG(...)
Read Guarded memory(de)allocation.
BMFace * BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del)
Join Connected Faces.
void BM_vert_separate(BMesh *bm, BMVert *v, BMEdge **e_in, int e_in_len, const bool copy_select, BMVert ***r_vout, int *r_vout_len)
bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src)
Splice Vert.
ATTR_WARN_UNUSED_RESULT BMesh * bm
BMVert * BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
Edge Split.
BMEdge * BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac, const bool do_del, const bool join_faces, const bool kill_degenerate_faces, const bool kill_duplicate_faces)
Vert Collapse Faces.
bool BM_vert_dissolve(BMesh *bm, BMVert *v)
Dissolve Vert.
BMVert * BM_face_loop_separate(BMesh *bm, BMLoop *l_sep)
Rip a single face from a vertex fan.
BMEdge * BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool kill_degenerate_faces, const bool kill_duplicate_faces)
Vert Collapse Faces.
BMFace * BM_face_split(BMesh *bm, BMFace *f, BMLoop *l_a, BMLoop *l_b, BMLoop **r_l, BMEdge *example, const bool no_double)
Face Split.
BMFace * BM_face_split_n(BMesh *bm, BMFace *f, BMLoop *l_a, BMLoop *l_b, float cos[][3], int n, BMLoop **r_l, BMEdge *example)
Face Split with intermediate points.
BMEdge * BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag)
Rotate Edge.
void BM_face_normal_flip(BMesh *bm, BMFace *f)
bool BM_face_split_edgenet(BMesh *bm, BMFace *f, BMEdge **edge_net, const int edge_net_len, BMFace ***r_face_arr, int *r_face_arr_len)
PyObject * BPy_BMEdge_CreatePyObject(BMesh *bm, BMEdge *e)
PyObject * BPy_BMLoop_CreatePyObject(BMesh *bm, BMLoop *l)
PyObject * BPy_BMFace_Array_As_Tuple(BMesh *bm, BMFace **elem, Py_ssize_t elem_len)
PyObject * BPy_BMVert_Array_As_Tuple(BMesh *bm, BMVert **elem, Py_ssize_t elem_len)
PyObject * BPy_BMFace_CreatePyObject(BMesh *bm, BMFace *f)
PyTypeObject BPy_BMEdge_Type
PyTypeObject BPy_BMVert_Type
PyTypeObject BPy_BMFace_Type
PyObject * BPy_BMVert_CreatePyObject(BMesh *bm, BMVert *v)
void * BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, const char htype, const bool do_unique_check, const bool do_bm_check, const char *error_prefix)
#define BPy_BMFace_Check(v)
#define BPY_BM_CHECK_OBJ(obj)
#define BPy_BMLoop_Check(v)
#define BPY_BM_CHECK_SOURCE_OBJ(bm, errmsg,...)
static PyObject * bpy_bm_utils_vert_splice(PyObject *UNUSED(self), PyObject *args)
static struct PyModuleDef BPy_BM_utils_module_def
PyDoc_STRVAR(bpy_bm_utils_vert_collapse_edge_doc, ".. method:: vert_collapse_edge(vert, edge)\n" "\n" " Collapse a vertex into an edge.\n" "\n" " :arg vert: The vert that will be collapsed.\n" " :type vert: :class:`bmesh.types.BMVert`\n" " :arg edge: The edge to collapse into.\n" " :type edge: :class:`bmesh.types.BMEdge`\n" " :return: The resulting edge from the collapse operation.\n" " :rtype: :class:`bmesh.types.BMEdge`\n")
static struct PyMethodDef BPy_BM_utils_methods[]
static PyObject * bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
static PyObject * bpy_bm_utils_edge_split(PyObject *UNUSED(self), PyObject *args)
PyObject * BPyInit_bmesh_utils(void)
static PyObject * bpy_bm_utils_face_vert_separate(PyObject *UNUSED(self), PyObject *args)
static PyObject * bpy_bm_utils_loop_separate(PyObject *UNUSED(self), BPy_BMLoop *value)
static PyObject * bpy_bm_utils_vert_collapse_edge(PyObject *UNUSED(self), PyObject *args)
static PyObject * bpy_bm_utils_vert_collapse_faces(PyObject *UNUSED(self), PyObject *args)
static PyObject * bpy_bm_utils_face_split_edgenet(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
static PyObject * bpy_bm_utils_vert_dissolve(PyObject *UNUSED(self), PyObject *args)
static PyObject * bpy_bm_utils_vert_separate(PyObject *UNUSED(self), PyObject *args)
static PyObject * bpy_bm_utils_face_flip(PyObject *UNUSED(self), BPy_BMFace *value)
static PyObject * bpy_bm_utils_edge_rotate(PyObject *UNUSED(self), PyObject *args)
static PyObject * bpy_bm_utils_face_join(PyObject *UNUSED(self), PyObject *args)
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
bool BM_vert_pair_share_face_check(BMVert *v_a, BMVert *v_b)
BMLoop * BM_face_vert_share_loop(BMFace *f, BMVert *v)
Return the Loop Shared by Face and Vertex.
BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
#define BM_vert_edge_count_is_over(v, n)
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMLoop * l_b
void(* MEM_freeN)(void *vmemh)
int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, const char *error_prefix)
int PyC_ParseBool(PyObject *o, void *p)
#define PyTuple_SET_ITEMS(op_arg,...)
PyObject_VAR_HEAD struct BMesh * bm
PyObject_VAR_HEAD struct BMesh * bm
PyObject_VAR_HEAD struct BMesh * bm
PyObject_VAR_HEAD struct BMesh * bm