Get List of Viewports

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:

  1. 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

  1. 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

  1. 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")

Hi @jacobgerlach,

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()

– Dale

1 Like

Hi Dale,

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.

  1. Did you use FindByFilter instead of rs.ObjetsByType out of necessity, or do you prefer it for some reason?
  2. 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?
  3. 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.
  4. 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()

Hi @jacobgerlach,

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.

test_find_clippingplanes.py (1.8 KB)

Rhino is written in C++, not Python. But for the most part, you can access Rhino’s layer table in Python like you would a list.

RhinoDoc.Layers

Note, the RhinoCommon API docs are formatted for C# usage. But you should be able to translate to Python.

– Dale