For better organization of the logic i have divided the projects in subgroups in different parts of the canvas.
MY GOAL : i need to transfers large set of datas from 1 place to the other and access those data where i need to use them , i need the data structure to be exactly the same downstream…to do this i’d need a “PACK component” with zoomable interface to set NR of inputs…i then would need an “UNPACK” COMPONENT that can match nr of outputs automatically ( same as explode tree ) and that return same identical data structure and path number for the data
I have been using “entwine component” successfully until now and it worked because all list in the branches were always simple flattened lists ( no tree )…but in this case i need to transfer a list of booleans with a specifci tree and i am not able ,i tried to use “wrap List” / "unwrapp list " ( by Metahopper) but i lose the data structure , see TEST2 attached file.
is there such a component that allow me to simply pack any sort as shown above unpack them wherever i need ? it would be very useful to organize the data and the job in massive definitions.
Hi @Volker_Rakow , i tried either flatten or graft and both are not doing what i Need , they both change the data tree , with flatten i lose the tree , with graft i add a branch and when i esplode It back and.match i have a ton of branches ..
I am notnin the office now , Need to try later.
That said i thino that a “pack” “unpack” component that can compress any sort of data and its tree inside different index would be very useful..i havent seen anything like that until now
@maje90 , i tried you C# component taken from this thread but it does not fix my problem , it actually produce same result as the Metahopper components
what i need is nothing but a many input component that do nothing but storing and packing data in a single object , it should work with any sort of data type and allow user to send data it remotely without changing anything , the only changeable thing is the nr.of inputs and the corresponding nr of output in to the unpack ( opposite ) component
Hi @Volker_Rakow , and thanks! Yes, this is exactly what I need to do. Thanks a lot!
I just wonder what is holding the GH developers back from creating a native GH component that works similarly to Entwine, but simply allows grouping N wires into one, and another component that decompresses one wire back into many without changing anything.
This would be very useful for organizing definitions and keeping the canvas cleaner.
YES AND NO , I mean , under a logical point of view you are right , i was able to restore the tree structure but it does not solve my need.
I want a single wire but when i entwine everything in a single wire i can either flatten or graft but it messed up the tree again and if i want it to work i need N+1 wires as first image = hard to handle when entwine has several inputs
thanks for your solution @Volker_Rakow , i remember facing this problem other times in the past and yes , thats helpful
that said , am i wrong when say this ?
i think that having an entwine that return unchanged data thus allowing to transfer lot data in a single wire could be very useful , this would actually be the result :
I wouldn’t worry about it. For me, canvas cleanliness is not a good enough reason to want to combine and unentangle data like this.
Yes. A stream can only ever carry a single data tree. Either you flatten data while entwining, so that branches from different sources with matching branch addresses merge, or graft so that each data set is a subset of the whole.
What you are looking for, I suppose, is some sort of data tree splitting component that has expandable outputs and splits at branch depth. Someone could make this component… the question is if it would be useful. Expandable output components are generally sketchy. They do not expand or contract automatically. The user needs to “Match outputs” from the context menu. And even if the number of outputs would update automatically, how would you decide wiring? Say on one solve, the component reduces to one output. Then the next expands to five. Or a hundred. What then? But it’s not a bad idea.
Here is a python script (~90% vibe coded) that reverses the Entwine + graft operation. It splits the incoming data by first branch index, makes sure the component has the right number of output nodes, and routes the branches to the correct output while stripping the extra path index added by the graft operation of Entwine.
import Grasshopper as gh
from Grasshopper.Kernel.Data import GH_Path, GH_Structure
from Grasshopper.Kernel.Types import GH_ObjectWrapper
import RhinoCodePluginGH
def reverse_entwine():
# 1. Group the paths by their first index
grouped_branches = {}
for i in range(D.BranchCount):
path = D.Path(i)
branch_data = D.Branch(i)
if path.Length > 0:
first_idx = path[0] # This represents which Entwine input it came from
# Create a shortened path by removing the first index
new_path_indices = [path[j] for j in range(1, path.Length)]
if not new_path_indices:
new_path_indices = [0]
new_path = GH_Path(*new_path_indices)
# Use GH_Structure[GH_ObjectWrapper] to satisfy IGH_Structure
if first_idx not in grouped_branches:
grouped_branches[first_idx] = GH_Structure[GH_ObjectWrapper]()
# Wrap raw python/rhino objects into Grasshopper Goo wrappers
wrapped_data = [GH_ObjectWrapper(item) for item in branch_data]
grouped_branches[first_idx].AppendRange(wrapped_data, new_path)
# 2. Determine how many outputs we need based on the highest Entwine index found
target_count = max(grouped_branches.keys()) + 1 if grouped_branches else 1
current_count = ghenv.Component.Params.Output.Count
# 3. Schedule a topology change if the output count doesn't match
if current_count != target_count:
def callback(doc):
params = ghenv.Component.Params
# Add missing outputs
while params.Output.Count < target_count:
new_idx = params.Output.Count
nickname = "R"
p = RhinoCodePluginGH.Parameters.ScriptVariableParam(nickname)
p.Name = "Entwine Out {}".format(new_idx)
p.Access = gh.Kernel.GH_ParamAccess.tree
params.RegisterOutputParam(p)
# Remove excess outputs
while params.Output.Count > target_count:
last_idx = params.Output.Count - 1
params.UnregisterOutputParam(params.Output[last_idx])
params.OnParametersChanged()
ghenv.Component.ExpireSolution(True)
ghenv.Component.OnPingDocument().ScheduleSolution(5, gh.Kernel.GH_Document.GH_ScheduleDelegate(callback))
# 4. Safely push the modified GH_Structures to their respective outputs
for i in range(ghenv.Component.Params.Output.Count):
output_param = ghenv.Component.Params.Output[i]
output_param.ClearData() # Prevent data accumulation on refreshes
if i in grouped_branches:
output_param.AddVolatileDataTree(grouped_branches[i])
# Run the execution routine
reverse_entwine()
This script uses a callback function to modify its own outputs without the right click menu step. It seems to work fine on this small file, but I’m not sure it wouldn’t do an entire re-run of a large solution and waste a bunch of time or something.
in simple word what i need is nothing but an entwine component that does not flatten or graft…it only wrap and stream in a single object complex sets of data and stream this data somewhere , i dont need input and output to change or update automatically cause it is just a placeholder and wrapper that make this set of data available everywhere down the definition., wherever i need
i have been using this approach on arranging massive definitions for a while now and i can assure that this practice helps a lot on keeping massive scripts scalable, ordered , easy to update, read and modify
Yes. And what I am trying to explain is that such a thing is not possible with in the bounds Grasshopper’s concept of data structure. There is no “entwining” that does not flatten or graft…
It doesn’t matter. I understand what you mean essentially.
For completion’s sake, some native Grasshopper variants: