I am trying to write script which split surface and select surface which has biggest area from splitted surfaces.
Script is following.
But I get error message “‘NoneType’ object is not subscriptable”
Could anyone give me some advice why I am getting this message and how to solve the problem?
splitted=rs.SplitBrep(surface,Obj,False)
base=splitted[0]
baseArea=rs.SurfaceArea(base)[0]
for sur in splitted:
area=rs.SurfaceArea(sur)[0]
if area < baseArea:
rs.DeleteObject(sur)
else:
rs.DeleteObject(base)
baseArea=area
rs.SplitBrep() wants another Brep (surface or polysurface) as a cutter, not a curve.
If you want to split a Brep with a curve, you’ll either need to script rs.Command("Split") or dive into RhinoCommon and use Rhino.Geometry.BrepFace.SplitBrep([curves],tolerance). Otherwise, you could turn your curve into a surface (by extruding it or something) and use the surface as the cutter in rs.SplitBrep().
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino
surface_id = rs.GetObject('select surface',8)
cutter_ids = rs.GetObjects('select curves',4)
tol=sc.doc.ModelAbsoluteTolerance
#get the Rhinocommon Brep geometry from the surface object ID
brep=rs.coercebrep(surface_id)
#get all the Rhinocommon curve geometries with a list comprehension
cut_crvs=[rs.coercecurve(cutter_id) for cutter_id in cutter_ids]
#as it is a single surface, you can get the brep's face list and use index 0
# - the brep only has one face...
face=brep.Faces[0]
split_brep=face.Split(cut_crvs,tol)
#if something happened, split_brep will be a joined polysurface
#To have separate surfaces, you need to 'explode' the brep by duplicating all faces
for split_face in split_brep.Faces:
new_brep=split_face.DuplicateFace(True)
#add the duplicate face (brep) to the document
sc.doc.Objects.AddBrep(new_brep)
#redraw the scene
sc.doc.Views.Redraw()
Thank you for this example… I will explore it and I hope understand a part of the gate between rhinoscriptsyntax and rhinocomon…
I don’t know how many methods there is in rhino comon, how can you remember all, do you search every time in the documentation?
There are literally thousands. A number of the most common I know because I use them frequently, the others I search for. The RhinoCommon API documentation is sparser and different than the rhinoscriptsyntax, it is aimed at programmers with a certain experience, it also takes some time to know how to read and understand it.
If I think there is a method that might exist, for example for a brep, I start by opening the Rhino.Geometry.Brep class documentations and start looking for a property or method. If you have an idea of the name or part of it, you can also use the search box, but I find that it doesn’t always work that well, it doesn’t find a lot of partial matches.
Correct. RhinoCommon created geometry is virtual until you specifically add it to the document. Scriptcontext is the bridge between RhinoCommon and the active document that allows you to do this.
It doesn’t. To delete the original, you need to do that in another line. You have the object ID because the original was gotten from the document, so you can simply use rs.DeleteObject(obj_id), or, the RhinoCommon equivalent would be sc.doc.Objects.Delete(obj_id,True) - which calls this method:
The problem is again that to choose the object, instead of using one of the standard rhinoscriptsyntax methods that always return a GUID, the user interaction is done with RhinoCommon GetObject(). The various RhinoCommon methods GetObject() do not return an object ID directly, rather they return an ‘object reference’ (hence the name …obj_ref). An object reference has properties and methods (like all other RhinoCommon classes), so the object ID can be gotten from the object reference via the property ObjRef.ObjectId; plus the actual geometry extracted via one of the ObjRef methods such as ObjRef.Curve, or more generically ObjRef.Geometry.
Not sure that’s necessary in this case as he has a polycurve. BrepFace.Split() wants a list of curves is all, not a single curve, so it should be enough to do the following (I think):
Yeah, I was afraid you would run into that - I tested it here and the simple making of a list worked on my example but I guess yours is different. Why this happens is a bit difficult to explain, but I’ll try with my limited knowledge…
The problem is what we call ‘overloads’ on certain RhinoCommon functions. Overloaded functions are designed in such a way as to be able to take multiple types of inputs, and they rely on being able to easily distinguish between the different possible inputs to execute the function correctly. If the functions are written well, this does not cause any problems and adds some flexibility. However, in this case, the functions are badly conceived (IMO), and they get confused - so you get the error message that it doesn’t know how to distinguish between a list of curves and a list of breps. As an aside I think this is a bad way to do things, IMO if this kind of confusion is possible, the functions should be separated into something like BrepFace.SplitWithCurve() and BrepFace.SplitWithBrep() etc… so that there is no more confusion possible.
The solution then is as @Mahdiyar posted above, you specifically need to define your list as a list of curves before sending it to the BrepFace.Split method, so that it knows that these are indeed curves. It’s painful, but that is the current state of affairs.
Edit:
There are several ways to do this, the one posted above, but also something like the following:
from System.Collections.Generic import IEnumerable
#...
splits=brep.Split.Overloads[IEnumerable[Rhino.Geometry.Curve],System.Double]([crv], tol)
Again, I find this positively painful, it would be nice if this kind of problem could be avoided by dis-overloading certain problematic methods.
Edit 2:
I maybe should add that this is perhaps only a problem with python as it is a weakly typed language - other languages may be able to infer the type of objects in the list because the list is created/efined as a list of curves for example… Maybe I didn’t get that right though…
thank you so much for your time, but i search, and i don’t understand all this part… i think this philosophy is too complicate for me now, i hope i will understand that one day…
i’ll continu to use rs.command () to split what i need…