Detecting Overlapping UV Shells in Maya

Maya’s Layout command supports separating overlapping shells as part of the layout process, but I would like to detect the overlapping faces myself and let the artist figure out how to separate them.

Going through each polygon and comparing against every other polygon seems really slow… might there be something in the API that could help, or maybe some solution that is already floating around?

Thanks.

it’s not that slow, if you just want the tool to do something like find overlapping shells and select them, assuming you aren’t looking to go more detailed then the shell bounds
compare each shell bound, if bounds overlap then select

def selectOverlappingShells(sel=None):
	import maya.cmds as cmds
	if not sel:
		sel=cmds.ls(sl=True)
		if not sel:
			return "nothing selected or passed"
	currentTool=cmds.currentCtx()
	cmds.setToolTo('selectSuperContext')
	biglist=cmds.ls( cmds.polyListComponentConversion( sel, tf=True ) , fl=True )
	shells=[]
	while len(biglist) > 0:
		cmds.select( biglist[0], r=True )
		cmds.polySelectConstraint(t=0)
		cmds.polySelectConstraint(sh=1,m=2)
		cmds.polySelectConstraint(sh=0,m=0)
		aShell=cmds.ls( sl=True, fl=True )
		shells.append( aShell )
		biglist=list( set(biglist) - set(aShell) )
	cmds.setToolTo(currentTool)
	cmds.select(clear=True)
	#shells = [ [faces in uv shell 1], [faces in shell 2], [etc] ]
	bounds=[]
	for faces in shells:
		uv=cmds.polyEditUV( cmds.polyListComponentConversion( faces, ff=True, tuv=True), q=True )
		uMin=uv[0]
		uMax=uv[0]
		vMin=uv[1]
		vMax=uv[1]
		for i in range(len(uv)/2):
			if uv[i*2]<uMin: uMin=uv[i*2]
			if uv[i*2]>uMax: uMax=uv[i*2]
			if uv[i*2+1]<vMin: vMin=uv[i*2+1]
			if uv[i*2+1]>vMax: vMax=uv[i*2+1]
		bounds.append( [[uMin,uMax],[ vMin,vMax]] )
	overlappers=[]
	for a in range(len(shells)):
		for b in range(a):
			aL=bounds[a][0][0] 
			aR=bounds[a][0][1] 
			aT=bounds[a][1][1] 
			aB=bounds[a][1][0] 

			bL=bounds[b][0][0] 
			bR=bounds[b][0][1] 
			bT=bounds[b][1][1] 
			bB=bounds[b][1][0] 
			
			overlaps=True
			if aT<bB: #A entirely below B
				overlaps=False
			if aB>bT: #A entirely above B			
				overlaps=False
			if aR<bL: #A entirely right of B
				overlaps=False
			if aL>bR: #A entirely left of B
				overlaps=False
			if overlaps:
				overlappers.extend(shells[a])
				overlappers.extend(shells[b])
				
	if overlappers:
		cmds.select(overlappers, r=True)

Thanks for the example. I do need to detect overlaps at the triangle level.
I ended up dividing UV space into a grid where the size of each cell is the average size of a triangle in UV space. I then put UVs into each tile they cross over.
Then i go through each tile and compare all the triangles against all the other triangles in the tile and do a “is this UV inside the UVs of another triangle” test, and perform a Line Intersection test.

This tells me if the UVs for 1 triangle overlap the UVs of another triangle. Its really slow (written in python) for large objects and only works on Triangulated Meshes.
To speed up the process I may subdividing tiles into sub-tiles if there are a large number of small triangles inside a single tile, or just kick the script over to programming to get it turned into a compiled plugin.