adding ed.key and face.edge_keys
avoids a lot of boiler place code in scripts that need to build connectivity.
This commit is contained in:
@@ -2223,7 +2223,7 @@ static PyObject *MEdge_getIndex( BPy_MEdge * self )
|
||||
}
|
||||
|
||||
/*
|
||||
* get an edge's select state
|
||||
* get an edge's flag
|
||||
*/
|
||||
|
||||
static PyObject *MEdge_getMFlagBits( BPy_MEdge * self, void * type )
|
||||
@@ -2237,7 +2237,7 @@ static PyObject *MEdge_getMFlagBits( BPy_MEdge * self, void * type )
|
||||
}
|
||||
|
||||
/*
|
||||
* get an edge's select state
|
||||
* get an edge's length
|
||||
*/
|
||||
|
||||
static PyObject *MEdge_getLength( BPy_MEdge * self )
|
||||
@@ -2262,6 +2262,24 @@ static PyObject *MEdge_getLength( BPy_MEdge * self )
|
||||
return PyFloat_FromDouble( sqrt( dot ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* get an key for using in a dictionary or set key
|
||||
*/
|
||||
|
||||
static PyObject *MEdge_getKey( BPy_MEdge * self )
|
||||
{
|
||||
MEdge *edge = MEdge_get_pointer( self );
|
||||
PyObject *attr = PyTuple_New( 2 );
|
||||
if (edge->v1 > edge->v2) {
|
||||
PyTuple_SetItem( attr, 0, PyInt_FromLong(edge->v2) );
|
||||
PyTuple_SetItem( attr, 1, PyInt_FromLong(edge->v1) );
|
||||
} else {
|
||||
PyTuple_SetItem( attr, 0, PyInt_FromLong(edge->v1) );
|
||||
PyTuple_SetItem( attr, 1, PyInt_FromLong(edge->v2) );
|
||||
}
|
||||
return attr;
|
||||
}
|
||||
|
||||
/*
|
||||
* set an edge's select state
|
||||
*/
|
||||
@@ -2335,6 +2353,10 @@ static PyGetSetDef BPy_MEdge_getseters[] = {
|
||||
{"length",
|
||||
(getter)MEdge_getLength, (setter)NULL,
|
||||
"edge's length, read only",
|
||||
NULL},
|
||||
{"key",
|
||||
(getter)MEdge_getKey, (setter)NULL,
|
||||
"edge's key for using with sets or dictionaries, read only",
|
||||
NULL},
|
||||
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
|
||||
};
|
||||
@@ -4150,6 +4172,95 @@ static int MFace_setCol( BPy_MFace * self, PyObject *value )
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get edge keys for using in a dictionary or set key
|
||||
*/
|
||||
|
||||
static PyObject *MFace_getEdgeKeys( BPy_MFace * self )
|
||||
{
|
||||
MFace *face = MFace_get_pointer( self );
|
||||
PyObject *attr, *edpair;
|
||||
if (face->v4) {
|
||||
attr = PyTuple_New( 4 );
|
||||
edpair = PyTuple_New( 2 );
|
||||
if (face->v1 > face->v2) {
|
||||
PyTuple_SetItem( edpair, 0, PyInt_FromLong(face->v2) );
|
||||
PyTuple_SetItem( edpair, 1, PyInt_FromLong(face->v1) );
|
||||
} else {
|
||||
PyTuple_SetItem( edpair, 0, PyInt_FromLong(face->v1) );
|
||||
PyTuple_SetItem( edpair, 1, PyInt_FromLong(face->v2) );
|
||||
}
|
||||
PyTuple_SetItem( attr, 0, edpair );
|
||||
|
||||
edpair = PyTuple_New( 2 );
|
||||
if (face->v2 > face->v3) {
|
||||
PyTuple_SetItem( edpair, 0, PyInt_FromLong(face->v3) );
|
||||
PyTuple_SetItem( edpair, 1, PyInt_FromLong(face->v2) );
|
||||
} else {
|
||||
PyTuple_SetItem( edpair, 0, PyInt_FromLong(face->v2) );
|
||||
PyTuple_SetItem( edpair, 1, PyInt_FromLong(face->v3) );
|
||||
}
|
||||
PyTuple_SetItem( attr, 1, edpair );
|
||||
|
||||
edpair = PyTuple_New( 2 );
|
||||
if (face->v3 > face->v4) {
|
||||
PyTuple_SetItem( edpair, 0, PyInt_FromLong(face->v4) );
|
||||
PyTuple_SetItem( edpair, 1, PyInt_FromLong(face->v3) );
|
||||
} else {
|
||||
PyTuple_SetItem( edpair, 0, PyInt_FromLong(face->v3) );
|
||||
PyTuple_SetItem( edpair, 1, PyInt_FromLong(face->v4) );
|
||||
}
|
||||
PyTuple_SetItem( attr, 2, edpair );
|
||||
|
||||
edpair = PyTuple_New( 2 );
|
||||
if (face->v4 > face->v1) {
|
||||
PyTuple_SetItem( edpair, 0, PyInt_FromLong(face->v1) );
|
||||
PyTuple_SetItem( edpair, 1, PyInt_FromLong(face->v4) );
|
||||
} else {
|
||||
PyTuple_SetItem( edpair, 0, PyInt_FromLong(face->v4) );
|
||||
PyTuple_SetItem( edpair, 1, PyInt_FromLong(face->v1) );
|
||||
}
|
||||
PyTuple_SetItem( attr, 3, edpair );
|
||||
|
||||
} else {
|
||||
|
||||
attr = PyTuple_New( 3 );
|
||||
edpair = PyTuple_New( 2 );
|
||||
if (face->v1 > face->v2) {
|
||||
PyTuple_SetItem( edpair, 0, PyInt_FromLong(face->v2) );
|
||||
PyTuple_SetItem( edpair, 1, PyInt_FromLong(face->v1) );
|
||||
} else {
|
||||
PyTuple_SetItem( edpair, 0, PyInt_FromLong(face->v1) );
|
||||
PyTuple_SetItem( edpair, 1, PyInt_FromLong(face->v2) );
|
||||
}
|
||||
PyTuple_SetItem( attr, 0, edpair );
|
||||
|
||||
edpair = PyTuple_New( 2 );
|
||||
if (face->v2 > face->v3) {
|
||||
PyTuple_SetItem( edpair, 0, PyInt_FromLong(face->v3) );
|
||||
PyTuple_SetItem( edpair, 1, PyInt_FromLong(face->v2) );
|
||||
} else {
|
||||
PyTuple_SetItem( edpair, 0, PyInt_FromLong(face->v2) );
|
||||
PyTuple_SetItem( edpair, 1, PyInt_FromLong(face->v3) );
|
||||
}
|
||||
PyTuple_SetItem( attr, 1, edpair );
|
||||
|
||||
edpair = PyTuple_New( 2 );
|
||||
if (face->v3 > face->v1) {
|
||||
PyTuple_SetItem( edpair, 0, PyInt_FromLong(face->v1) );
|
||||
PyTuple_SetItem( edpair, 1, PyInt_FromLong(face->v3) );
|
||||
} else {
|
||||
PyTuple_SetItem( edpair, 0, PyInt_FromLong(face->v3) );
|
||||
PyTuple_SetItem( edpair, 1, PyInt_FromLong(face->v1) );
|
||||
}
|
||||
PyTuple_SetItem( attr, 2, edpair );
|
||||
}
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
*
|
||||
* Python MFace_Type attributes get/set structure
|
||||
@@ -4228,6 +4339,10 @@ static PyGetSetDef BPy_MFace_getseters[] = {
|
||||
{"uvSel",
|
||||
(getter)MFace_getUVSel, (setter)MFace_setUVSel,
|
||||
"face's UV coordinates select status",
|
||||
NULL},
|
||||
{"edge_keys",
|
||||
(getter)MFace_getEdgeKeys, (setter)NULL,
|
||||
"for each edge this face uses return an ordered tuple edge pair that can be used as a key in a dictionary or set",
|
||||
NULL},
|
||||
|
||||
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
|
||||
|
||||
@@ -381,6 +381,10 @@ class MEdge:
|
||||
changing the select state of an edge changes the select state of the edge's
|
||||
vertices.
|
||||
@type sel: int
|
||||
@ivar key: The edges vert indicies in an ordered tuple, this can be used as a dictionary key. Read-only.
|
||||
|
||||
This is the same as (min(ed.v1.index, ed.v2.index), max(ed.v1.index, ed.v2.index))
|
||||
@type key: typle
|
||||
"""
|
||||
|
||||
def __iter__():
|
||||
@@ -576,6 +580,24 @@ class MFace:
|
||||
@type cent: vector
|
||||
@ivar area: The area of the face. Read-only.
|
||||
@type area: float
|
||||
@ivar edge_keys: A tuple, each item a key that can reference an edge by its ordered indicies. Read-only.
|
||||
This is usefull for building connectivity data
|
||||
Example::
|
||||
from Blender import Mesh
|
||||
me = Mesh.Get('Cube')
|
||||
# a dictionary where the edge is the key, and a list of faces that use it are the value
|
||||
edge_faces = dict([(ed.key, []) for ed in me.edges])
|
||||
|
||||
# Add the faces to the dict
|
||||
for f in me.faces:
|
||||
for key in f.edge_keys:
|
||||
edge_faces[key].append(f) # add this face to the edge as a user
|
||||
|
||||
# Print the edges and the number of face users
|
||||
for key, face_users in edge_faces.iteritems():
|
||||
print 'Edge:', key, 'uses:', len(face_users),'faces'
|
||||
|
||||
@type edge_keys: tuple
|
||||
@note: there are regular faces and textured faces in Blender, both currently
|
||||
with their own selection and visibility states, due to a mix of old and new
|
||||
code. To (un)select or (un)hide regular faces (visible in EditMode), use
|
||||
|
||||
Reference in New Issue
Block a user