[Maya API] Python function for finding nearest vertex : return incorect index

Hello !

I’m working on a little python plugin function to improve some performances in one of my tools (moving a mel function into an API function basically). Unfortunately I’m stuck on something and I really don’t see why I get an incorrect result.

So I’m sending to my command the currently selected vertex (its index) and then compare with all the vertices in the related mesh which is the nearest vertex from this one. The result is totally incorrect, the vertex I get is really not close. On a 12K mesh (subdivided sphere for example) I can get a vertex that can be on the opposite side of the mesh.

I’m far from being fluent with the Maya API in Python unfortunately. Any help is appreciated. :slight_smile:

Here is the main python code :


        # arguments
        argData = om.MArgParser(self.syntax(), args)
        index = argData.flagArgumentInt(kFroIndexF, 0) #currently selected vertex (index)
        range = argData.flagArgumentDouble(kFroRangeF, 0) #max distance to find a vertex
        
        # get the active selection
        sel = om.MSelectionList()
        om.MGlobal.getActiveSelectionList( sel )
        list = om.MItSelectionList(sel, om.MFn.kMesh)
        
        # get mesh
        mesh = None
        dagPath = om.MDagPath()
        list.getDagPath( dagPath )
        mesh = om.MFnMesh( dagPath )
        
        #define variables to find the vertex
        nb = mesh.numVertices()
        point = om.MPoint() #target point
        
        print ("
There is " + str( nb ) + " vertices in the mesh")
        
        foundVtx = 0
        closestVert = 0
        minLength = None
        pos = om.MPoint()
        
        # search for the nearest vertex
        count = 0
        while count < nb :
            # ignore vertex already selected by user
            if count != index :
                #get point by its index
                mesh.getPoint(count, point, om.MSpace.kWorld)
                dist = pos.distanceTo( point )
                
                #if the vtx is the closest, save it (only if we are under the user range)
                if dist <= range :
                    if minLength is None or dist < minLength:
                        foundVtx = 1
                        minLength = dist
                        closestVert = count
                    
            count += 1
        
        if count :
            print ( "Vertex found is " + str( closestVert ) + "
" )
        
        #send the closest vertex to the user
        resultArray = om.MDoubleArray()
        resultArray.append( foundVtx )
        resultArray.append( closestVert )
        resultArray.append( point.x )
        resultArray.append( point.y )
        resultArray.append( point.z )
        
        self.clearResult()
        self.setResult( resultArray )

Here is how I call it (I assume that the user has selected a vertex on a mesh) :


global proc froRetopoTargetWeld()
{
	string $highlighted[] = `ls -hl`;
	string $sel[] = `ls -sl`;
    float $range = `floatField -q -v froRetopo_field_snapweld`;

    //isolate vertex index
    string $buffer[];
    tokenize $sel[0] "[" $buffer;
    tokenize $buffer[1] "]" $buffer;
    int $index = int($buffer[0]);
        
    //select mesh to compute vertex list in the python plugin
    select -r $highlighted[0];

    //call the python command and get the nearest vertex index
    float $result[5] = `froVertexFinder -fid $index -frg $range`;

    //found a vertex ?
    if($result[0])
    {
        //vertex name
        string $target = ($highlighted[0] + ".vtx[" + int($result[1]) + "]");

        select -r $sel[0];
        move -ws $result[2] $result[3] $result[4] $sel[0];
        
        select -add $target;
        polyMergeVertex  -d 0.2 -ch 1;
        
        select -r $highlighted[0];
    }
    else
        select -r $sel[0];
}

it looks like you never set ‘pos’ to any value, is that intentional? Won’t it initialize to 0,0,0? If so you’ll be testing against distance to origin

[QUOTE=Theodox;23695]it looks like you never set ‘pos’ to any value, is that intentional? Won’t it initialize to 0,0,0? If so you’ll be testing against distance to origin[/QUOTE]
Indeed ! I missed that part.

Your answer made me doing some other debug tests. Once I fixed what you mentionned, I found that it was not the python part which was the problem. It’s the move command that move incorrectly my vertex. The getPoint() function return me a position normally in world space. However using the mel command “move -ws” or even “move -os” still produce the same error. My current workaround is to query again the vertex position with the “pointPosition -world” mel command. However I would have preferred to directly use the information found during the python process, for performance reasons…

So any idea what I could do wrong with the move command ?

Are you getting the return position in world units too? Have you tried making a locator or something to check the results of the command?

[QUOTE=Theodox;23709]Are you getting the return position in world units too? Have you tried making a locator or something to check the results of the command?[/QUOTE]

Well, in theory it should since I do : getPoint(count, point, om.MSpace.kWorld)
However, when I comparing the python result whit the mel command (I print the coordinates), they are different. I have no idea in which space I get those coordinates then. I read here and there that some people were having problem with the getPoints method because they weren’t using a dagPath (which forced them to query in object space and do matrix transformation to get world space coordinates). So it’s not my case here.

Check and see if the results are in CM (I think its one of those aspects of Maya that ignore world unit settings).

I’m working in centimeters, and the units I get are quite close, but still differents.
For example the mel command returns : -9.8, 5.4, 3.2.
The python command returns : 3.4, -9.6, -7.2.

So not exactly very far, but still very wrong.

Try it on a unit cube centered at origin so you can control for scaling, rotation, etc. Is there a consistent ratio?