I’m writing a little script to find clipping planes hiding in inactive layers, but having trouble getting a proper viewport object to use as the argument for the clipping plane’s IsActiveInViewport method.
I’ve tried:
Using the viewname:
for vp in rs.ViewNames():
if cpo.IsActiveInViewport(vp) and not rs.IsLayerOn(cp_layer):
But the viewname is a string and not a RhinoViewport
Coercing from the viewport name returned by rs.ViewNames:
for vp_id in rs.ViewNames():
vpo=rs.coercerhinoobject(vp_id,True,True)
but the viewnames aren’t guids
Getting views from scriptcontext: sc.doc.Views.GetEnumerator() #wrong type, RhinoView instead of Viewport
Full script follows:
import Rhino
import rhinoscriptsyntax as rs
import scriptcontext as sc
cps = rs.ObjectsByType(536870912)
if len(cps)>0:
print("Found clipping planes")
for cp_id in cps:
cp_layer=rs.ObjectLayer(cp_id)
cpo=rs.coercerhinoobject(cp_id,True,True)
for vp in rs.ViewNames():
if cpo.IsActiveInViewport(vp) and not rs.IsLayerOn(cp_layer):
print("An active clipping plane is hiding on ",cp_layer)
else:
print("Found no clipping planes")
Please review the following and let me know if you have any questions:
import Rhino
import scriptcontext as sc
import clr
def test_find_clippingplanes():
# Object type to find
filter = Rhino.DocObjects.ObjectType.ClipPlane
# Construct enumerator settings
settings = Rhino.DocObjects.ObjectEnumeratorSettings()
settings.NormalObjects = True
settings.HiddenObjects = True
settings.LockedObjects = True
settings.DeletedObjects = False
settings.ObjectTypeFilter = filter
# Find the objects
rh_objects = sc.doc.Objects.FindByFilter(settings)
if not rh_objects or len(rh_objects) == 0:
print("No clipping plane objects found.")
return
# Build a dictionary of viewportid/name pairs
dict = {}
views = sc.doc.Views.GetStandardRhinoViews()
for v in views:
dict[v.ActiveViewportID] = v.ActiveViewport.Name
# Process each object that was found
for rh_obj in rh_objects:
print(rh_obj.ObjectType.ToString())
print(" " + rh_obj.Attributes.ObjectId.ToString())
print(" " + sc.doc.Layers[rh_obj.Attributes.LayerIndex].FullPath)
# Cast as a clipping plane object
cp_obj = clr.Convert(rh_obj, Rhino.DocObjects.ClippingPlaneObject)
if cp_obj:
# Print the clipped views
for id in cp_obj.ClippingPlaneGeometry.ViewportIds():
if dict.has_key(id):
print(" " + dict[id].ToString())
if __name__ == "__main__":
test_find_clippingplanes()
Thanks, this got me where I needed to be. I ended up adding reference objects to the object finder so I could pick up clipping planes from worksession references, and making a couple other changes to specifically find hidden clipping planes. My final version below for reference.
If you can spare any time to teach a man to fish, I’m curious about the differences in your approach. Any enlightenment on the following would be appreciated.
Did you use FindByFilter instead of rs.ObjetsByType out of necessity, or do you prefer it for some reason?
If I tested this right, cp_obj.ClippingPlaneGeometry.ViewportIds() excludes layout details. This is actually what I want here, but how would I do something similar to check detail viewports?
Is getting a specific layer with sc.doc.Layers[rh_obj.Attributes.LayerIndex] just a python dictionary lookup? I’m a python novice, so not sure about the syntax here.
Related to #3, where can I find documentation for sc.doc.Layers? I had trouble googling this.
Thanks again!
Jake
import Rhino
import scriptcontext as sc
import clr
def test_find_clippingplanes():
# Object type to find
filter = Rhino.DocObjects.ObjectType.ClipPlane
# Construct enumerator settings
settings = Rhino.DocObjects.ObjectEnumeratorSettings()
settings.NormalObjects = True
settings.HiddenObjects = True
settings.LockedObjects = True
settings.DeletedObjects = False
settings.ReferenceObjects = True
settings.ObjectTypeFilter = filter
# Find the objects
rh_objects = sc.doc.Objects.FindByFilter(settings)
if not rh_objects or len(rh_objects) == 0:
print("No clipping plane objects found.")
return
# Process each object that was found
for rh_obj in rh_objects:
#we only care about clipping planes on hidden layers, assume user has handled others
#a future improvement would be to check for hidden objects, but typing show is pretty easy
cp_layer = sc.doc.Layers[rh_obj.Attributes.LayerIndex]
if not cp_layer.IsVisible:
# Cast as a clipping plane object
cp_obj = clr.Convert(rh_obj, Rhino.DocObjects.ClippingPlaneObject)
if cp_obj:
#don't care which views are clipped, just that there is at least one
if cp_obj.ClippingPlaneGeometry.ViewportIds():
print("An active clipping plane is hiding on layer: " + sc.doc.Layers[rh_obj.Attributes.LayerIndex].FullPath)
if __name__ == "__main__":
test_find_clippingplanes()
My preference is to call into RhinoCommon directly, rather than use rhinoscriptsyntax (which eventually calls into RhinoCommon too). But both methods work.
Yeah, my simple example assumed clipping planes were all clipping model viewports. Here’s an update that should do both model and detail viewports.