py api, bmesh
- add BMEdge.calc_face_angle_signed() which gives a negative angle for for concave edges. - add BMEdge.is_convex
This commit is contained in:
@@ -775,6 +775,27 @@ bool BM_edge_is_contiguous(BMEdge *e)
|
||||
(l_other->v != l->v));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the edge is convex or concave
|
||||
* (depends on face winding)
|
||||
*/
|
||||
bool BM_edge_is_convex(BMEdge *e)
|
||||
{
|
||||
if (BM_edge_is_manifold(e)) {
|
||||
BMLoop *l1 = e->l;
|
||||
BMLoop *l2 = e->l->radial_next;
|
||||
if (!equals_v3v3(l1->f->no, l2->f->no)) {
|
||||
float cross[3];
|
||||
float l_dir[3];
|
||||
cross_v3_v3v3(cross, l1->f->no, l2->f->no);
|
||||
/* we assume contiguous normals, otherwise the result isn't meaningful */
|
||||
sub_v3_v3v3(l_dir, l1->next->v->co, l1->v->co);
|
||||
return (dot_v3v3(l_dir, cross) > 0.0f);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether or not an edge is on the boundary
|
||||
* of a shell (has one face associated with it)
|
||||
@@ -1152,6 +1173,27 @@ float BM_edge_calc_face_angle(BMEdge *e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief BMESH EDGE/FACE ANGLE
|
||||
*
|
||||
* Calculates the angle between two faces.
|
||||
* Assumes the face normals are correct.
|
||||
*
|
||||
* \return angle in radians
|
||||
*/
|
||||
float BM_edge_calc_face_angle_signed(BMEdge *e)
|
||||
{
|
||||
if (BM_edge_is_manifold(e)) {
|
||||
BMLoop *l1 = e->l;
|
||||
BMLoop *l2 = e->l->radial_next;
|
||||
const float angle = angle_normalized_v3v3(l1->f->no, l2->f->no);
|
||||
return BM_edge_is_convex(e) ? angle : -angle;
|
||||
}
|
||||
else {
|
||||
return DEG2RADF(90.0f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief BMESH EDGE/FACE TANGENT
|
||||
*
|
||||
|
||||
@@ -62,6 +62,7 @@ bool BM_vert_is_manifold(BMVert *v);
|
||||
bool BM_edge_is_manifold(BMEdge *e);
|
||||
bool BM_edge_is_boundary(BMEdge *e);
|
||||
bool BM_edge_is_contiguous(BMEdge *e);
|
||||
bool BM_edge_is_convex(BMEdge *e);
|
||||
|
||||
bool BM_loop_is_convex(BMLoop *l);
|
||||
|
||||
@@ -71,6 +72,7 @@ void BM_loop_calc_face_direction(BMLoop *l, float r_normal[3]);
|
||||
void BM_loop_calc_face_tangent(BMLoop *l, float r_tangent[3]);
|
||||
|
||||
float BM_edge_calc_face_angle(BMEdge *e);
|
||||
float BM_edge_calc_face_angle_signed(BMEdge *e);
|
||||
void BM_edge_calc_face_tangent(BMEdge *e, BMLoop *e_loop, float r_tangent[3]);
|
||||
|
||||
float BM_vert_calc_edge_angle(BMVert *v);
|
||||
|
||||
@@ -423,6 +423,15 @@ static PyObject *bpy_bmedge_is_contiguous_get(BPy_BMEdge *self)
|
||||
return PyBool_FromLong(BM_edge_is_contiguous(self->e));
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpy_bmedge_is_convex_doc,
|
||||
"True when this edge joins 2 convex faces, depends on a valid face normal (read-only).\n\n:type: boolean"
|
||||
);
|
||||
static PyObject *bpy_bmedge_is_convex_get(BPy_BMEdge *self)
|
||||
{
|
||||
BPY_BM_CHECK_OBJ(self);
|
||||
return PyBool_FromLong(BM_edge_is_convex(self->e));
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpy_bmedge_is_wire_doc,
|
||||
"True when this edge is not connected to any faces (read-only).\n\n:type: boolean"
|
||||
);
|
||||
@@ -569,10 +578,10 @@ static PyObject *bpy_bmloop_link_loop_radial_prev_get(BPy_BMLoop *self)
|
||||
return BPy_BMLoop_CreatePyObject(self->bm, self->l->radial_prev);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpy_bm_is_convex_doc,
|
||||
"True when this loop is at the convex corner of a face, depends on a valid face normal (read-only).\n\n:type: :class:`BMLoop`"
|
||||
PyDoc_STRVAR(bpy_bmloop_is_convex_doc,
|
||||
"True when this loop is at the convex corner of a face, depends on a valid face normal (read-only).\n\n:type: boolean"
|
||||
);
|
||||
static PyObject *bpy_bm_is_convex_get(BPy_BMLoop *self)
|
||||
static PyObject *bpy_bmloop_is_convex_get(BPy_BMLoop *self)
|
||||
{
|
||||
BPY_BM_CHECK_OBJ(self);
|
||||
return PyBool_FromLong(BM_loop_is_convex(self->l));
|
||||
@@ -690,6 +699,7 @@ static PyGetSetDef bpy_bmedge_getseters[] = {
|
||||
/* readonly checks */
|
||||
{(char *)"is_manifold", (getter)bpy_bmedge_is_manifold_get, (setter)NULL, (char *)bpy_bmedge_is_manifold_doc, NULL},
|
||||
{(char *)"is_contiguous", (getter)bpy_bmedge_is_contiguous_get, (setter)NULL, (char *)bpy_bmedge_is_contiguous_doc, NULL},
|
||||
{(char *)"is_convex", (getter)bpy_bmedge_is_convex_get, (setter)NULL, (char *)bpy_bmedge_is_convex_doc, NULL},
|
||||
{(char *)"is_wire", (getter)bpy_bmedge_is_wire_get, (setter)NULL, (char *)bpy_bmedge_is_wire_doc, NULL},
|
||||
{(char *)"is_boundary", (getter)bpy_bmedge_is_boundary_get, (setter)NULL, (char *)bpy_bmedge_is_boundary_doc, NULL},
|
||||
{(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
|
||||
@@ -741,8 +751,8 @@ static PyGetSetDef bpy_bmloop_getseters[] = {
|
||||
{(char *)"link_loop_radial_prev", (getter)bpy_bmloop_link_loop_radial_prev_get, (setter)NULL, (char *)bpy_bmloop_link_loop_radial_prev_doc, NULL},
|
||||
|
||||
/* readonly checks */
|
||||
{(char *)"is_convex", (getter)bpy_bm_is_convex_get, (setter)NULL, (char *)bpy_bm_is_convex_doc, NULL},
|
||||
{(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
|
||||
{(char *)"is_convex", (getter)bpy_bmloop_is_convex_get, (setter)NULL, (char *)bpy_bmloop_is_convex_doc, NULL},
|
||||
{(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
|
||||
|
||||
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
|
||||
};
|
||||
@@ -1398,6 +1408,18 @@ static PyObject *bpy_bmedge_calc_face_angle(BPy_BMEdge *self)
|
||||
return PyFloat_FromDouble(BM_edge_calc_face_angle(self->e));
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpy_bmedge_calc_face_angle_signed_doc,
|
||||
".. method:: calc_face_angle_signed()\n"
|
||||
"\n"
|
||||
" :return: The angle between 2 connected faces in radians (negative for concave join).\n"
|
||||
" :rtype: float\n"
|
||||
);
|
||||
static PyObject *bpy_bmedge_calc_face_angle_signed(BPy_BMEdge *self)
|
||||
{
|
||||
BPY_BM_CHECK_OBJ(self);
|
||||
return PyFloat_FromDouble(BM_edge_calc_face_angle_signed(self->e));
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpy_bmedge_calc_tangent_doc,
|
||||
".. method:: calc_tangent(loop)\n"
|
||||
"\n"
|
||||
@@ -2440,6 +2462,7 @@ static struct PyMethodDef bpy_bmedge_methods[] = {
|
||||
|
||||
{"calc_length", (PyCFunction)bpy_bmedge_calc_length, METH_NOARGS, bpy_bmedge_calc_length_doc},
|
||||
{"calc_face_angle", (PyCFunction)bpy_bmedge_calc_face_angle, METH_NOARGS, bpy_bmedge_calc_face_angle_doc},
|
||||
{"calc_face_angle_signed", (PyCFunction)bpy_bmedge_calc_face_angle_signed, METH_NOARGS, bpy_bmedge_calc_face_angle_signed_doc},
|
||||
{"calc_tangent", (PyCFunction)bpy_bmedge_calc_tangent, METH_VARARGS, bpy_bmedge_calc_tangent_doc},
|
||||
|
||||
{"normal_update", (PyCFunction)bpy_bmedge_normal_update, METH_NOARGS, bpy_bmedge_normal_update_doc},
|
||||
|
||||
Reference in New Issue
Block a user