@luca_vezza wrote:
@Anonymous wrote:
I would suggest to use the ComAPI, converting your ModelItemCollection once.
Using this method I'm able to parse depth first a model with around half million objects in less than a second on a typical laptop, including accessing each object name.
Back to my performance quest...
I have a problem with the ComAPI. Suppose you have two items under the same parent group; if I get the paths for them, how can I detect that they belong to the same parent node? The two paths DO NOT include the same nodes apparently (or I may have missed something crucial there...).
Luca
Hi Luca,
Not sure how you get your paths or why you need to check the parent, but let me guess
Imagine you get the paths based on the current selection, something like this:
InwOpSelection nwSel = ComApiBridge.ToInwOpSelection(NWApp.ActiveDocument.CurrentSelection.SelectedItems);
InwSelectionPathsColl nwItems = nwSel.Paths()
And you want to get access to their parents but only once per parent?
for each node, you can access the parent (provided it's not already a root, I just keep the code simple):
int c = nwItems.Count;
for (int i=1;i<=c;i++)
{
InwOaPath3 path = (InwOaPath3)nwItems[i];
InwOaNode parent = path.Nodes()[path.Nodes().Count - 1] as InwOaNode;
// check here if already in a list you build on the fly
}
Is it what you are looking at?
BTW, I was intrigued by your comment
The two paths DO NOT include the same nodes apparently (or I may have missed something crucial there...).
Thus I decided to implement it and I ended up being "flabbergasted".
As you stated the nodes objects in different paths, and worst even when extracted from the same path are different and both == and .Equals() return false !!! Even their HashCodes are different !
And since it's not possible to access their nwHandle, the only workaround I found was to build the parent full path as a string and store it in a HashSet to check for already "found" parent
I include the code below but I strongly recommend you report this as a bug in the ComAPI to Autodesk team, hopefully they could fix the Equals method or worst case to avoid compatibility issues provides a way to check for equality and thus avoid such ugly and inefficient workaround.
InwOpSelection nwSel = ComApiBridge.ToInwOpSelection(NWApp.ActiveDocument.CurrentSelection.SelectedItems);
InwSelectionPathsColl nwItems = nwSel.Paths();
int pc = nwItems.Count;
HashSet<string> parentsPaths = new HashSet<string>(pc);
for (int i = 1; i <= pc; i++)
{
InwOaPath3 path = (InwOaPath3)nwItems[i];
// Check for parent
InwPathNodesColl nodes = path.Nodes();
int nc = nodes.Count;
if (nc > 1)
{
InwOaNode parent = path.Nodes()[nc - 1] as InwOaNode;
InwOaNode parent2 = path.Nodes()[nc - 1] as InwOaNode;
Debug.Print($"== {(parent == parent2).ToString()}");
Debug.Print($"Equals = {parent.Equals(parent2).ToString()}");
Debug.Print($"Equal HashCodes = {(parent.GetHashCode()==parent2.GetHashCode()).ToString()}");
System.Array adp = (System.Array)path.ArrayData;
string adpstr = adp.GetValue(1).ToString();
for (int j = 1; j != adp.Length-1; j++)
adpstr = adpstr + "/" + adp.GetValue(j).ToString();
if (parentsPaths.Contains(adpstr))
Debug.Print($"Already found parent: {parent.UserName}");
else
parentsPaths.Add(adpstr);
}
PPS: I hacked this quickly, I guess saving the sub SystemArray and comparing it would probably be more efficient than concatenating strings and comparing their hash code via a HashSet 😉
PS: Another option would be to convert the parent path back into a ModelItem but this would defeat the purpose of voiding ModelItems in the first place.