Hi @duanemclemore
In my opinion is best practice to create a platform independent library. This means that it is much better to use .NET’s native data structures like array, multidimensional array, jagged array, stacks, hash tables etc… This will make your code be easily ported to other software’s outside of the Rhino ecosystem. All the data tree stuff related to “depth” or “paths” just gets to freeky in my opinion. If you want something that behaves similar to a DataTree
or a GH_Structure
you can use a Jagged Array
which is basically an array of arrays. This type of data structure is best used when your data is not rectangular. This means that each array will have a different length, like DataTrees usually have
Jagged arrays are also very quick to access by index, because the C# runtime is highly optimized for arrays. Do note that they will consume more memory to allocate because each array will occupy its own memory space in the heap. Making it more time consuming for the Garbage Collector to clear out memory.
For example, if your input will be a DataTree from Grasshopper you can convert it easily to a Jagged Array as such
/// <summary>
/// Convert Data Tree to Jagged Array data structure
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data">Data tree to convert</param>
/// <returns></returns>
public static T[][] ToJaggedArray<T>( DataTree<T> data)
{
// formula for getting items in branches = total number of elements / branch count
int totalElementsPerArray = data.DataCount / data.BranchCount;
int numElements = data.BranchCount;
T[][] observations = new T[numElements][];
for (int i = 0; i < observations.Length; i++)
{
T[] sub = new T[totalElementsPerArray];
for (int j = 0; j < totalElementsPerArray; j++)
{
sub[j] = data.Branch(i)[j];
}
observations[i] = sub;
}
return observations;
}
And when you are ready to display some stuff in Rhino :
/// <summary>
/// Convert Jagged Array to a Data Tree
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data">Jagged Array to manipulate </param>
/// <returns> A Grasshopper Data Tree matching the same data structure as the input
/// Jagged Array </returns>
public static DataTree<T> ToDataTree<T>(T[][] data)
{
DataTree<T> dataTree = new DataTree<T>();
int totalBranches = data.Length;
for (int i = 0; i < data.Length; i++)
{
for (int j = 0; j < data[i].Length; j++)
{
dataTree.Add(data[i][j], new GH_Path(i));
}
}
return dataTree;
}
Note: I am using something called Generics in C#, that is what the T
is basically telling the compiler. This means that your data structures can hold anything you need.
I hope, this helps.
PS: I think eventually you will need to start posting some code, so we can see what you are trying to do, this can be more efficient in how people can help you as well. There can be many misunderstandings sometimes. So its better to be as explicit as possible with the problem you are having and need help with.
PSS:
Here you can see what I was referring to about memory allocation differences
Jagged Array
long t1 = GC.GetTotalMemory(true);
int[][] jaggedArr = new int[1000][];
for (int i = 0; i < 1000; i++)
{
//Notice how each element of jaggedArr is an array that will hold 250 elements.
// Or a "Branch" with 250 elements
jaggedArr[i] = new int[250];
}
long t2 = GC.GetTotalMemory(true);
this will occupy:
2D Array
long t3 = GC.GetTotalMemory(true);
int[,] multArr = new int[1000, 250];
long t4 = GC.GetTotalMemory(true);
this will occupy:
So the Jagged Array will occupy 32,392 + bytes !