PyMEL: Checking MeshUV connections not possible?


#1

The MeshEdge, MeshFace and MeshVertex -classes has some neat methods for checking if they are connected to other components, such as isConnectedTo(component)

However, when I try and use this like edge.isConnectedTo(uv) I get a TypeError:

raise TypeError, ‘type %s is not supported’ % type(component)

TypeError: type <class ‘pymel.core.general.MeshUV’> is not supported //

Are you kidding me? Documentation says isConnectedTo(component) - MeshUV is a component, yet this fails.
Also, why are there no methods in the MeshUV class?

TL:DR:
I want to a fast way of checking if an edge is connected to a UV coordinate without having to do slow operations such as selecting/deselecting or converting selected component types.


#2

Edit again:

Well I might as well reply to this. I tend to avoid PyMEL because it’s just another wrapper on the underlying Maya language interfaces. While it can be extremely convenient for what you might need to do, it might hide functionality that might be otherwise available to you.

Case in point, you should spend some time learning the Python API as it can give you lower level access to things like this and be scriptable to boot.

I’ve written up a quick example that tests if a given uv_id is on an edge_id:

import maya.api.OpenMaya as om
import maya.cmds as cmds

def get_local_vertex_id( face_vertices, vert_id ):
	"""
	Helper function that returns the local face-relative index
	given a mesh-relative index. If it cannot locate vert_id
	in the face_vertices list, it returns -1.
	
	Many of the iterator interfaces look for a local face-relative
	index rather than the mesh-relative vertex index. That is to say
	if your face has vertices [10, 12, 11, 9]. Then:
		
		vertex 10 is at local index 0
		vertex 12 is at local index 1
		etc.
	"""
	for i in range(len(face_vertices)):
		if vert_id == face_vertices[i]:
			return i
	return -1

def is_uv_on_edge( mesh, edge_id, uv_id ):
	"""
	Given the name of a mesh transform or shape, this function
	will return True if the given edge_id is connected to the
	given uv_id on the default map set.
	"""
	# Retrieve the mesh DAG path
	sel_list = om.MSelectionList()
	sel_list.add( mesh_shape )
	path = sel_list.getDagPath( 0 )
	path.extendToShape()
	
	# Retrieve the edge vertices.
	# It's easier to do it by vertices than edges because
	# of the interface.
	mesh_fn = om.MFnMesh( path.node() )
	verts = mesh_fn.getEdgeVertices( edge_id )
	
	# Iterate over the faces of the polygon.
	iter = om.MItMeshPolygon( path.node() )
	while not iter.isDone():
		# For each face, look at the vertices that make up the face
		# and test to see if the edge vertices appear in the face.
		# If so, look up the UV id for that local vertex and compare
		# if it matches our uv_id
		face_vertices = iter.getVertices()
		for v in verts:
			local_id = get_local_vertex_id( face_vertices, v )
			if local_id < 0:
				continue
			mesh_uv = iter.getUVIndex( local_id )
			if mesh_uv == uv_id:
				return True

		# Passing in iter into the next must be a Python API 2.0 bug
		iter.next(iter)
	return False
	
if __name__ == '__main__':
	# Quick polyCube testing.
	# edge_id = 0 should be linked to uv_id=(0,1)
	cmds.file(f=True, new=True)
	mesh = cmds.polyCube()[0]
	edge_id = 0
	uv_id = 1
	print is_uv_on_edge( mesh, edge_id, uv_id )

#3

Thanks. You have an error in the code (variable called mesh_shape instead of mesh) but other than that minor fault things are working nicely!


#4

Ah my bad. I renamed it and missed that one. I’m reluctant to edit that post because of that weird bug that throws off whitespace formatting for code text on this forum. Glad to hear it’s working.