Seems like an interesting challenge. :)
from maya import cmds
def find_joint(position, epsilon=0.01):
"""Find joint at `position` with precision `epsilon`
Arguments:
position (tuple): XYZ coordinates to look for a joint
epsilon (float, optional): Precision at which to consider it a match
"""
for joint in cmds.ls(type="joint"):
# Find worldspace position of joint, including parenthood
p = cmds.xform(
joint,
translation=True,
worldSpace=True,
query=True,
)
if all(abs(p[axis] - position[axis]) < epsilon for axis in range(3)):
return joint
# No joint was found at this position
return None
# For example..
positions = [
(10.0, 10.0, 10.0),
(50.0, 0.0, 0.0),
(0.0, 10.0, 0.0)
]
# Create joints at these positions..
for p in positions:
joint = cmds.createNode("joint")
cmds.move(p[0], p[1], p[2], joint)
# And then retrieve them again
for p in positions:
joint = find_joint(p)
print("Found: %s @ %s" % (joint, str(p)))
# Test whether it fails when expected
assert not find_joint((999.0, 0, 0)), "There shouldn't have been a joint here!"
The trick being to (1) iterate over all joints, which isn’t free but also not too costly in any scene with < 10,000 joints or so and queries being made < 1 time/sec or so, and (2) compare their position with some “precision”. The latter being important because we’re comparing floating-point numbers, which cannot be trusted to exactly match with a float1 == float2
comparison. If you’re scene is very large, you would increase the size of epsilon
to e.g. 0.1
or even 1.0
if it’s really, really large. If your scene is very small, then the opposite is true. 0.01
should hold up in cases where joints are placed with a minimum of 0.02
cm (default Maya units).
If joints are too close or epsilon is too large, only one of the overlapping joints would be returned, in the order provided by cmd.ls
.
Is there a faster way? Possibly by replacing maya.cmds
with maya.api
, but I don’t think you can escape having to iterate over all joints like this which is where time is likely spent (although do profile it to make sure!), unless you do what Vincent suggests and store your joints up-front instead of relying on their worldspace position in the scene.
Hope it helps
--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/a78d9ea8-4a31-46a4-9cc2-bbf9f919ec04o%40googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.