I already had a blog post on Hook up a chain using iMate's, but I was recently asked about more iMate related API samples, so I thought I could also demonstrate the usage of iMate MatchList.
In theory, when using a MatchList, the iMates in the various components should be matched automatically when using the "Automatically generate iMates on place" option in the "Place Component" dialog, based on the names provided in the list. I did not realize that they over-match 😬
(i.e. if there are unresolved/unpaired iMates left then they will be matched even if there is no appropriate name in the MatchList)
Inventor Idea Station: Match list for imates
This is what I thought of doing as a test:
We have 4 parts based on 2 types of models: a and b. There will be four connection points as shown in the above image. So we'll have an a type part with connections for points 1 and 2 named chain_a_1-2.ipt, one b type part with connections for point 2 and 3 named chain_b_2-3.ipt, etc
iMates will be named following this pattern: "<iMate type [Insert or Mate]><connection point number [1..4]><part type [a or b]>", e.g. Insert2b
Each iMate will have a MatchList containing the same iMate type for the same connection point but for the opposite part type:
Insert1a will be matching Insert1b, and Insert1b will be matching nothing, etc
Unfortunately, as I mentioned above, simply relying on the "Automatically generate iMates on place" option in the "Place Component" dialog will not work as it will also match Insert1a to Insert3b and Mate1a to Mate3b when adding the second part to the assembly.
Instead, we can just place all the components in the assembly at the same time without automatic iMate resolution and then use the API to match the iMates.
Here is the VBA code I used - if you want to use .NET / iLogic instead have a look at Convert VBA to .NET / iLogic
Function GetAlliMates(cd As AssemblyComponentDefinition) As NameValueMap Dim res As NameValueMap Set res = ThisApplication.TransientObjects.CreateNameValueMap Dim occ As ComponentOccurrence For Each occ In cd.Occurrences Dim imate As iMateDefinition For Each imate In occ.iMateDefinitions Call res.Add(imate.name, imate) Next Next Set GetAlliMates = res End Function Function MatchiMate( _ cd As AssemblyComponentDefinition, _ imate As iMateDefinition, _ imates As NameValueMap, _ ByVal name As String) As Boolean On Error Resume Next Dim imateMatch As iMateDefinition Set imateMatch = imates.item(name) If Not imateMatch Is Nothing Then Call cd.iMateResults.AddByTwoiMates(imate, imateMatch) Debug.Print "Matching " + imate.name + " with " + imateMatch.name + " // " + Err.Description End If MatchiMate = (Err.Number = 0) On Error GoTo 0 End Function Sub HookTheChain() Dim doc As AssemblyDocument Set doc = ThisApplication.ActiveDocument Dim cd As AssemblyComponentDefinition Set cd = doc.ComponentDefinition Dim imates As NameValueMap Set imates = GetAlliMates(cd) Dim imate As iMateDefinition For Each imate In imates Dim item As Variant For Each item In imate.MatchList If MatchiMate(cd, imate, imates, item) Then Exit For End If Next Next End Sub
When the code finishes, the parts will be on top of each other - I described the same thing in the other article.
Best thing is to ground one of the components and then you can move around the others so they come apart and end up like shown in the picture on the top.
The above code only works well if inside the assembly each iMate has a unique name and should only be matched with a specific other iMate.
Here is the Inventor 2020 model I used: Download Chain_with_MatchList