static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { static const char *kwlist[] = {"face", "vert_a", "vert_b", "coords", "use_exist", "example", NULL}; BPy_BMFace *py_face; BPy_BMVert *py_vert_a; BPy_BMVert *py_vert_b; /* optional */ PyObject *py_coords = NULL; int edge_exists = TRUE; BPy_BMEdge *py_edge_example = NULL; float *coords; int ncoords = 0; BMesh *bm; BMFace *f_new = NULL; BMLoop *l_new = NULL; if (!PyArg_ParseTupleAndKeywords(args, kw, "O!O!O!|OiO!:face_split", (char **)kwlist, &BPy_BMFace_Type, &py_face, &BPy_BMVert_Type, &py_vert_a, &BPy_BMVert_Type, &py_vert_b, &py_coords, &edge_exists, &BPy_BMEdge_Type, &py_edge_example)) { return NULL; } BPY_BM_CHECK_OBJ(py_face); BPY_BM_CHECK_OBJ(py_vert_a); BPY_BM_CHECK_OBJ(py_vert_b); if (py_edge_example) { BPY_BM_CHECK_OBJ(py_edge_example); } /* this doubles for checking that the verts are in the same mesh */ if (BM_vert_in_face(py_face->f, py_vert_a->v) == FALSE || BM_vert_in_face(py_face->f, py_vert_b->v) == FALSE) { PyErr_SetString(PyExc_ValueError, "face_split(...): one of the verts passed is not found in the face"); return NULL; } if (py_vert_a->v == py_vert_b->v) { PyErr_SetString(PyExc_ValueError, "face_split(...): vert arguments must differ"); return NULL; } if (py_coords) { ncoords = mathutils_array_parse_alloc_v(&coords, 3, py_coords, "face_split(...): "); if (ncoords == -1) { return NULL; } } /* --- main function body --- */ bm = py_face->bm; if (ncoords) { f_new = BM_face_split_n(bm, py_face->f, py_vert_a->v, py_vert_b->v, (float (*)[3])coords, ncoords, &l_new, py_edge_example ? py_edge_example->e : NULL); } else { f_new = BM_face_split(bm, py_face->f, py_vert_a->v, py_vert_b->v, &l_new, py_edge_example ? py_edge_example->e : NULL, edge_exists); } if (f_new && l_new) { PyObject *ret = PyTuple_New(2); PyTuple_SET_ITEM(ret, 0, BPy_BMFace_CreatePyObject(bm, f_new)); PyTuple_SET_ITEM(ret, 1, BPy_BMLoop_CreatePyObject(bm, l_new)); return ret; } else { PyErr_SetString(PyExc_ValueError, "face_split(...): couldn't split the face, internal error"); return NULL; } }
/* note: this function could be optimized by some spatial structure */ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *args) { PyObject *py_planes; float (*planes)[4]; unsigned int planes_len; if (!PyArg_ParseTuple(args, "O:points_in_planes", &py_planes)) { return NULL; } if ((planes_len = mathutils_array_parse_alloc_v((float **)&planes, 4, py_planes, "points_in_planes")) == -1) { return NULL; } else { /* note, this could be refactored into plain C easy - py bits are noted */ const float eps = 0.0001f; const unsigned int len = (unsigned int)planes_len; unsigned int i, j, k, l; float n1n2[3], n2n3[3], n3n1[3]; float potentialVertex[3]; char *planes_used = MEM_callocN(sizeof(char) * len, __func__); /* python */ PyObject *py_verts = PyList_New(0); PyObject *py_plene_index = PyList_New(0); for (i = 0; i < len; i++) { const float *N1 = planes[i]; for (j = i + 1; j < len; j++) { const float *N2 = planes[j]; cross_v3_v3v3(n1n2, N1, N2); if (len_squared_v3(n1n2) > eps) { for (k = j + 1; k < len; k++) { const float *N3 = planes[k]; cross_v3_v3v3(n2n3, N2, N3); if (len_squared_v3(n2n3) > eps) { cross_v3_v3v3(n3n1, N3, N1); if (len_squared_v3(n3n1) > eps) { const float quotient = dot_v3v3(N1, n2n3); if (fabsf(quotient) > eps) { /* potentialVertex = (n2n3 * N1[3] + n3n1 * N2[3] + n1n2 * N3[3]) * (-1.0 / quotient); */ const float quotient_ninv = -1.0f / quotient; potentialVertex[0] = ((n2n3[0] * N1[3]) + (n3n1[0] * N2[3]) + (n1n2[0] * N3[3])) * quotient_ninv; potentialVertex[1] = ((n2n3[1] * N1[3]) + (n3n1[1] * N2[3]) + (n1n2[1] * N3[3])) * quotient_ninv; potentialVertex[2] = ((n2n3[2] * N1[3]) + (n3n1[2] * N2[3]) + (n1n2[2] * N3[3])) * quotient_ninv; for (l = 0; l < len; l++) { const float *NP = planes[l]; if ((dot_v3v3(NP, potentialVertex) + NP[3]) > 0.000001f) { break; } } if (l == len) { /* ok */ /* python */ PyObject *item = Vector_CreatePyObject(potentialVertex, 3, Py_NEW, NULL); PyList_Append(py_verts, item); Py_DECREF(item); planes_used[i] = planes_used[j] = planes_used[k] = TRUE; } } } } } } } } PyMem_Free(planes); /* now make a list of used planes */ for (i = 0; i < len; i++) { if (planes_used[i]) { PyObject *item = PyLong_FromLong(i); PyList_Append(py_plene_index, item); Py_DECREF(item); } } MEM_freeN(planes_used); { PyObject *ret = PyTuple_New(2); PyTuple_SET_ITEM(ret, 0, py_verts); PyTuple_SET_ITEM(ret, 1, py_plene_index); return ret; } } }