Rhino python preview geometry methods?

When programming with Rhino python I find myself working without much visual connection. Sure the product of my script is some geometry that is added to the document in the end, but I wish that there was an easy way to preview geometry just like selecting a grasshopper component. I’ve been wanting to write a python library that would let you take a quick peek at Rhinocommon geometry while running your script, without writing it to the document.
It would have the following features:

  • Geometry would be drawn with display order priority over existing rhino geometry just like grasshopper. This would allow the user to see highlighted brep edges etc.
  • Ability to show geometry in the document after script is run.
  • Simple use of the library, one fuction to show any type of geometry.

A potential usage:

import geo_viewer
pt = Rhino.Geometry.Point3d(0,0,1)
geo_viewer.show(pt, show_after=True, color='red') ]
geo_viewer.hide(pt)
geo_viewer.clear()

I’ve been trying to write this library for my own use but am having issues with display conduits written in python(I’m on mac). Does anyone have ideas on how I could implement something like this? Maybe using NodeInCode to hijack the native grasshopper preview? I thought I would reach out on the forum in case anyone is already doing something similar or would want to help develop this?

From the DisplayConduit examples it looks like something like this would be possible using sticky to keep the geometry around after script is run etc.

One of the things that makes grasshopper a great tool is how easy it is to see what your working with in the viewport, I’d like to have that same benefit when working with python.

Best,
Tristan

1 Like

This sounds like a great idea, and I would love to use it. Feels like it would be more powerful if it’s used in interactive mode.

if it’s just for the development of your script, you can always code inside the grasshopper python component and then later use that code (with maybe a few modifications) in Rhino. What difficulties do you have in using display conduits?
When developing scripts with display conduits, it often happens that something crashes or hangs and you will end up with left overs from the conduit. Bugs in Conduits can easily crash Rhino. Therefore it is always recommended to write your display conduit stuff inside try/except blocks, at least when developing the scripts. If you look on my github page you can find various examples of scripts that use display conduits.

1 Like

Here is an example of my issue with display conduit at the moment:
This script is a brep version of: https://developer.rhino3d.com/samples/rhinocommon/draw-mesh/
It also translates the brep by 10 in the y direction to ensure it is not being drawn undeneath the selected geometry.

import rhinoscriptsyntax as rs
from scriptcontext import doc
import Rhino
import System
import System.Drawing

def RunCommand():
    gs = Rhino.Input.Custom.GetObject()
    gs.SetCommandPrompt("select brep")
    gs.GeometryFilter = Rhino.DocObjects.ObjectType.Brep
    gs.Get()
    if gs.CommandResult() != Rhino.Commands.Result.Success:
        return gs.CommandResult()

    brep = gs.Object(0).Brep()
    brep.Translate(Rhino.Geometry.Vector3d(0,0,0))

    conduit = DrawConduit(brep)
    conduit.Enabled = True
    doc.Views.Redraw()
    inStr = rs.GetString("press <Enter> to continue")
    conduit.Enabled = False
    doc.Views.Redraw()
    return Rhino.Commands.Result.Success

class DrawConduit(Rhino.Display.DisplayConduit):
    def __init__(self, brep):
        self.brep = brep
        self.color = System.Drawing.Color.Blue
        self.bbox = brep.GetBoundingBox(True)

    def CalculateBoundingBox(self, calculateBoundingBoxEventArgs):
        calculateBoundingBoxEventArgs.BoundingBox.Union(self.bbox)

    def PreDrawObjects(self, drawEventArgs):
        drawEventArgs.Display.DrawBrepWires(self.brep, self.color)

if __name__ == "__main__":
    RunCommand()

The script completes, but no brep is drawn to the screen.
Any ideas @Gijs on how to get this to work? This was where I was starting work on the library.

Does this help? (works on Windows, not tested on Mac)

import rhinoscriptsyntax as rs
from scriptcontext import doc
import Rhino
import System
import System.Drawing

def RunCommand():
    gs = Rhino.Input.Custom.GetObject()
    gs.SetCommandPrompt("select brep")
    gs.GeometryFilter = Rhino.DocObjects.ObjectType.Brep
    gs.Get()
    if gs.CommandResult() != Rhino.Commands.Result.Success:
        return gs.CommandResult()

    brep = gs.Object(0).Brep()
    brep.Translate(Rhino.Geometry.Vector3d(30,30,30))

    conduit = DrawConduit(brep)
    conduit.Enabled = True
    doc.Views.Redraw()
    inStr = rs.GetString("press <Enter> to continue")
    conduit.Enabled = False
    doc.Views.Redraw()
    return Rhino.Commands.Result.Success

class DrawConduit(Rhino.Display.DisplayConduit):
    def __init__(self, brep):
        self.brep = brep
        self.color = System.Drawing.Color.Blue
        self.bbox = brep.GetBoundingBox(True)

    def CalculateBoundingBox(self, calculateBoundingBoxEventArgs):
        calculateBoundingBoxEventArgs.IncludeBoundingBox(self.bbox)

    def PreDrawObjects(self, drawEventArgs):
        drawEventArgs.Display.DrawBrepWires(self.brep, self.color)

if __name__ == "__main__":
    RunCommand()

yes works on mac thanks, had meant to set that vector to something…
Do you have any idea how to draw the display conduit geometry on top of rhino geometry?
Also, what about using the DrawObject method instead of having a bunch of if statements to figure out which types of geometry are being passed to the function and calling DrawBrepWires, DrawMeshWires etc.
When replacing drawEventArgs.Display.DrawBrepWires(self.brep, self.color) with drawEventArgs.Display.DrawObject(self.brep) nothing is drawn to the screen.
I guess this raises the question how to convert from Geometry.Brep to DocObjects.RhinoObject class?
Tristan

but also notice I changed the bbox code a bit to make it include the box

for this use DrawOverlay
See also a general overview of the ‘layers’ here: DisplayPipeline Class

I never used that, so cannot give much advise about it. But since it is targeted at a Rhino doc object, I have a hard time understanding how that would be useful.