Problems with GhPython data structure

There is a problem with the data structure of GhPython: when my input is a list, the tree data on the output is merged; When the input end is in a tree shape, this problem will not occur (ps: the following string of data is the correct data)

def RunScript(self, Curve, Tolerance):
        try:
            sc.doc = Rhino.RhinoDoc.ActiveDoc
            self.tol = Tolerance if Tolerance else sc.doc.ModelAbsoluteTolerance
            intersection_points_list = self.Find_Intersections(Curve)
            zip_list = list(zip(Curve, intersection_points_list))
            Broken_curve = ghp.run(self.temp, zip_list)
            Broken_curve = ght.list_to_tree(Broken_curve)
            print(Broken_curve)
            
            sc.doc.Views.Redraw()
            ghdoc = GhPython.DocReplacement.GrasshopperDocument()
            sc.doc = ghdoc
            
            return Broken_curve
        finally:
            pass

Attach some of my source code


Is there a problem with this part of the source code?
If anyone needs the source code and gh files, I can send them to you

I will add some main codes again

    def temp(self, tuple):
        curve, points = tuple
        curves = self.split_curve(curve, points)
        return curves

    def split_curve(self, curve, points):
        t = []
        for p in points:
            t.append(curve.ClosestPoint(p)[1])
        return curve.Split(t)

    def Find_Intersections(self, curves):
        intersection_points_list = []
        for curve in curves:
            pts = []
            for other_curve in curves:
                if curve == other_curve: 
                    continue
                curve_intersections = rg.Intersect.Intersection.CurveCurve(curve, other_curve, self.tol, self.tol)
                for i in curve_intersections:
                       if i.IsPoint:
                           pts.append(i.PointA)
            intersection_points_list.append(pts) 

        return intersection_points_list

maybe do it here


not sure why you have to use override…

Thank you for your reply, but I don’t want to modify it in Grasshopper, it’s in the source code



Actually, I want to output a tree shape on the output side when the input side is a list

But when I changed the output to a tree shape and the input to a tree shape in the source architecture, the results were not satisfactory

Hi Niko. I’m not sure this will solve your problem (I’m happy to be corrected, but I find mangling DataTrees and re-pathing them is normal in Grasshopper), but I was able to output DataTrees (from treehelpers) for my purposes, by setting the output param to: Grasshopper.Kernel.Parameters.Param_ScriptVariable . I just use that type by default, and try to let the GhPython ‘auto-magic’ handle as much as possible.

Adding params in code in general, I found to be quite intricate (i.e. brittle, and it took a lot of trial and error to figure out). Even if you put in an ‘idempotent’ condition into RunScript, to only add Params once on the first call (when the component is placed or the first time the worksheet is loaded), you can still easily end up creating weird bugs from a component’s previous state.

I still add Params that way, but I clear all the other Params first (so I alwauys start a component from a known state), and treat it more as ‘component builder’ / ‘Devops’ code, and use it to build other GhPython components from separate special builder or config GhPython components. I can still let the user add their own Params via the ZUI, and translate them into ‘kwargs’, parsing *args in RunScript, and matching them up to their names in self.Params.Input.

If adding Params is treated as normal component code, so the component can add Params to itself, no end of tricky problems could be created, not least of which infinite loops (as updating the Params, causes RunScript to be called again).

Thank you for your reply, but do you have any code snippets on your end? I find it difficult to understand your literal meaning, and I would like to combine it with the code to try to understand the techniques you told me :slightly_smiling_face:

I can’t edit those jpegs / screen shots of code you posted. It’s easier to help you in future if you use the </> preformatted text block for code, or just put it inside triple back ticks.

So just change:

Grasshopper.Kernel.Parameters.Param_GenericObject
to:
Grasshopper.Kernel.Parameters.Param_ScriptVariable

I will give it a try, and then I will publish the code for the screenshot. Thank you very much for your help

Unfortunately, this approach did not succeed.


I will upload some of the source code here for you to find the problem

class IntersectionBreak(component):
    def SetUpParam(self, p, name, nickname, description):
        p.Name = name
        p.NickName = nickname
        p.Description = description
        p.Optional = True
    
    def RegisterInputParams(self, pManager):
        p = Grasshopper.Kernel.Parameters.Param_Curve()
        self.SetUpParam(p, "Curve", "C", "xxx")
        p.Access = Grasshopper.Kernel.GH_ParamAccess.list
        self.Params.Input.Add(p)
    
        p = Grasshopper.Kernel.Parameters.Param_Number()
        self.SetUpParam(p, "Tolerance", "T", "xxx")
        Tolerance = 0.0001
        p.SetPersistentData(gk.Types.GH_Number(Tolerance))
        p.Access = Grasshopper.Kernel.GH_ParamAccess.item
        self.Params.Input.Add(p)
    
    def RegisterOutputParams(self, pManager):
        p = Grasshopper.Kernel.Parameters.Param_ScriptVariable()
        self.SetUpParam(p, "Res_Curve", "C", "xxx")
        self.Params.Output.Add(p)
    
    def SolveInstance(self, DA):
        p0 = self.marshal.GetInput(DA, 0)
        p1 = self.marshal.GetInput(DA, 1)
        result = self.RunScript(p0, p1)
    
        if result is not None:
            self.marshal.SetOutput(result, DA, 0, True)
    def temp(self, tuple):
        curve, points = tuple
        curves = self.split_curve(curve, points)
        return curves
    
    def split_curve(self, curve, points):
        t = []
        for p in points:
            t.append(curve.ClosestPoint(p)[1])
        return curve.Split(t)
    
    def Find_Intersections(self, curves):
        intersection_points_list = []
        for curve in curves:
            pts = []
            for other_curve in curves:
                if curve == other_curve:
                    continue
               
                curve_intersections = rg.Intersect.Intersection.CurveCurve(curve, other_curve, self.tol, self.tol)
                for i in curve_intersections:
                    if i.IsPoint:
                        pts.append(i.PointA)
            intersection_points_list.append(pts) 
        return intersection_points_list
    
    def RunScript(self, curve, tol):
        try:
            sc.doc = Rhino.RhinoDoc.ActiveDoc
            Broken_curve = gd[object]()
            self.tol = tol if tol else self.tol
    
            if curve:
                self.tol = tol if tol else self.tol
                intersection_points_list = self.Find_Intersections(curve)
    
                zip_list = list(zip(curve, intersection_points_list))
                Broken_curve = ghp.run(self.temp, zip_list)
                Broken_curve = ght.list_to_tree(Broken_curve)
            else:
                self.message2(xxx')
            sc.doc.Views.Redraw()
            ghdoc = GhPython.DocReplacement.GrasshopperDocument()
            sc.doc = ghdoc
            return Broken_curve
        finally:
            self.Message = 'xxx'

I will try to modify the structure to a tree shape, which is currently the only possible solution

I only made a suggestion a week ago. I did mention it’s a tricky, fiddly, trial and error type of area.

If you would like professional support, message me.

Okay, I will. Thank you very much!