Grasshopper

algorithmic modeling for Rhino

I'm writing my first GH add-on with Visual Studio C#

I've succeeded in matching string, my next step is to change the tree branch path to the index of the matched string. Here's what I have so far (see below).

Explanation of my intent:

The first input (crvTree) has the exact same data structure as the second input (cell_name). crvTree contains one or more Curves in each branch, while cell_name contains exactly one string per branch. 

The third input (system_names) is a list of string data, and I compare the single string from each branch of cell_name and find a match, then return the index of system_name.

So, for example:

crvTree brings in:

{0} bunch of Curves

{1} bunch of other Curves

{2} another bunch of Curves

cell_name brings in:

{0} "curve type A"

{1} "curve type D"

{2} "curve type A"

system_name brings in:

{0;0} "curve type A"

{0;1} "curve type B"

{2;0} "curve type C"

{2;1} "curve type D"

{2;2} "curve type E"

{3;0} "curve type F"

output should be:

{0;0} bunch of Curves (and) another bunch of Curves

{2;1} bunch of other Curves

I'm pretty sure that I can't keep accessing cell_name as an item, but instead as a tree. I was only doing that to first get the strings to match, which I did.

protected override void SolveInstance(IGH_DataAccess DA)
{
//Declare a new List(Of T) to hold the input text data.
string cell_name = "nothing yet";
List<string> system_names = new List<string>();
int index;

Grasshopper.Kernel.Data.GH_Structure<Grasshopper.Kernel.Types.GH_Curve> crvTree = new
Grasshopper.Kernel.Data.GH_Structure<Grasshopper.Kernel.Types.GH_Curve>();

//Retrieve the whole list of System Names using DA.GetDataList().
if ((!DA.GetDataTree(0, out crvTree))) { return; }
if ((!DA.GetData(1, ref cell_name))) { return; }
if ((!DA.GetDataList(2, system_names))) { return; }

index = system_names.IndexOf(cell_name);

int index2 = -1;
for(int i = 0; i < system_names.Count; i++)
{
if(String.Equals(system_names[i], cell_name, StringComparison.OrdinalIgnoreCase))
{
index2 = i;
break;
}
}

DA.SetData(0, index2);
DA.SetDataTree(1, crvTree);

}

Views: 720

Reply to This

Replies to This Discussion

Hi Santiago,

if you're getting trees out of inputs, never modify them, because they are shared. It's a bit more code, but I'd approach this by getting all input trees and setting all output trees. The following code does not have sufficient error checks to make me happy, it doesn't validate whether the input data is correct, but that's stuff that can be added later.

The idea is that you build a dictionary from your system_names data, so that you can very quickly look up string/path pairs. You then use this dictionary to populate a new data tree one item at a time.

protected override void SolveInstance(IGH_DataAccess DA)
{
// Get the curve tree (although the fact that it is curves is irrelevant).
// I switched to IGH_Goo, but the generic constraint depends on the type of parameter you've picked.
GH_Structure<IGH_Goo> treeData;
DA.GetDataTree(0, out treeData);
if (treeData.IsEmpty)
return;

// Get list of type descriptions (ie. must be one for each item in treeData).
GH_Structure<GH_String> treeTypes;
DA.GetDataTree(1, out treeTypes);
if (treeTypes.PathCount != treeData.PathCount)
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Data and type trees must have the same layout");
return;
}

// Get the category layout.
GH_Structure<GH_String> treeCategories;
DA.GetDataTree(2, out treeCategories);

// Build category dictionary for easy lookup.
Dictionary<string, GH_Path> table = new Dictionary<string, GH_Path>();
for (int p = 0; p < treeCategories.PathCount; p++)
{
GH_Path path = treeCategories.Paths[p];
List<GH_String> list = treeCategories.Branches[p];
foreach (GH_String category in list)
table.Add(category.Value, path);
// The above will throw exceptions if the same category name occurs more than once,
// or if the category tree contains null items.
}

// Build a new tree. NEVER MODIFY THE OLD TREE, IT IS SHARED!
GH_Structure<GH_Integer> treeIndices = new GH_Structure<GH_Integer>();
GH_Structure<IGH_Goo> treeResult = new GH_Structure<IGH_Goo>();
for (int p = 0; p < treeData.PathCount; p++)
{
List<IGH_Goo> listData = treeData.Branches[p];
List<GH_String> listTypes = treeTypes.Branches[p];

for (int i = 0; i < listData.Count; i++)
{
string type = listTypes[i].Value;
GH_Path path = table[type];
treeResult.Append(listData[i], path);
treeIndices.Append(new GH_Integer(-1), path); // Sorry, what index?
}
}

DA.SetDataTree(1, treeResult);
}

Hi Dave, I tried your code, and it works. Thank you!

Regarding the index to be exported (treeIndices), there is additional data that I need to replace paths to match the treeData.

The treeCategories are actually the names of building systems. Each building system contains a series of data that describes this system. When the system descriptor is paired with cell curves, a building is generated.

I'll spend some time trying to figure out how to get this to work. It is already working by using GH components. I am now trying to accomplish the same with a GH add-on. I can send you my GH definition if you're curious to see it. Any further help or insights is obviously very welcome!

I am spending time now trying to make the definition run faster (by writing the add-on). Your suggestion of using a dictionary helps. There's still much room for performance improvement, I have my work cut-out for me.

Santiago

RSS

About

Translate

Search

Photos

  • Add Photos
  • View All

© 2020   Created by Scott Davidson.   Powered by

Badges  |  Report an Issue  |  Terms of Service