Example #1
0
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;
		}
	}
}