Hi,
How can I use SelBoundary to select from a specific layer?
rs.UnselectAllObjects()
rs.Command(“_SelBoundary _SelectionMode=Crossing selid {} _Enter”.format(str(rftp)), False)
n_items = rs.SelectedObjects()
Thanks,
Zoltan
Hi,
How can I use SelBoundary to select from a specific layer?
rs.UnselectAllObjects()
rs.Command(“_SelBoundary _SelectionMode=Crossing selid {} _Enter”.format(str(rftp)), False)
n_items = rs.SelectedObjects()
Thanks,
Zoltan
Hi Again,
Still not getting it right - I cannot seem to find the python command to restrict SelBoundary to select from a ‘named’ layer.
Before the above 3 lines of code, I buffer everything on another layer:
blds = rs.ObjectsByLayer(‘Building’, False)
These are all closed curves and and I give each of then a unique name.
Then: del blds
I then buffer another layer of closed curves.
Then stepping through each curve in the 2nd buffer I want to select any closed curves from the 1st (blds) buffer that overlaps this curve and attach the blds ‘name’ to this “selecting” curve.
But each time the SelBoundary only select from its own layer and not from the Blds layer.
I cannot find a Pythonic way to activate a specific layer so that SelBoundary only selects from that layer.
Hope this clarifies as I really need a direction to try.
Thanks and regards,
Zoltan
There isn’t really one as SelBoundary is not layer-aware. The way would be to use (rs.Command) SelBoundary to get everything and then loop through all the selected objects and deselect any which are not on the layer(s) concerned.
Hi Helvetosaur
I do exactly that, but it onlt selects from its own rooftops layer, and not from the buildings layer.
Here’s the loop:
rftps = rs.ObjectsByLayer(‘Roofprint’, False)
rs.UnselectAllObjects()
n_rftps = len(rftps)
n_rftp = 0
for rftp in rftps:
n_rftp += 1
oldrfid = rs.GetUserText(rftp, “#0", False)
if oldrfid == None:
oldrfid = ‘z’ + '{0:06d}'.format(n_rftp)
rs.UnselectAllObjects()
rs.Command(”_SelBoundary _SelectionMode=Crossing selid {} _Enter".format(str(rftp)), False)
items = rs.SelectedObjects()
rs.UnselectAllObjects()
n_items = len(items)
for item in items:
lyr = rs.ObjectLayer(item)
if lyr == ‘RhinoCapture::Building’:
** print('Found: ’ + lyr)**
continue
It never selects from the Building layer, but their are hundres that it should…
So I am wondering what is restricting SelBoundary from accessing that layer
To properly format code in your posts, do the following:
Below is a prototype of some code. Unfortunately SelBoundary isn’t really set up well for scripting, so you will see the selection of everything before the layer filter is applied, but then after you choose the layers to keep, the rest will be unselected.
import rhinoscriptsyntax as rs
def SelBoundaryWLayers():
rs.UnselectAllObjects()
rs.Command("SelBoundary")
if rs.LastCommandResult()==0:
bound_sel=rs.SelectedObjects()
if not bound_sel: return
layers=rs.GetLayers("Select layers for boundary selection")
if not layers:
rs.UnselectAllObjects()
return
rs.EnableRedraw(False)
for obj_id in bound_sel:
if rs.ObjectLayer(obj_id) not in layers:
rs.UnselectObject(obj_id)
SelBoundaryWLayers()
Hi Helvetosaur
Apologies for my delay in responding - been travelling without much ‘real world’ connection time.
Massive thanks for the ‘3-ticks’ headsup
and of course for the info regarding my problem.
I have been trying to avoid having to loop through all objects on a layer in my script, due to perceived inefficiencies.
I come from a GIS scripting/data background, where my first methodolgy is to use the “host” SW to do the selection sets, and then also use the “host” SW to do the comparison between the selected subsets - very efficient in GIS SW, so that is why I have been trying find simillar methods in Rhinoceros.
Seems I am out of luck, but at least I can now get on with solving my issue.
I really thank you for your efforts and clarifications.
Hopefully one day I can return the effort.
Kind regards,
Zoltan
Not entirely.
The main problem with scripting rs.Command("SelBoundary")
is that the Rhino command is not really set up all that well. For some reason, it does not allow you to preselect the boundary curve. I remember arguing about this a long time ago, and there was an obscure reason why it’s that way, but I can’t remember anymore.
If it was possible to preselect the boundary curve, one could at least cut the redraw while SelBoundary selected everything and then one iterated through the layer list and threw out any objects not on the desired layers. So you would only see the result, not everything possible being selected first and then unwanted objects deselected. I don’t think this looping procedure is all that computationally expensive by the way, unless you are dealing with many thousands of objects.
The other way to approach this is simply to create your own SelBoundary function and not rely on Rhino’s native command. The basics are not all that hard, but the complicated part is that SelBoundary has four modes - Window, Crossing, Invert Window and Invert Crossing. If you only want to select objects within a closed curve (i.e. Window) it becomes somewhat simpler.
Basically one gets the bounding box of all the objects on the desired layers and then translates/extrudes the closed curve so that it covers the depth of the bounding box. Capping this will give you a closed volume that theoretically contains the objects you want. You then intersect all the objects that are on the layers you want with the volume, and first you throw out anything that intersects the volume*. The remaining objects are either entirely inside or entirely outside the volume, and an easy single point inclusion check for each object will tell you if it’s inside or outside.
*The tricky part is if you want to include objects just “touching” the boundary. That requires quite a bit more specialized checking, but is it definitely possible. Another tactic would be to offset the boundary curve a tiny amount (like the file tolerance) before extruding to make sure that objects that touch are included. I am not all that fond of that direction because Offset can be unreliable in some cases.