34 #include "../mathutils/mathutils.h"
40 #include "../generic/py_capi_utils.h"
41 #include "../generic/python_utildefines.h"
44 ".. method:: vert_collapse_edge(vert, edge)\n"
46 " Collapse a vertex into an edge.\n"
48 " :arg vert: The vert that will be collapsed.\n"
49 " :type vert: :class:`bmesh.types.BMVert`\n"
50 " :arg edge: The edge to collapse into.\n"
51 " :type edge: :class:`bmesh.types.BMEdge`\n"
52 " :return: The resulting edge from the collapse operation.\n"
53 " :rtype: :class:`bmesh.types.BMEdge`\n");
62 if (!PyArg_ParseTuple(args,
63 "O!O!:vert_collapse_edge",
75 if (!(py_edge->
e->
v1 == py_vert->
v || py_edge->
e->
v2 == py_vert->
v)) {
76 PyErr_SetString(PyExc_ValueError,
77 "vert_collapse_edge(vert, edge): the vertex is not found in the edge");
82 PyErr_SetString(PyExc_ValueError,
83 "vert_collapse_edge(vert, edge): vert has more than 2 connected edges");
95 PyErr_SetString(PyExc_ValueError,
96 "vert_collapse_edge(vert, edge): no new edge created, internal error");
101 ".. method:: vert_collapse_faces(vert, edge, fac, join_faces)\n"
103 " Collapses a vertex that has only two manifold edges onto a vertex it shares an "
106 " :arg vert: The vert that will be collapsed.\n"
107 " :type vert: :class:`bmesh.types.BMVert`\n"
108 " :arg edge: The edge to collapse into.\n"
109 " :type edge: :class:`bmesh.types.BMEdge`\n"
110 " :arg fac: The factor to use when merging customdata [0 - 1].\n"
111 " :type fac: float\n"
112 " :arg join_faces: When true the faces around the vertex will be joined otherwise "
113 "collapse the vertex by merging the 2 edges this vertex connects to into one.\n"
114 " :type join_faces: bool\n"
115 " :return: The resulting edge from the collapse operation.\n"
116 " :rtype: :class:`bmesh.types.BMEdge`\n");
128 if (!PyArg_ParseTuple(args,
129 "O!O!fi:vert_collapse_faces",
143 if (!(py_edge->
e->
v1 == py_vert->
v || py_edge->
e->
v2 == py_vert->
v)) {
144 PyErr_SetString(PyExc_ValueError,
145 "vert_collapse_faces(vert, edge): the vertex is not found in the edge");
150 PyErr_SetString(PyExc_ValueError,
151 "vert_collapse_faces(vert, edge): vert has more than 2 connected edges");
158 bm, py_edge->
e, py_vert->
v,
clamp_f(fac, 0.0f, 1.0f),
true, do_join_faces,
true,
true);
164 PyErr_SetString(PyExc_ValueError,
165 "vert_collapse_faces(vert, edge): no new edge created, internal error");
170 ".. method:: vert_dissolve(vert)\n"
172 " Dissolve this vertex (will be removed).\n"
174 " :arg vert: The vert to be dissolved.\n"
175 " :type vert: :class:`bmesh.types.BMVert`\n"
176 " :return: True when the vertex dissolve is successful.\n"
177 " :rtype: boolean\n");
184 if (!PyArg_ParseTuple(args,
"O!:vert_dissolve", &
BPy_BMVert_Type, &py_vert)) {
196 ".. method:: vert_splice(vert, vert_target)\n"
198 " Splice vert into vert_target.\n"
200 " :arg vert: The vertex to be removed.\n"
201 " :type vert: :class:`bmesh.types.BMVert`\n"
202 " :arg vert_target: The vertex to use.\n"
203 " :type vert_target: :class:`bmesh.types.BMVert`\n"
205 " .. note:: The verts mustn't share an edge or face.\n");
215 if (!PyArg_ParseTuple(args,
230 if (py_vert->
v == py_vert_target->
v) {
231 PyErr_SetString(PyExc_ValueError,
"vert_splice(...): vert arguments match");
236 PyErr_SetString(PyExc_ValueError,
"vert_splice(...): verts can't share an edge");
241 PyErr_SetString(PyExc_ValueError,
"vert_splice(...): verts can't share a face");
254 ".. method:: vert_separate(vert, edges)\n"
256 " Separate this vertex at every edge.\n"
258 " :arg vert: The vert to be separated.\n"
259 " :type vert: :class:`bmesh.types.BMVert`\n"
260 " :arg edges: The edges to separated.\n"
261 " :type edges: :class:`bmesh.types.BMEdge`\n"
262 " :return: The newly separated verts (including the vertex passed).\n"
263 " :rtype: tuple of :class:`bmesh.types.BMVert`\n");
275 Py_ssize_t edge_array_len;
279 if (!PyArg_ParseTuple(args,
"O!O:vert_separate", &
BPy_BMVert_Type, &py_vert, &edge_seq)) {
295 "vert_separate(...)");
297 if (edge_array ==
NULL) {
306 PyMem_FREE(edge_array);
312 ".. method:: edge_split(edge, vert, fac)\n"
314 " Split an edge, return the newly created data.\n"
316 " :arg edge: The edge to split.\n"
317 " :type edge: :class:`bmesh.types.BMEdge`\n"
318 " :arg vert: One of the verts on the edge, defines the split direction.\n"
319 " :type vert: :class:`bmesh.types.BMVert`\n"
320 " :arg fac: The point on the edge where the new vert will be created [0 - 1].\n"
321 " :type fac: float\n"
322 " :return: The newly created (edge, vert) pair.\n"
334 if (!PyArg_ParseTuple(args,
348 if (!(py_edge->
e->
v1 == py_vert->
v || py_edge->
e->
v2 == py_vert->
v)) {
349 PyErr_SetString(PyExc_ValueError,
350 "edge_split(edge, vert): the vertex is not found in the edge");
358 if (v_new && e_new) {
359 PyObject *
ret = PyTuple_New(2);
365 PyErr_SetString(PyExc_ValueError,
366 "edge_split(edge, vert): couldn't split the edge, internal error");
371 ".. method:: edge_rotate(edge, ccw=False)\n"
373 " Rotate the edge and return the newly created edge.\n"
374 " If rotating the edge fails, None will be returned.\n"
376 " :arg edge: The edge to rotate.\n"
377 " :type edge: :class:`bmesh.types.BMEdge`\n"
378 " :arg ccw: When True the edge will be rotated counter clockwise.\n"
379 " :type ccw: boolean\n"
380 " :return: The newly rotated edge.\n"
381 " :rtype: :class:`bmesh.types.BMEdge`\n");
390 if (!PyArg_ParseTuple(
409 bpy_bm_utils_face_split_doc,
410 ".. method:: face_split(face, vert_a, vert_b, coords=(), use_exist=True, example=None)\n"
412 " Face split with optional intermediate points.\n"
414 " :arg face: The face to cut.\n"
415 " :type face: :class:`bmesh.types.BMFace`\n"
416 " :arg vert_a: First vertex to cut in the face (face must contain the vert).\n"
417 " :type vert_a: :class:`bmesh.types.BMVert`\n"
418 " :arg vert_b: Second vertex to cut in the face (face must contain the vert).\n"
419 " :type vert_b: :class:`bmesh.types.BMVert`\n"
420 " :arg coords: Optional argument to define points in between *vert_a* and *vert_b*.\n"
421 " :type coords: sequence of float triplets\n"
422 " :arg use_exist: .Use an existing edge if it exists (Only used when *coords* argument is "
423 "empty or omitted)\n"
424 " :type use_exist: boolean\n"
425 " :arg example: Newly created edge will copy settings from this one.\n"
426 " :type example: :class:`bmesh.types.BMEdge`\n"
427 " :return: The newly created face or None on failure.\n"
428 " :rtype: (:class:`bmesh.types.BMFace`, :class:`bmesh.types.BMLoop`) pair\n");
431 static const char *kwlist[] = {
432 "face",
"vert_a",
"vert_b",
"coords",
"use_exist",
"example",
NULL};
439 PyObject *py_coords =
NULL;
440 bool edge_exists =
true;
451 if (!PyArg_ParseTupleAndKeywords(args,
453 "O!O!O!|OO&O!:face_split",
473 if (py_edge_example) {
483 PyErr_SetString(PyExc_ValueError,
484 "face_split(...): one of the verts passed is not found in the face");
488 if (py_vert_a->
v == py_vert_b->
v) {
489 PyErr_SetString(PyExc_ValueError,
"face_split(...): vert arguments must differ");
501 PyErr_SetString(PyExc_ValueError,
"face_split(...): verts are adjacent in the face");
517 py_edge_example ? py_edge_example->
e :
NULL);
526 py_edge_example ? py_edge_example->
e :
NULL,
530 if (f_new && l_new) {
531 PyObject *
ret = PyTuple_New(2);
537 PyErr_SetString(PyExc_ValueError,
"face_split(...): couldn't split the face, internal error");
542 ".. method:: face_split_edgenet(face, edgenet)\n"
544 " Splits a face into any number of regions defined by an edgenet.\n"
546 " :arg face: The face to split.\n"
547 " :type face: :class:`bmesh.types.BMFace`\n"
548 " :arg face: The face to split.\n"
549 " :type face: :class:`bmesh.types.BMFace`\n"
550 " :arg edgenet: Sequence of edges.\n"
551 " :type edgenet: :class:`bmesh.types.BMEdge`\n"
552 " :return: The newly created faces.\n"
553 " :rtype: tuple of (:class:`bmesh.types.BMFace`)\n"
557 " Regions defined by edges need to connect to the face, otherwise they're "
558 "ignored as loose edges.\n");
563 static const char *kwlist[] = {
"face",
"edgenet",
NULL};
569 Py_ssize_t edge_array_len;
577 if (!PyArg_ParseTupleAndKeywords(args,
579 "O!O:face_split_edgenet",
599 "face_split_edgenet(...)");
601 if (edge_array ==
NULL) {
609 PyMem_FREE(edge_array);
619 PyErr_SetString(PyExc_ValueError,
620 "face_split_edgenet(...): couldn't split the face, internal error");
625 ".. method:: face_join(faces, remove=True)\n"
627 " Joins a sequence of faces.\n"
629 " :arg faces: Sequence of faces.\n"
630 " :type faces: :class:`bmesh.types.BMFace`\n"
631 " :arg remove: Remove the edges and vertices between the faces.\n"
632 " :type remove: boolean\n"
633 " :return: The newly created face or None on failure.\n"
634 " :rtype: :class:`bmesh.types.BMFace`\n");
638 PyObject *py_face_array;
640 Py_ssize_t face_seq_len = 0;
642 bool do_remove =
true;
644 if (!PyArg_ParseTuple(args,
"O|O&:face_join", &py_face_array,
PyC_ParseBool, &do_remove)) {
649 &
bm, py_face_array, 2, PY_SSIZE_T_MAX, &face_seq_len,
BM_FACE,
true,
true,
"face_join(...)");
651 if (face_array ==
NULL) {
659 PyMem_FREE(face_array);
669 bpy_bm_utils_face_vert_separate_doc,
670 ".. method:: face_vert_separate(face, vert)\n"
672 " Rip a vertex in a face away and add a new vertex.\n"
674 " :arg face: The face to separate.\n"
675 " :type face: :class:`bmesh.types.BMFace`\n"
676 " :arg vert: A vertex in the face to separate.\n"
677 " :type vert: :class:`bmesh.types.BMVert`\n"
678 " :return vert: The newly created vertex or None on failure.\n"
679 " :rtype vert: :class:`bmesh.types.BMVert`\n"
683 " This is the same as loop_separate, and has only been added for convenience.\n");
693 if (!PyArg_ParseTuple(args,
694 "O!O!:face_vert_separate",
710 PyErr_SetString(PyExc_ValueError,
"vertex not found in face");
717 if (v_new != v_old) {
725 ".. method:: face_flip(faces)\n"
727 " Flip the faces direction.\n"
729 " :arg face: Face to flip.\n"
730 " :type face: :class:`bmesh.types.BMFace`\n");
734 PyErr_Format(PyExc_TypeError,
735 "face_flip(face): BMFace expected, not '%.200s'",
736 Py_TYPE(value)->tp_name);
748 ".. method:: loop_separate(loop)\n"
750 " Rip a vertex in a face away and add a new vertex.\n"
752 " :arg loop: The loop to separate.\n"
753 " :type loop: :class:`bmesh.types.BMLoop`\n"
754 " :return vert: The newly created vertex or None on failure.\n"
755 " :rtype vert: :class:`bmesh.types.BMVert`\n");
763 PyErr_Format(PyExc_TypeError,
764 "loop_separate(loop): BMLoop expected, not '%.200s'",
765 Py_TYPE(value)->tp_name);
777 if (v_new != v_old) {
785 {
"vert_collapse_edge",
788 bpy_bm_utils_vert_collapse_edge_doc},
789 {
"vert_collapse_faces",
792 bpy_bm_utils_vert_collapse_faces_doc},
796 bpy_bm_utils_vert_dissolve_doc},
800 bpy_bm_utils_vert_splice_doc},
804 bpy_bm_utils_vert_separate_doc},
808 bpy_bm_utils_edge_split_doc},
812 bpy_bm_utils_edge_rotate_doc},
815 METH_VARARGS | METH_KEYWORDS,
816 bpy_bm_utils_face_split_doc},
817 {
"face_split_edgenet",
819 METH_VARARGS | METH_KEYWORDS,
820 bpy_bm_utils_face_split_edgenet_doc},
822 {
"face_vert_separate",
825 bpy_bm_utils_face_vert_separate_doc},
830 bpy_bm_utils_loop_separate_doc},
834 PyDoc_STRVAR(BPy_BM_utils_doc,
"This module provides access to blenders bmesh data structures.");
836 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