Issue with IEnumerable(GeometryBase)

Been trying to use the CreatePatch method, but got stuck on its first parameter: IEnumerable(GeometryBase).

Seems like @stevebaer already gave an explanation on this issue in here.
Still I am not getting it.
Tried the following code:

from System.Collections.Generic import IEnumerable
from Rhino.Geometry import Point
import rhinoscriptsyntax as rs
import Rhino
import System

pt_ids = rs.GetObjects()
pts = [rs.coerce3dpoint(pt_id) for pt_id in pt_ids]
pointL = [Rhino.Geometry.Point(pt) for pt in pts]

IEGB = IEnumerable[Point](pointL)

got the following error message (one the last line of the upper code):

Cannot create instances of IEnumerable[Point] because it is abstract

I thought that maybe a “conversion” of Point3d needs to be done, as Point class has been derived from GeometryBase. Is this causing the problem?

Your last line of code tries to create a new instance of IEnumberable, which is abstract and will fail. You would need to provide some specific Array or List class instead.

But pointL is an array. It should already implement IEnumerable and be accessible through the Interface.

Thank you for the reply Hannes.
I already tried using just pointL as CreatePatch’s first parameter, but got an error message:

expected IEnumerable[GeometryBase], got list

This is a problem that is inherent to the use of a dynamically typed language like Python on a framework that is statically typed, like RhinoCommon.

You create a Python list here

pointL = [Rhino.Geometry.Point(pt) for pt in pts]

But you need a .NET List{Point} (which implements IEnumerable{Point})
But you need a .NET List{GeometryBase} (which implements IEnumerable{GeometryBase})

Seems odd though, if you look at the code for AddNetworkSrf() - implemented in rhinoscriptsyntax - the function it calls is CreateNetworkSurface, which also uses IEnumerable, and it seems to be able to work just by passing a simple list… So what’s different about the two?

–Mitch

Hmm… odd indeed. Maybe because GeometryBase is a superclass of Point that it does automatically create a List<Point> instead of a List<GeometryBase>?

The reason it works with AddNetworkSrf is that it wants a List<Curve> and it gets a (Python) list of Curve objects.

This is one (of many) reasons that I don’t like Python, by the way.

Thank you Menno.

That is a different issue. The problem brought up there is that were were multiple overloads to the same function in RhinoCommon and python needed help choosing which specific overload to use.

This works for me

import rhinoscriptsyntax as rs
import Rhino
import scriptcontext

surface = rs.GetObject("select surface", rs.filter.surface)
points = rs.GetPoints(True)

surface = rs.coercesurface(surface)
points = [Rhino.Geometry.Point(pt) for pt in points]

tol = scriptcontext.doc.ModelAbsoluteTolerance
patch = Rhino.Geometry.Brep.CreatePatch(points, surface, tol)
print patch

Thank you Steve.
Sorry if I misunderstood your reply there.
An Overload CreatePatch() list shows three methods. There stands that all of them require IEnumerable(GeometryBase) as their first parameter. But somehow the first and the second one accept regular python lists too. Only the third one requires a .NET list, which I did after Menno’s advice.
The only thing that confuses me now is this inconsistency - when IEnumerable required: why is it sometimes ok to only pass a regular python list, while some other time you need to pass a .NET one?
I think Mitch was talking about that too.

There really isn’t any inconsistency with respect to IEnumerable in these functions. I suspect python was actually getting confused with the bool array and was giving you a somewhat bogus error message because it couldn’t figure out what you were intending. The following works for me

import rhinoscriptsyntax as rs
import Rhino
import scriptcontext
import System

surface = rs.GetObject("select surface", rs.filter.surface)
points = rs.GetPoints(True)

surface = rs.coercesurface(surface)
points = [Rhino.Geometry.Point(pt) for pt in points]

b = System.Array.CreateInstance(bool, 4)
for i in range(4): b[i] = True

tol = scriptcontext.doc.ModelAbsoluteTolerance
patch = Rhino.Geometry.Brep.CreatePatch(points, surface, 5, 8, True, False, 3, 10, 0, b, tol)
scriptcontext.doc.Objects.Add(patch)
scriptcontext.doc.Views.Redraw()

Did not know that.
Thank you.

I’m still having the exact same problem djordje points out with the long form of CreatePatch requiring an IEnumerable, but I don’t see the code listed here to fix it specifically for using curves. The command takes a wide variety of geometry as input so I can’t use a little one line loop to force everything in to a points container ( points = [Rhino.Geometry.Point(pt) for pt in points] ). Is there another Rhinocommon container that will hold generic geometry? I tried various things and they wouldn’t work at all.

menno says “You create a Python list here” but don’t I already have a Python list given that I’m just inputting curves into it from Grasshopper?

And what on Earth does “But you need a .NET List{GeometryBase} (which implements IEnumerable{GeometryBase})” mean in terms of what buttons do I push to make it work?

Posted here as a question:

Instead of using a Python list, use a .NET generic list.

from System.Collections.Generic import List

geomBaseList = List[GeometryBase]()
# add stuff to list (curves, points)

I’m not at my PC right now so this is untested code - it should work I think.