I am new to Python, and I feel like I am missing something basic. Forgive me if that is true, but please point me toward something that explains the concept because I have been trying to work around this for a while and I am out of ideas.
I have some surfaces and I want to use them to split each other. I am using the SplitBreps method. It seems to work, generally. The code below splits a brep: segSurfs contains two surfaces. I ignore the first and keep the second as my remainder.
Inside the for loop, I want the first element of remainder to be saved to TTops and save the second as my remainder for the next loop.
But when I attempt this, it will not let me get at the elements inside segSurfs. I have tried the for loop below- for j in segSurfs- and I have tried segSurfs[0], segSurfs[1]. These work fine outside the ‘for i in range(TFaces.Count):’ loop, but not inside it. I am, however, able to print the ObjectType of segSurfs[0] from within the loop.
That’s the problem in a nutshell- the split happens and I can access it if I do it once. As soon as I set it inside a for loop, I cannot.
I get a runtime error saying segSurfs is not subscriptable or that it is “iteration over non-sequence type None Type”
segSurfs = []
TBreps = []
TVBreps = rs.coercebrep(TVSurf[0])
TTops =[]
tTop = []
TBreps.Add(rs.coercebrep(TFaces[0]))
segSurfs = rs.SplitBrep(TVBreps,TBreps[0],False)
for i in segSurfs:
if i == 0:
continue
remainder = i
for i in range(TFaces.Count):
if i == 0: #skip the first iteration
continue
TBreps.Add(rs.coercebrep(TFaces[i]))
segSurfs = rs.SplitBrep(remainder,TBreps[i],False)
tops.Add(rs.coerceguid(segSurfs))
for j in segSurfs:
if j == 0:
TTops.Add(j)
remainder = j
So the file isn’t mine to share in public. I extracted the bit I am having difficulty with, but in doing so, a new problem arose. Maybe this was the issue all along.
While still part of the larger file, the first instance of SplitBrep worked. Now it does not because one of the arguments I pass to it won’t convert to a Brep.
If it succeeds, split brep returns a list of guids representing the objects. i cannot be equal to 0. You can slice your list for surf in segSurfs[1:]: if you want to skip the first one.
Great suggestion, or if you want to stick to the for, instead of for each loop that @Dancergraham proposed, you can simply start your range() at 1, instead of 0:
Sorry I thought I had internalised the data. It is here now. I have extended it a little because it seems that my issues relate to feeding BrepSplit the wrong type.
I feel like this should be easier- I shouldn’t have to coerce everything the way I am. In the enclosed example, I start with a list of points, create an interpolated spline, then loft to create a surface. But in the next step I have to coerce the surface to be a surface. I understand having to maybe coerce between Nurbs and Brep, but this makes me think I am missing something really basic about Python.
You’ve set both component inputs to Surface which means that your geometries get input as Rhino.Geometry.Surface types. This won’t work with rhinoscriptsyntax, because it mainly handles GUIDs - unique IDs of geometries in memory - not the actual geometries themselves.
In my opinion, I wouldn’t mix rhinoscriptsyntax and rhinocommon (API) code. Simply stick to either and you probably don’t have to deal with coercing, getting the referenced geometry from a GUID and vis versa.
Generally speaking, for Grasshopper I’d recommend to use rhinocommon!
To me it is not exactly clear what your end goal is here?
However, here’s some example code that splits your base surface with the intersecting, rib-like surfaces.
import Rhino.Geometry as rg
import scriptcontext as sc
MTOL = sc.doc.ModelAbsoluteTolerance # document tolerance
start_pts = [] # intersection curve start points
for i, srf in enumerate(VFaces):
rc, icrvs, ipts = rg.Intersect.Intersection.SurfaceSurface(TopSurf, srf, MTOL)
if not rc:
print "No intersection found between TopSurf and VFaces at index", i
continue
if len(icrvs) == 0:
print "No intersection curve found between TopSurf and VFaces at index", i
continue
for crv in icrvs:
start_pts.append(crv.PointAtStart)
segments = [] # surface segments
if len(start_pts) > 0:
# Get the surface edge from the intersection curve start points
edge = TopSurf.InterpolatedCurveOnSurface(start_pts, MTOL)
# Split the base surface into segments
tmp_srf = TopSurf # temporary surface that is "recursively" split
for i in range(len(start_pts)):
rc, u, v = tmp_srf.ClosestPoint(start_pts[i])
if not rc:
continue
# Split the temporary surface into two segments
split_srfs = tmp_srf.Split(1, v) # horizontal split in v-direction
if len(split_srfs) == 0:
print "Failed to split TopSurf horizontally with VFace at index", i
continue
south_seg, north_seg = split_srfs
segments.append(south_seg)
tmp_srf = north_seg # update the temporary surface
segments.append(tmp_srf)
# Outputs
a = segments
Thank you so much. I finally got some time to study your work this evening. I have learned a lot from this, and I really appreciate the amount of effort you put in to help me. My big takeaway was about not using rhinoscriptsyntax with RhinoCommon.
But beyond that, I found a lot of great things in the code you wrote. By following the bread crumbs, I could see that I was relying too much on the info in the RhinoCommon API. Sometimes, the help in the Python editor window in GH offers a different, occasionally clearer, explanation.
Your solution was exactly what I was trying to get at. I am still at the stage where I am trying to use the claw of a hammer to turn a screw because I haven’t yet gotten to the chapter on screwdrivers, but bit by bit…
I do have two questions, if it’s okay to impose. I recognize that you have gone above and beyond with this already. But in your code, you got the surface edge, but didn’t appear to do anything with it. Was this an approach that turned out to be a dead end? Or is there a reason it stayed in the code?
# Get the surface edge from the intersection curve start points
edge = TopSurf.InterpolatedCurveOnSurface(start_pts, MTOL)
And the second question: where does the Swatch component come from? That’s one I really need badly.
Thanks again for your patience and generosity,
Graham
Exactly, I had tried something that turned out not to be necessary, but I left it in to show you how you could get a surface edge without converting to a brep first. I guess I should have commented it out though!
Color Swatch is a vanilla Grasshopper component at least in Rhino 6. It can be found in the Params tab under Inputs.