Displaying a Vector using C# and GH_PreviewUtil....?

Hi,

im trying to write a component that will take a line and show the line as is its a vector (line start point as the anchor point and line end point as the vector). ive found that i can do this using GH_Preview Utility. (see attached images)

the issue im having is that once in Rhino, after ive created a line and plugged it into my component, if i try to adjust the original line (move one of its endpoints for example) the original vector preview (and every following one) is persistent regardless of if i clear the component, freeze, etc.

my assumption is that it has something to do with how the code is handled in the solver instance? any ideas of how to fix this?

I have never used that preview util.

But from grasshopper components I always display geometry by overriding these two methods:

public override BoundingBox ClippingBox {
    get {
      return boundingboxOfYourGeo;
    }
  }
  public override void DrawViewportWires(IGH_PreviewArgs args)
  {
      args.Display.DrawSomeMethod()
}

Petras,

Thanks for your input i will definitely use your strategy in the future. I was though, finally, able to get the preview utility to work. It involved creating the GH_PreviewUtil object in the components constructor and running its .Clear() method in the solver instance before running the .AddVector(Line ln) method.

… pretty basic stuff, im kind of mad at myself that it took this long to solve

Happy New Year

Hi @mlewis, @Petras_Vestartas

I was trying to utilize this .GH_PreviewUtil() as well and having a similar problem - trying to run through a Python component, it seemingly works fine:

import Grasshopper
import Rhino

previewUtil = Grasshopper.Kernel.GH_PreviewUtil()
previewUtil.Enabled = True
previewUtil.Clear()
previewUtil.Redraw()
previewUtil.AddPoint(Rhino.Geometry.Point3d(0,0,0))


Adds preview geometry (in this case just a point) to the Rhino Scene and Layout view just as I’d hoped, but it doesn’t seem to ‘Clear’ any existing previews? If I change the point value and run again, it adds a second point, but the first point sticks around even though I’ve added a .Clear() call in there?

Any thoughts on what I’m doing wrong there and how you got it to work properly in your component?

thanks very much!
-Ed

1 Like

I think that’s because every time you commit a change to your Python code, Grasshopper interprets that as a brand new component being created (your standard Python script component, by default, is getting a new random Guid every time you make a change to it). So every time you hit the Test button, Grasshopper creates a new instance of previewUtil, keeping the old one still in memory, but not accessible by your “new component” any more.

Okay, I have tried myself.
It seems that the Python component generates a new instance of itself every time it runs.

So here how to make it work in this case:
You need first to switch to GH_Component SDK mode, create a new class for your component, and define a class attribute that will be inherited by all of its instances.

class MyComponent(component):

previewUtil = Grasshopper.Kernel.GH_PreviewUtil()
previewUtil.Enabled = True

def RunScript(self, *args):
    
    # Some Code
    
    return

Then, you can (still without editing the script!) add all the geometry you need to your previewUtil and still be able to clear it in a later moment.

For example:
I am starting with this:


I then draw on my PreviewUtil some points sliding the slider:

And still, hitting the button I am able to delete them:

I hope this makes sense.

Cheers!
Matteo

Hi @Matteo_Falduto

This is great! thanks. I’ll give your method a try and see if it works for my project here. In case it is any help to folks who might stumble on this post in the future: Jumping off this example script from Rhino Developer Docs I was able to make my custom preview work using a GH Python component in a slightly different manner by creating my own CustomConduit and then enabling / disabling that using a simple boolean toggle.

I havn’t at all cleaned up my if/thens just yet, but if its helpful the relevant bits ended up looking like:

import Rhino
import scriptcontext as sc
from System import Object
import System.Drawing

class CustomConduit(Rhino.Display.DisplayConduit):
    
    def DrawForeground(self, e):
        color = System.Drawing.Color.Blue
        Text3dEntity = Rhino.Display.Text3d( self.Text )
        Text3d_Origin = Rhino.Geometry.Point3d(0,0,0)
        Text3d_Normal = Rhino.Geometry.Vector3d(0,0,1)
        Text3dEntity.TextPlane = Rhino.Geometry.Plane(origin=Text3d_Origin, normal=Text3d_Normal)
        Text3dEntity.Height = 1
        align = Rhino.DocObjects.TextHorizontalAlignment()
        Rhino.DocObjects.TextHorizontalAlignment.value__.SetValue(align, 1) #1=Center
        Text3dEntity.HorizontalAlignment = align
        
        e.Display.Draw3dText(Text3dEntity, color)

def showafterscript(_text, _preview):
    newConduit = None
    newConduit = CustomConduit()
    newConduit.Text = _text
    
    if not _preview:
        if sc.sticky.has_key('myconduit'):
            oldConduit = sc.sticky['myconduit']
            oldConduit.Enabled = False
            newConduit.Enabled = False
    else:
        if sc.sticky.has_key('myconduit'):
            oldConduit = sc.sticky['myconduit']
            oldConduit.Enabled = False
            newConduit.Enabled = True
            sc.sticky['myconduit'] = newConduit
        else:
            newConduit.Enabled = True
            sc.sticky['myconduit'] = newConduit
    
    if newConduit.Enabled: print('Conduit Enabled!')
    else: print('Conduit Disabled!')
    
    sc.doc.Views.Redraw()

# Show Text Preview
if showPreview != False and text != None:
    previewText = text
    showPreview = True
else:
    previewText = None
    showPreview = False

showafterscript(previewText, showPreview)

thanks again!
best,
-Ed

1 Like