Expected Ienumerable[curve], got list

hello every body!!!
i search to create a network surface with:
Rhino.Geometry.NurbsSurface.CreateNetworkSurface(edges,2,0,0,0,0)

but it return an error:
expected IEnumerable[Curve], got list
how can i transform a list to an IEnumerable,

i searched but what is the difference between an IEnumerable and list?

Only!

Bonjour et Bonne Année!

See the general solution from the end of this post

Essentially you need a C# List, not a python list

2 Likes

Merci et bonne année aussi!!!
I found this post, but I don’t understand…
I have to create a Curve list?

Ok @Dancergraham and @AndersDeleuran … but now it return me:
expected StrongBox[int], got int

what is a strongbox[int]?
I found this:

but it doesn’t help me…

below the file for example, and the srcipt…
FiletCorner.3dm (87.8 KB)
FiletCorner.py (3.2 KB)

This thread might help shed some light on the strongbox issue:

Hello!!!
It’s strange to have to use c# list to create an rhino common network surface, no?
Or is it because I start in python?

Thanks
Only!

Not really, no! The API/rhinocommon is written in C#, and IronPython - the flavour used in Grasshopper and Rhino - is derived from it too.

Yes. :wink:

Oftentimes, there is a Python-only workaround though, because in most cases many roads lead to Rome.

What is your end goal here?

Thank you @diff-arch!
i’ve got a intersction of 3 filets:


my script cut the extremity of the 3 filets and i need to create the network surface with the 3 breps edges create…
my script find a list of the 3 edges, but the Rhino.Geometry.NurbsSurface.CreateNetworkSurface(edges,2,0,0,0,0) return an error about the type of list,
so i created an Ienumerable but not enought…

def CreateSurface(edges):
    
    ledges=List[Rhino.Geometry.BrepEdge](edges)
    Rhino.Geometry.NurbsSurface.CreateNetworkSurface(ledges,2,0.1,0.1,0.1,1)

but it return:
expected StrongBox[int], got int

so now i try to create a strongbox, but i don’t know how…

I try to import clr, to make a:
ledges=clr.strongbox[int](ledges)

but no it’s not this…
i don’t understand something, and it make me crazy!!!

Doesn’t your fillet produce the missing surface patch automatically?
When I fillet brep edges with Python and rhinocommon it does!

Here’s my sample code:

import Rhino.Geometry as rg
import scriptcontext as sc

MTOL = sc.doc.ModelAbsoluteTolerance  # document tolerance

edge_indices = list(range(Brep.Edges.Count))  # indices of edges to fillet
start_radii = [Radius] * Brep.Edges.Count
end_radii = [Radius] * Brep.Edges.Count

blend_type = rg.BlendType.Fillet  # or: rg.BlendType.Chamfer, rg.BlendType.Blend
rail_type = rg.RailType.RollingBall # or: rg.RailType.DistanceFromEdge, rg.RailType.DistanceBetweenRails

# Outputs
if Radius == 0:
    a = Brep
else:
    a = rg.Brep.CreateFilletEdges(Brep, edge_indices, start_radii, end_radii, blend_type, rail_type, MTOL)

You don’t have to fillet all the edges, but the number of start and end radii, must always match the number of edges to fillet.

fillet_python.gh (5.0 KB)

1 Like

in fact, i have to put fillet on 3dm product, but i do that along 4 or 5 days work… I don’t know how many fillet i have to draw but it’s not on a cube and every radius value is different so i have to put them one by one for a lot of them and draw manualy the connection…

fillet tool on every cad solution doesn’t work, solidworks is the worth, Catia can make a good job, but it’s not faster than rhino… i passed a lot of time on this kind of intersection of 3 filet, if i find the script for 3 filet it can run for four!!!

i’ll try your script, but i’m not sure that it is what i want…
on your script all edges has the same radius value…??? no?

Oh, that’s sounds tedious.

Yes, but it would also be possible to enter the radius values for specific edges manually.
Furthermore, each edge can have different values for the start and end radius!

i don’t know how can explain my problem in english, i just want to know how can i , with a list of Brep.edge, create a network surface with this list…

thank you @diff-arch!!!

Does the code below help? It’s pulled directly from the rs.AddNetworkSrf code…

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino 


def GetBrepEdges(prompt):
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt(prompt)
    go.EnablePreSelect
    go.GeometryFilter=Rhino.DocObjects.ObjectType.EdgeFilter
    go.GetMultiple(1,0)
    if go.CommandResult()!=Rhino.Commands.Result.Success:
        return go.CommandResult()
    objrefs = go.Objects()
    if not objrefs: return
    
    #can have multiple objrefs from same brep object(multiple edges), cull objrefs
    unique_IDs=[]
    unique_objrefs=[]
    objs=[]
    for objref in objrefs:
        if not objref.Object().Id in unique_IDs:
            unique_IDs.append(objref.Object().Id)
            unique_objrefs.append(objref)
            objs.append(objref.Object())
    edge_crvs=[]
    #need to loop here in case multiple base objs are involved
    for obj in objs:
        sub_objs=obj.GetSelectedSubObjects()
        if sub_objs:
            trims=[obj.Geometry.Trims[sub_obj.Index] for sub_obj in sub_objs]
            trim_crvs=[trim.Edge.ToNurbsCurve() for trim in trims]
            edge_crvs.extend(trim_crvs)
    #returns selected EDGE curve *GEOMETRY* (Nurbs curves)
    return edge_crvs


def TestAddNetworkSrfFromBRepEdges():
    tol=sc.doc.ModelAbsoluteTolerance
    atol=sc.doc.ModelAngleToleranceRadians
    curves=GetBrepEdges("Pick Brep edges for network surface")
    pass
    surf, err = Rhino.Geometry.NurbsSurface.CreateNetworkSurface(curves,2,tol,tol,atol)
    if err==0:
        rc = sc.doc.Objects.AddSurface(surf)
        sc.doc.Views.Redraw()
TestAddNetworkSrfFromBRepEdges()

Thank you @Helvetosaur, I tried to take some parts of this script, but it’s more difficult, I’ve got a list of brep edges and you a list of object… I think I’ve to convert my edges to nurbs curve, but in yours you pass by a trim , I don’t understand why… It’s really nebulous for me…

A BrepEdge has a ToNurbsCurve() method:
https://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Geometry_Curve_ToNurbsCurve.htm

A list of Nurbs curves actually. They are converted to Nurbs curves in the script on line 31
image

1 Like

Hey,

I’ve quickly hammered this together in the last 15 minutes, but it seems to work with trimmed and non-trimmed surfaces. The only important thing is that your input surfaces are connected (at vertices), like in your screenshot above.

The curves forming the network surface should be selected automatically. The new network surface patch is output.

import Rhino.Geometry as rg
import scriptcontext as sc


MTOL = sc.doc.ModelAbsoluteTolerance
ATOL =  sc.doc.ModelAngleToleranceRadians


curves = []

for i, brep in enumerate(Breps):
    for j, edge in enumerate(brep.Edges):
        edge_start_pt = edge.StartVertex.Location
        edge_end_pt = edge.EndVertex.Location
    
        connected_start = []
        connected_end = []
    
        for k, other_brep in enumerate(Breps):
            if k == i:
                continue
        
            for l, other_edge in enumerate(other_brep.Edges):
                other_start_pt = other_edge.StartVertex.Location
                other_end_pt = other_edge.EndVertex.Location
            
                if other_start_pt.DistanceTo(edge_start_pt) < MTOL or other_end_pt.DistanceTo(edge_start_pt) < MTOL:
                    connected_start.append((k, l))
                
                if other_start_pt.DistanceTo(edge_end_pt) < MTOL or other_end_pt.DistanceTo(edge_end_pt) < MTOL:
                    connected_end.append((k, l))
    
        if len(connected_start) > 0 and len(connected_end) > 0:
            curves.append(edge.ToNurbsCurve())

continuity = 0 # 0 = loose, 1 = position, 2 = tan, 3 = curvature
surface, rc = rg.NurbsSurface.CreateNetworkSurface(curves, continuity, MTOL, MTOL, ATOL)


# Outputs
a = surface

You can change the surface continuity to something else. I’ve listed the options in a comment!
I hope this works for you, too, no guarantees though! :wink:

fillet_python_v2.gh (15.6 KB)

2 Likes

Yess!!
I had already try the ToNurbsCurve() method, but i didn’t found th right syntax… but it’s Ok now:

import rhinoscriptsyntax as rs
import Rhino
from System.Collections.Generic import List
import scriptcontext as sc
import Rhino.Geometry as rg




def CreateSurface(edges):
    MTOL = sc.doc.ModelAbsoluteTolerance
    ATOL =  sc.doc.ModelAngleToleranceRadians
    curves=[]
    for edge in edges:
        curves.append(edge.ToNurbsCurve())
        
    continuity = 3 # 0 = loose, 1 = position, 2 = tan, 3 = curvature
    surface, err = rg.NurbsSurface.CreateNetworkSurface(curves, continuity, MTOL, MTOL, ATOL)
    if err==0:
        rc = sc.doc.Objects.AddSurface(surface)
        sc.doc.Views.Redraw()

def EdgeFilter(edges,ptcontrol):
    for edge in edges:
        crv=edge.ToNurbsCurve()
        if rs.IsPointOnCurve(crv,ptcontrol):
                return edge
                

def PointInters (borders,breps,i):
    j=0
    a=(j+i)%len(borders)
    b=(j+1+i)%len(borders)
    c=(j+2+i)%len(borders)
    inter1=rs.CurveCurveIntersection(borders[a],borders[b])
    dist=[]
    dist=rs.Distance(inter1[0][1],breps[a][3])
    pt1=inter1[0][1]
    if len(inter1)>1:
        distcontrol=rs.Distance(inter1[1][1], breps[a][3])
        if distcontrol<dist: pt1=inter1[1][1]
    inter1=rs.CurveCurveIntersection(borders[a],borders[c])
    dist=[]
    dist=rs.Distance(inter1[0][1],breps[a][3])
    pt2=inter1[0][1]
    if len(inter1)>1:
        distcontrol=rs.Distance(inter1[1][1], breps[a][3])
        if distcontrol<dist: pt2=inter1[1][1]
    return (pt1,pt2)


def FiletCorner():
    #selection des surfaces a limiter
    breps=[]
    breps.append(rs.GetSurfaceObject('select surf1'))
    if not breps[0]:
        return
    breps.append(rs.GetSurfaceObject('select surf2'))
    if not breps[1]:
        return
    breps.append(rs.GetSurfaceObject('select surf3'))
    if not breps[2]:
        return
    rs.EnableRedraw(False)
    #dupliquer les borders
    borders=[]
    borders.append(rs.DuplicateSurfaceBorder(breps[0][0],1))
    borders.append(rs.DuplicateSurfaceBorder(breps[1][0],1))
    borders.append(rs.DuplicateSurfaceBorder(breps[2][0],1))

    network=[]
    edges=[]

    for i in range(len(breps)):
        
        pts=PointInters(borders,breps,i)
        line=rs.AddLine(pts[0],pts[1])
        midpt=rs.CurveMidPoint(line, segment_index=-1)
        clpt=rs.PointClosestObject(midpt,breps[i])
        direction=rs.VectorCreate(clpt[1],midpt)
        rs.SelectObject(line)
        rs.SelectObject(breps[i][0])
        proj=rs.ProjectCurveToSurface(line, breps[i], direction)
        network.append(proj)
        rs.UnselectAllObjects()
        plane=rs.PlaneFromPoints(rs.CurveStartPoint(line),rs.CurveEndPoint(line),rs.CurveMidPoint(proj))
        cutter=rs.AddPlaneSurface(plane,rs.CurveLength(line),rs.CurveLength(line))
        parts=rs.SplitBrep(breps[i][0],cutter,True)
        rs.DeleteObject(cutter)
        for part in parts:
            if not rs.IsPointOnSurface(part,breps[i][3]):
                rs.DeleteObject(part)
            else:
                surf=rs.coercebrep(part)
        pass
        edges.append(EdgeFilter(surf.Edges,clpt[1]))
        rs.DeleteObject(proj)
        rs.DeleteObject(line)
    cap=CreateSurface(edges)
    rs.DeleteObjects(borders)
    rs.EnableRedraw(True)

if( __name__ == "__main__" ):
    FiletCorner()

Anybody have tipes for creating an IEnumerable Mesh ? It’s taken me maybe 15 minutes of googling just to try and get one method working, Curve.ProjectToMesh with python, I think there should be a rethink (at least in terms of documentation) to make this clearer.

Alternatively, if someone could point me in the direction of how to specify an overload (such as the much simpler Curve.ProjectToMesh Method (Curve, Mesh, Vector3d, Double)) then that would be a real timesaver!

Something like this should do it:

import Rhino as rc
from System.Collections.Generic import List

meshList = List[rc.Geometry.Mesh](yourPythonMeshList)
1 Like

Thank you! I cannot emphasise how much this is my least favourite bit about scripting in Python.

How would you go about specifying the overloads, in case I wanted to try that as an option in future too?

Do you feel this aspect could be documented better? (with beginners in mind or those that are only familiar with python, syntactically?)