Find Occurrences based on Attribute-sets

Find Occurrences based on Attribute-sets

vandrakonZ
Participant Participant
447 Views
5 Replies
Message 1 of 6

Find Occurrences based on Attribute-sets

vandrakonZ
Participant
Participant

Hello community,

 

I'm facing an issue to identify / find the occurrences to the corresponding attribute sets.

I'm looking for the following:

- find all objects (occurrences) inside an assembly containing a certain Attribute "myAttribute"

- get the value of this attribute for each object.

--> output a list of objects containing the values of "myAttribute"

 

first way I tried, where I'm facing issues is:

to find inside an assembly all objects which contains a certain attribute name by:

Inventor.AttributesEnumerator allAttributes = attributeManager.FindAttributes("*", "myAttribute");

 

Now by iterating through this enumeration I'm able to get the values of this attributes and to identify the attribute set of each attribute. Now I would like to get also the corresponding occurrence object. but How?

 

Second way which is working but very slow is to find first all objects containing a certain attribute by:

Inventor.ObjectCollection allObjects = attributeManager. FindObjects("*", "myAttribute");

 

There I can iterate through all object and inside through all attribute sets to get the value of the attribute "myAttribute". 

--> this way is working but it takes lot of time to iterate through a big assembly.

 

Any suggestion how get a list of object with a certain attribute and its values in a efficient way is highly welcome.

 

Many thanks,

0 Likes
Accepted solutions (2)
448 Views
5 Replies
Replies (5)
Message 2 of 6

WCrihfield
Mentor
Mentor
Accepted solution

Hi @vandrakonZ.  When using the FindAttributes method, and obtaining an AttributesEnumerator, it sounds like you know how to use Attribute.Parent to get a reference to its parent AttributeSet object.  But after that point, the AttributeSet also has a Parent property.  However, that property will either return the parent object that this AttibuteSet is attached to, or it will return an ObjectCollection with multiple Inventor objects within it that have the same named AttributeSet attached to them.  That's the catch that trips up the process for most folks.  If your goal is truly to obtain a list of all the Objects in a list, then it would seem like the FindObjects method would be the best starting route, even if it might take a little longer to process.  When iterating through the ObjectCollection it returns, we already know that the object will have at least 1 AttributeSet that will contain an Attribute with that specified name.  In a case like this, where you want not just a simple list of objects, but a list in which you know what the value of those attributes are for each of those objects, I think a List(Of KeyValuePair(Of Object, String)) would be useful.  Assuming of course that the Value of the attribute is a String, and not one of the other available data types.

Below is an example iLogic rule using this technique, and reports its findings to the iLogic Log window at the end.  You can change that report process to something more useful if the main process works better for you.

Dim oDoc As Inventor.Document = ThisDoc.Document
Dim oAttMgr As Inventor.AttributeManager = oDoc.AttributeManager
Dim sAttName As String = "myAttribute"
Dim oColl As Inventor.ObjectCollection = oAttMgr.FindObjects("*", sAttName)
If oColl Is Nothing OrElse oColl.Count = 0 Then
	Logger.Debug("No Objects found with that Attribute name.")
	Return
End If
Dim oKeyValueList As New List(Of KeyValuePair(Of Object, String))
For Each oObj In oColl
	Dim oSets As Inventor.AttributeSets = oObj.AttributeSets
	If oSets Is Nothing OrElse oSets.Count = 0 Then Continue For
	For Each oSet As Inventor.AttributeSet In oSets
		If oSet.NameIsUsed(sAttName) = True Then
			Dim oAtt As Inventor.Attribute = oSet.Item(sAttName)
			Dim sVal As String = oAtt.Value.ToString
			oKeyValueList.Add(New KeyValuePair(Of Object, String)(oObj, sVal))
			Exit For
		End If
	Next 'oSet
Next 'oObj
Logger.Info(oKeyValueList.Count.ToString & " Object & Attribute Value pairs found.")
For Each oPair In oKeyValueList
	Logger.Info("Object Type = " & TypeName(oPair.Key) & vbCrLf & _
	"Attribute Value = " & oPair.Value & vbCrLf)
Next

If this solved your problem, or answered your question, please click ACCEPT SOLUTION .
Or, if this helped you, please click (LIKE or KUDOS) 👍.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 3 of 6

Michael.Navara
Advisor
Advisor
Accepted solution

I don't know how big is your assembly, but I test this code and the duration of extraction process is in milliseconds (about 40 ms).

In attachment is testing assembly with two rules.

 

BuildOccurrences rule creates 1000 occurrences of one ipt file and assign attributes to them. AttributeSet name is "Position" and Attribute name is "Origin". Value is x,y,z coordinates of occurrent in [cm] 

GetOccurrences rule finds all occurrences with attribute "Origin" and prints occurrence name and value of the attribute to the iLogic log console.

 

BuildOccurrences

 

Dim asm As AssemblyDocument = ThisDoc.Document
Dim fileName As String = System.IO.Path.ChangeExtension(asm.FullFileName, ".ipt")
ThisApplication.StatusBarText = "Please Wait ..."
ThisApplication.ScreenUpdating = False
Dim t As Transaction = ThisApplication.TransactionManager.StartTransaction(asm, "Build occurrences")
For x = 0 To 9
	For y = 0 To 9
		For z = 0 To 9
			Dim mtx As Matrix = ThisApplication.TransientGeometry.CreateMatrix
			mtx.Cell(1, 4) = x
			mtx.Cell(2, 4) = y
			mtx.Cell(3, 4) = z
			Dim occ = asm.ComponentDefinition.Occurrences.Add(fileName, mtx)
			Dim attSet = occ.AttributeSets.Add("Position")
			attSet.Add("Origin", ValueTypeEnum.kStringType, String.Format("{0},{1},{2}", x, y, z))
		Next
	Next
Next
t.End	
ThisApplication.ScreenUpdating = True
ThisApplication.ActiveView.Update

 

 

GetOccurrences

 

Dim asm As AssemblyDocument = ThisDoc.Document
Dim start = DateTime.Now()

Dim objs = asm.AttributeManager.FindObjects(AttributeName :="Origin")
Dim atts = asm.AttributeManager.OpenAttributeSets(objs,"Position")

Dim duration As TimeSpan = DateTime.Now - start
Logger.Debug(duration.TotalMilliseconds)
Logger.Debug(objs.Count)
Logger.Debug(atts.Count)

Dim strBuilder As New System.Text.StringBuilder

For i = 1 To objs.Count
	Dim occ As ComponentOccurrence = objs(i)
	Dim attSet As Inventor.AttributeSet = atts(i)
	strBuilder.AppendFormat("{0} - [{1}]{2}", occ.Name, attSet("Origin").Value, vbCrLf)
Next
Logger.Debug(strBuilder.ToString)

 

 

Message 4 of 6

vandrakonZ
Participant
Participant

Hi @WCrihfield ,

 

thanks for the solution. I have already implemented the path using the "FindObjects()" in the same way as you have proposed. And this ways is unfortunately really slow. I have an assembly with ca. 2000 occurrences and several attribute sets in each of the occurrences.

 

the second way going by "FindAttributes()" and then go over it parents and parents.parents didn't work for me. 

Now, I know why. You explanation "However, that property will either return the parent object that this AttibuteSet is attached to, or it will return an ObjectCollection with multiple Inventor objects within it that have the same named AttributeSet attached to them." was realy helpful.

 

Many thanks.

 

0 Likes
Message 5 of 6

vandrakonZ
Participant
Participant

Hi @Michael.Navara ,

 

many thanks for your solution.

It was exactly what I was looking for. Now, I was able to reduce the need time from 4-5 min. down to 25 sec.

 

At the end it was the combination your solution and of the solution from the @WCrihfield ...

 

Many thanks to both.

 

 

 

0 Likes
Message 6 of 6

WCrihfield
Mentor
Mentor

The example that @Michael.Navara showed is using that extra method that I forgot about (AttributeManager.OpenAttributeSets), which really helps cut down on processing time.  Nice catch Michael. 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes