Selecting all verticies above intersection

Hey!
I’m trying to learn using the Maya api through pymel and create a tool that selects all verticies above an intersection point (in this case, all vtx on the sphere that are above the intersecting plane)

I’ve managed to find the intersection point, using closestIntersection, which gets me most of the intersecting vertices whit a few strays here and there, but I can’t seem to get a clean cut along the line nor get only all the vertices above the intersection.

Apreciate any help and guidence :smiley:

I think it’s a good idea to forget about PyMEL, especially when writing tools that you plan to support in future versions of Maya.
Essentially the problem:
If the problem is only for a sphere and a plane, then it is a trivial problem of mathematical geometry.
If the problem is for a plane and arbitrary geometry, then:
Imagine that your plane is perpendicular to the Y axis.
What transformation should be applied to place the plane at the origin, perpendicular to the Y axis?
We add the inversedd transform matrix of the plane to the current transformation of the sphere.
In this case, we simply iterate through the positions of the vertices of the target geometry, leaving only vertices with Y position values greater than zero.

Here is a demo scene that visually demonstrates this idea.

I used maya.api.OpenMaya only to find the inverse matrix.
But you can write this function yourself.

If the transforms for the objects are frozen, then there is a little more work:
You will need to calculate the position of the plane (using the equation of the plane and using the positions of any three vertices of the current plane).
And for the target object, calculate the position of the center of the bounding box.

If you need a fast interactive tool, then use the Maya API.
At a minimum, you will need:
MFnMesh
MFnTransform
MTransformationMatrix
MMatrix
MSelectionList

import maya.cmds as cmds
import maya.api.OpenMaya as om2
maya_useNewAPI = True

# Preparing a demo scene
cmds.file(new = True, force = True)
cam_name_transform = cmds.createNode('transform', name = 'demo_look', 
                                      skipSelect = True)
cam_name_shape = '{}Shape'.format(cam_name_transform)
cam_node_name = cmds.createNode('camera',
                                     name = cam_name_shape,
                                   parent = cam_name_transform,
                               skipSelect = True)
cmds.modelEditor('modelPanel4', edit = True, camera = cam_node_name)


poly_plane = cmds.polyPlane(w=25, h=25, sx=10, sy=10, ax=(0, 1, 0), cuv=2, ch=False)[0]
poly_sphere = cmds.polySphere(r=10, sx=20, sy=20, ax=(0, 1, 0), cuv=2, ch=False)[0]
cmds.move(25,5,3, poly_sphere, absolute=True, worldSpace=True)
cmds.move(24,7,4, poly_plane, absolute=True, worldSpace=True)
cmds.rotate(37,5,-12, poly_sphere, absolute=True, worldSpace=True, fo=True)
cmds.rotate(16,-13,20, poly_plane, absolute=True, worldSpace=True, fo=True)


for item in cmds.getPanel(type = 'modelPanel'):
    cmds.modelEditor(item, edit = True, da = 'smoothShaded', swf = True, wos = True)
    cmds.viewFit(animate = True, allObjects = True)


# Let's duplicate the polysphere for clarity
dub_geo = cmds.duplicate(poly_sphere, rr = True)[0]

# Get transform matrix from polyplane (in world space)
plane_matrix = cmds.xform(poly_plane, query = True, matrix = True, worldSpace=True)

# Get inverse transform matrix from polyplane with maya.api.OpenMaya
om_plane_matrix = om2.MMatrix(plane_matrix)
plane_matrix_inverse = list(om_plane_matrix.inverse())

# Set transform matrix for polysphere (in world space. But! Relative to current position)
cmds.xform(dub_geo, matrix = plane_matrix_inverse, relative=True, worldSpace=True)
cmds.viewFit(animate = True, allObjects = True)

# Get all vertices position from duplicate sphere (Absolute position in world space!)
vertex_position = cmds.xform('{}.vtx[*]'.format(dub_geo), query = True, absolute=True, worldSpace=True, translation= True)

# Let's put all vertices (with Y-position  > 0) in a lists
top_vertex_original = []
top_vertex_duplicate = []
for i,idx in zip(range(int(len(vertex_position)/3)) ,range(1, len(vertex_position), 3)):
    if vertex_position[idx] > 0.0:
        top_vertex_original.append('{}.vtx[{}]'.format(poly_sphere, i))
        top_vertex_duplicate.append('{}.vtx[{}]'.format(dub_geo, i))

# For clarity, lets select the resulting vertices (on both polyspheres)
cmds.select(top_vertex_original, top_vertex_duplicate)

It goes without saying that in real code you don’t need to create a duplicate geometry.
In the demo scene this is used for clarity only.
Good luck, harmony and positivity!

3 Likes

Apologies for the late reply :'D I’ve only scratched the surface of the API, but I really want to learn more and I felt like this is a good opportunity to do so :slight_smile: (Plus, like you said, this is probably going to be used in multiple versions of Maya)

And you are absolutely amazing! I’d been running around in circles trying to figure this out. Can’t believe I didn’t even think of using the inverse matrix. Modified it and got my script to work like a charm now. Thank you so so much for dropping your knowledge! Exactly what I was looking for :smiley:
Cheers!

1 Like