Code to create an arrow preview in GhPython

Hi @piac
i try Display.DrawDirectionArrow with the script of @dadandroid but i have one problem (i don’t compile the component yet)
when i unplug the curve, the arrows still appear until i hit Test again and i want remove the message box.

from ghpythonlib.componentbase import executingcomponent as component
import Grasshopper, GhPython
import System
import Rhino
import rhinoscriptsyntax as rs
import Rhino.Geometry as rg


class PreviewEx(component):
    
    def RunScript(self,C):

        if not C: return
        self.points = []
        self.tps = []
        self.tgnt = []
        pts = rs.DivideCurve(C,2,True)
        
        npts = pts
        npts.insert(2, rs.CurveEndPoint(C))
        self.points = npts
        
        for i in range(3):
            pt = rs.CurveClosestPoint(C,pts[i])
            self.tps.append(pt)
            tg = rs.CurveTangent(C,self.tps[i])
            self.tgnt.append(tg)
            
    def DrawViewportWires(self, args):
        
        try:
            for i in range(3):
                args.Display.DrawDirectionArrow(self.points[i], self.tgnt[i], System.Drawing.Color.White)
            
        except Exception, e:
            None
            #System.Windows.Forms.MessageBox.Show(str(e), "script error")
        
    def IsPreviewCapable(self):
        return True

You should remove the curves and make sure that DrawViewportWires returns immediately when C is None:

if not C: return creates the condition that you noticed.

Thanks,

Giulio


Giulio Piacentino
for Robert McNeel & Associates
giulio@mcneel.com

1 Like

Thanks Giulio
i tried but i don’t understand exactly, if i use

def DrawViewportWires(self, args):
            if not C: return
            for i in range(3):
                args.Display.DrawDirectionArrow(self.points[i], self.tgnt[i], System.Drawing.Color.White)

The line disappear from the viewoprt.
The only method work for me now when i disable the condition, with error on the component

def RunScript(self,C):

        #if not C: return

Ehm, who wrote this script then?

I can fix it for you, but it would be wiser for you to study it also line by line, to see what it does. If you are OK with this, I’ll move it to a new topic. This is an advanced topic, and it might just be a bit overwhelming if you are just starting with scripting.

1 Like

I solve it now thanks :slight_smile:

i call it self.crv = C instead of C and it work fine

from ghpythonlib.componentbase import executingcomponent as component
#import Grasshopper, GhPython
import System
#import Rhino
import rhinoscriptsyntax as rs
import Rhino.Geometry as rg


class PreviewEx(component):
    

    def RunScript(self,C):
        self.crv = C
        if not self.crv: return
        self.points = []
        self.tps = []
        self.tgnt = []
        pts = rs.DivideCurve(self.crv,2,True)
        npts = pts
        npts.insert(2, rs.CurveEndPoint(self.crv))
        self.points = npts
        
        for i in range(3):
            pt = rs.CurveClosestPoint(self.crv,pts[i])
            self.tps.append(pt)
            tg = rs.CurveTangent(self.crv,self.tps[i])
            self.tgnt.append(tg)
            
    def DrawViewportWires(self,arg):
        
         if not  self.crv: return
         for i in range(3):
              arg.Display.DrawDirectionArrow(self.points[i], self.tgnt[i], System.Drawing.Color.White)
1 Like

Yes i just start scripting with grasshopper, i hope see your solution to learn from it and for anyone who need help in future
the script created based on script of David in this thread as i mentioned before

1 Like

There is another problem in the last script ; the arrows appear but the curve are not appear in grasshopper
emm thats wird ; it work in a new document

I haven’t tested the script, but it also needs to compute the bounding box of all the geometry that it wants to preview. Then, the bounding box must be returned in the get_ClippingBox method. As it is shown here:

I moved this sub-topic to a new topic.

1 Like

Many thanks Giulio, i appreciate your help
i study now when many curves selected

1 Like

My Brain stopped here :smiley:

from ghpythonlib.componentbase import executingcomponent as component
import System
import rhinoscriptsyntax as rs
import Rhino.Geometry as rg

class PreviewEx(component):

def RunScript(self,C):
    self.crv = C
    if not self.crv: return
    self.points = []
    self.tgnt = []
    for i in range(len(C)):
        pts = rs.DivideCurve(self.crv[i],2,True)
        for j in range(3):
           pt = rs.CurveClosestPoint(self.crv[i],pts[j])
           tg = rs.CurveTangent(self.crv[i],pt)
           self.tgnt.append(tg)
           self.points.append(pts[j])
    #print self.points
    #print self.tgnt
        
def DrawViewportWires(self,arg):
    
     if not  self.crv: return
     for i in range(len(self.crv)):
        for i in range(3):
             arg.Display.DrawDirectionArrow(self.points[i], self.tgnt[i], System.Drawing.Color.White) 

the input have two curves (or more )
in def DrawViewportWires(self,arg): the length of curves list have no effect
maybe because i append all points and tangents

I compile the script and it work fine with single curve without bounding box

One day it might not work fine. This is a requirement that does not show sometimes. But then when it shows, it is really bad. I also don’t see the point of compiling if the code is already online…
My 2 cents.

1 Like

I compile it to try if it work because sometimes the scripts it work fine but after compiling nope.
and of course i need the best solution that why i asked and i don’t really understand the idea of the bounding box, i will study it more.
I use always examples from help but some of them don’t work or need more lines to work

The bounding box computation is because of this: Rhino tries to optimize preview by using bounding boxes. If the thing that you want to draw is outside the “view frustum”, then its drawing function will not be called. This operation is called “view frustum culling”.

1 Like

Thank you ,I tried it but bounding box union don’t accept the points

Update:

i use this ; i don’t know if this work or not

i hope this ok :slight_smile: , thanks for help Giulio

from ghpythonlib.componentbase import executingcomponent as component
import Grasshopper, GhPython
import System
import Rhino
import rhinoscriptsyntax as rs
import Rhino.Geometry as rg

class DisplayDirection(component):
    
    def __init__(self):
        self.pts = []
        self.bb = Rhino.Geometry.BoundingBox()

    def RunScript(self,C):
        self.c = C
        if not self.c: return
        self.bb = Rhino.Geometry.BoundingBox()
        self.tps = []
        self.tgnt = []
        self.pts = rs.DivideCurve(self.c,2,True)
        for i in range(len(self.pts)):
            self.bb.Union(self.pts[i])
        self.pts.insert(2, rs.CurveEndPoint(self.c))

        for i in range(3):
            pt = rs.CurveClosestPoint(self.c,self.pts[i])
            self.tps.append(pt)
            tg = rs.CurveTangent(self.c,self.tps[i])
            self.tgnt.append(tg)
            
    def DrawViewportWires(self,arg):
        
         if not  self.c: return
         for i in range(3):
             arg.Display.DrawDirectionArrow(self.pts[i], self.tgnt[i], System.Drawing.Color.White)
    
    def get_ClippingBox(self):
        return self.bb

Update: this version work with multi curves, i also add the idea of bounding box
i know there is always more simple method but that what i get

from ghpythonlib.componentbase import executingcomponent as component
import Grasshopper, GhPython
import System
import Rhino
import rhinoscriptsyntax as rs

class CurvesDirection(component):
    def __init__(self):
        self.pts = []
        self.bb = Rhino.Geometry.BoundingBox()
        
    def RunScript(self, C):
        self.c = C
        if not self.c: return
        self.bb = Rhino.Geometry.BoundingBox()
        lisc = []
        self.plist = []
        self.tlist = []
        
        for i in range(len(self.c)):
            lisc.append([self.c[i]])
        for i in range(len(self.c)):
            if not self.c[i] : return
            if rs.IsCurveClosed(self.c[i]) == True:
                 n = 3
            elif rs.IsCurveClosed(self.c[i]) == False:
                 n = 2
                 
            for j in range(1):
               self.pt = rs.DivideCurve(lisc[i][0],n,True)
               for k in range(len(self.pt)):
                   self.bb.Union(self.pt[k])
                   self.pts = rs.CurveClosestPoint(self.c[i],self.pt[k])
                   self.tg = rs.CurveTangent(self.c[i],self.pts)
                   self.plist.append(self.pt[k])
                   self.tlist.append(self.tg)

        parts = len(self.c)
        self.p = [self.plist[(i*len(self.plist))//parts:((i+1)*len(self.plist))//parts] for i in range(parts)]
        self.t = [self.tlist[(i*len(self.plist))//parts:((i+1)*len(self.plist))//parts] for i in range(parts)]
                            
    def DrawViewportWires(self,arg):                 
       if not  self.c: return
       for i in range(len(self.c)):
           if not self.c[i] : return
           for j in range(3):
              arg.Display.DrawDirectionArrow(self.p[i][j],self.t[i][j], System.Drawing.Color.White)
              
    def get_ClippingBox(self):
        return self.bb

It work fine now i hope no problem appear in future :slight_smile:
I create also other components i need them
Thank you for help

Hi Seghier
Care to share?

Yes of course; if a problem appear tell me

image