I would like to delete some layers and the objects on those layers in Rhino from GH. They were previously generated by Human. I know there is a “Delete on Layer” component, but that only deletes objects and doesn’t delete in sublayers.
So what I have are the layer paths to delete in the typical format of “Layer::Sublayer::etc.”
Thanks, yes, Purge is the correct command, but I just gave it a small go and it seems it doesn’t work as I would hope.
Firstly I dont really like using Rhino commands triggered from GH. They usually cause trouble, especially when using in loops. GH just gets stuck a lot, because a Rhino command is stuck somewhere. So I much prefer how for example Human does it, where its not triggering Rhino commands.
But yeah, anyways, I didn’t get it to work anyways. It seems that it doesn’t work with Full layer paths in the format “Layer::Sublayer::Sublayer”
Thank you though.
This is what I am trying (with my limited knowledge of python and rhino script) but its not working right yet:
Oh, actually it totally works. Just didn’t know that Python doesn’t understand “true” and instead expects a 1. And I still had the layer = rs.GetString(“Layer to purge”) in there from the documentation, which I now realise is the prompt for the layer in the Rhino command line, so I just had to get rid of that.
Now its working fine with:
import rhinoscriptsyntax as rs
import scriptcontext
import Rhino
scriptcontext.doc = Rhino.RhinoDoc.ActiveDoc
if x == 1:
if layer: rs.PurgeLayer(layer)
scriptcontext.doc = ghdoc
I have a True only button connected to x (type hint: boolean) and a “layer” input (type hint: str).
You can see that in the explanation it says the layer is deleted even if it contains geometry, but in the layer input it says the layer needs to be empty and thats also the observed behaviour.
Seems like someone just copy/pasted in the documentation and in the code behind it. Here is the documentation for DeleteLayer and you can tell the parameter has the same description:
True, but I think that is what Purge is for, right? To delete geometry you have to specify the exact layer you want to delete the objects from, so that means you have to first find and then pass it all sublayers just to be able to delete the parent layer.
Purge should be able to delete a parent layer with all the sublayers and objects without specifying them. I think someone just copied the deleteLayer function and forgot to change it.
So PurgeLayer layer also still has to first delete everything in the sublayers? From the description, I was under the impression, that it wouldn’t need that. So then whats the difference to DeleteLayer? I was assuming PurgeLayer is like selecting a parent layer in Rhino, pressing Del and then clicking “Yes to All”!?
As far as I understand Purge does not delete geometry. It rather cleans your file from stuff that’s not needed. I’ve been using the command regularly in Rhino to delete empty layers, unused block definitions and unused materials.
I think you are confusing it with the “Purge” command in Rhino. This is a RhinoScript command called “PurgeLayer” and from the description should be able to take a layer and delete it, regardless of sublayers and objects in the sublayers. Probably if you would have a Block on any of the Sublayers it wouldn’t let you do it, but that’s not an issue in my case.
Can one of the devs please confirm what the correct way to delete stuff in RhinoScript is for:
Deleting a layer with all its contents
Deleting a layer only if its empty (I guess “DeleteLayer”)
I’m not sure if this helps at all, but it might clarify things a bit. rs.PurgeLayer simply wraps this method:
def PurgeLayer(layer):
"""Removes an existing layer from the document. The layer will be removed
even if it contains geometry objects. The layer to be removed cannot be the
current layer
empty.
Parameters:
layer (str|guid): the name or id of an existing empty layer
Returns:
bool: True or False indicating success or failure
Example:
import rhinoscriptsyntax as rs
layer = rs.GetString("Layer to purge")
if layer: rs.PurgeLayer(layer)
See Also:
AddLayer
CurrentLayer
DeleteLayer
RenameLayer
"""
layer = __getlayer(layer, True)
rc = scriptcontext.doc.Layers.Purge( layer.LayerIndex, True)
scriptcontext.doc.Views.Redraw()
return rc
While rs.DeleteLayer wraps this one:
def DeleteLayer(layer):
"""Removes an existing layer from the document. The layer to be removed
cannot be the current layer. Unlike the PurgeLayer method, the layer must
be empty, or contain no objects, before it can be removed. Any layers that
are children of the specified layer will also be removed if they are also
empty.
Parameters:
layer (str|guid): the name or id of an existing empty layer
Returns:
bool: True or False indicating success or failure
Example:
import rhinoscriptsyntax as rs
layer = rs.GetString("Layer to remove")
if layer: rs.DeleteLayer(layer)
See Also:
AddLayer
CurrentLayer
PurgeLayer
RenameLayer
"""
layer = __getlayer(layer, True)
return scriptcontext.doc.Layers.Delete( layer.LayerIndex, True)
Clicking the button does nothing for the list of layers or even the Test layer.
If you create an empty layer and even add some sublayers and then pass just the Parent Layer to the phython component it works and deletes the layer and all its sublayers. But as soon as there is an object in any of the sublayers it simply does nothing.
If you duplicate the phython component and replace “PurgeLayer” with “DeleteLayer” the behaviour is identical. Therefore I think in the code behind the PurgeLayer method, someone just copied the DeleteLayer method and forgot to remove the flag about containing geometry.
It’s working right now, but still very slow. It does something on every calculation even when Purge is not true (its connected to a button to only trigger when needed).
Any idea what could cause GH to take so much longer for every calculation even though its not supposed to do anything?
Also then this shows that PurgeLayer doesn’t do what it says in the description, ie. delete any layer including its sublayers and objects if you have to delete all the child layers first and sort of work through it recursively.
It’s probably a combination of using the implied GHPython looping and changing the scriptcontext before checking if Purge is True. Here’s a quick go at fixing those issues:
Hi all,
I’m looking to Purge only the empty sub-layers under a specific layer.
So I need the script to read all the layers under a given layer name, and delete only the empty ones.
I have limited knowledge of scripting, so I’ll appreciate your help here if possible.
Many thanks!