Problem Calling Overloaded Methods from Python

Hi there, I have been programming a script where I want to retrieve the Point3d from the NurbsSurfaceControlpoints.
I got a NurbsSurfacePointList and I want to call the GetPoint() method which is Overloaded NurbsSurfacePointList

I know there is a solution for calling RHinocommon overloaded methods with the following error: “Message: Multiple targets could match” by using the Overloads Method as explained here: Calling Overloaded Methods from Python

But whenever I use the Overloads method on the .Getpoint() method as seen here:

srfControlPoints.GetPoint.Overloads[System.Int32, System.Int32, rg.Point3d](u, v)#Get point3d from control points

I get this error message:

No match found for the method signature GetPoint[Int32, Int32, Point3d]. Expected [Int32, Int32, Point4d&], [Int32, Int32, Point3d&]

Now i ask myself what this expected Type “Point3d&” is (It is not Rhino.Geometry.Point3d)

I have been trying to solve this, but I could not figure it out. Maybe I am overseeing something.
Any help would be helpful! :slight_smile:
_dromaius

Here is a snipped of the code to recreate the error:

import Rhino, System
import Rhino.Geometry as rg
import scriptcontext as sc
import rhinoscriptsyntax as rs

def Main():
    surfaceId = rs.GetSurfaceObject("Select surface")
    if not surfaceId:
        sc.errorhandler()
    
    srfGeo = sc.doc.Objects.Find(surfaceId[0]).Geometry
    if not srfGeo:
        sc.errorhandler()
        
    if srfGeo.IsSurface:
        srfGeo = srfGeo.Surfaces[0]
    else:
        print ("User selected more then one surface")
        return None
    
    nurbsSurfacePoints = srfGeo.Points #Gets the NurbsSurfaceControlPoints
    if not nurbsSurfacePoints:
        print ("ERROR: Could not retrive NurbsSurfaceControlPoints")
        return None

    ControlPoints(nurbsSurfacePoints)

def ControlPoints(srfControlPoints):
    #Get the u and v point from the surface
    countU = srfControlPoints.CountU
    countV = srfControlPoints.CountV

    for u in range(countU):
        for v in range(countV):
            srfControlPoints.GetPoint.Overloads[System.Int32, System.Int32, rg.Point3d](u, v)#Get point3d from control points

if __name__ == "__main__":
    Main()

edit: spelling

Hi @Dromaius,

You can always do something like this:

import Rhino

def test_get_surface_cvs():
    filter = Rhino.DocObjects.ObjectType.Surface
    rc, objref = Rhino.Input.RhinoGet.GetOneObject("Select surface", False, filter)
    if not objref or rc != Rhino.Commands.Result.Success:
        return
        
    srf = objref.Surface()
    if not srf:
        return
        
    nurb = srf.ToNurbsSurface()
    if nurb:
        for v in range(0, nurb.Points.CountV):
            for u in range(0, nurb.Points.CountU):
                cv = nurb.Points.GetControlPoint(u, v)
                print('CV({0},{1}) = {2}'.format(u, v, cv.Location))

if __name__ == "__main__":
    test_get_surface_cvs()

– Dale

1 Like

Thank you, this is helpful

I still wonder though what the problem with the Overloads method was.

@Dromaius The correct way to index into Overloads with a reference type (the out parameters, postfixed by & in the overloads list) is with System.Type.MakeByRefType. And to actually call the method you will need to create a clr.StrongBox holding the point value:

def ControlPoints(srfControlPoints):
    # Get the u and v point from the surface
    countU = srfControlPoints.CountU
    countV = srfControlPoints.CountV
    
    cvs = [
        [clr.Reference[rg.Point3d]() for j in range(countV)]
        for i in range(countU)
    ]

    for u in range(countU):
        for v in range(countV):
            srfControlPoints.GetPoint.Overloads[
                System.Int32, System.Int32, System.Type.MakeByRefType(rg.Point3d)
            ](u, v, cvs[u][v])  # Get point3d from control points
            
    return cvs

See this TODO item in IronPython documentation for System.Type.MakeByRefType. The clr.Reference (alias for clr.StrongBox) is a bit further down in that documentation.

Note that you don’t actually need to index into the Overloads array if you are already using the StrongBox: srfControlPoints.GetPoint(u, v, cvs[u][v]) with cvs[u][v] an instance of clr.StrongBox[rg.Point3d] will already select the correct method.

6 Likes