Almost six years later and derive components via API is STILL painfully slow
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hi all,
I recently had cause to revisit some VB.NET Inventor API code I originally wrote back in 2016(!) and, despite the recent advances in multi-core use within Inventor, having just run the code again, it still seems just as slow as when I wrote it. (FULL disclosure: If my memory serves, in 2016 this same code took ~10 minutes to process one assembly; Here in 2022 the outputs take ~7 minutes - so it IS a little faster than it was)
Am I misunderstanding how I should use the API for this? The reason I ask that is because with the file in question (containing 46 Solid bodies) takes < 30 seconds to produce the same number of derived components.
Here is the method that carries out the bulk of the process:
Sub BuildandPlaceSurfaceBodies(ByVal ThisPart As PartDocument, ByVal ResultsFolder As String, ByVal Thispartname As String, ByVal IsMirrored As Boolean, ByRef ThisAssembly As AssemblyDocument, _
ByRef PanelACollection As ObjectCollection, ByRef PanelBCollection As ObjectCollection, ByRef PanelCCollection As ObjectCollection, _
ByRef PanelDCollection As ObjectCollection, ByVal NumRightSpinesCount As String, ByVal thisbalcony As Balcony)
Try
'base work axes
Dim XAxis As WorkAxis
Dim YAxis As WorkAxis
Dim Zaxis As WorkAxis
With ThisAssembly.ComponentDefinition
XAxis = .WorkAxes(1)
YAxis = .WorkAxes(2)
Zaxis = .WorkAxes(3)
End With
'base work planes
Dim XYPlane As WorkPlane = Nothing
Dim YZPlane As WorkPlane = Nothing
Dim XZPlane As WorkPlane = Nothing
With ThisAssembly.ComponentDefinition
XYPlane = .WorkPlanes.Item("XY Plane")
YZPlane = .WorkPlanes.Item("YZ Plane")
XZPlane = .WorkPlanes.Item("XZ Plane")
End With
For i As Integer = 1 To ThisPart.ComponentDefinition.SurfaceBodies.Count
Dim surfacebody As SurfaceBody = ThisPart.ComponentDefinition.SurfaceBodies.Item(i)
Dim surfaceBodyName As String = surfacebody.Name
If surfaceBodyName.StartsWith("Solid") Or surfaceBodyName.Contains("Source") Then
Continue For
End If
Dim partdocument As PartDocument = g_inventorApplication.Documents.Add(DocumentTypeEnum.kPartDocumentObject, g_inventorApplication.FileManager.GetTemplateFile(DocumentTypeEnum.kPartDocumentObject))
Dim p As Inventor.Property = partdocument.PropertySets("{32853F0F-3444-11D1-9E93-0060B03C1CA6}")("Description")
p.Expression = surfaceBodyName
Dim derivedpartcomponents As DerivedPartComponents = partdocument.ComponentDefinition.ReferenceComponents.DerivedPartComponents
Dim derivedpartuniformscaledefinition As DerivedPartUniformScaleDef = derivedpartcomponents.CreateUniformScaleDef(ThisPart.FullDocumentName)
Dim derivedpartentity As DerivedPartEntity
For Each derivedpartentity In derivedpartuniformscaledefinition.Solids
If Not derivedpartentity.ReferencedEntity Is surfacebody Then
derivedpartentity.IncludeEntity = False
Else
derivedpartentity.IncludeEntity = True
End If
Next
' theory copied from here: http://adndevblog.typepad.com/manufacturing/2012/06/includeexclude-parameters-from-the-base-part-in-a-derived-part.html
Dim paramtoderive As DerivedPartEntity
For Each paramtoderive In derivedpartuniformscaledefinition.Parameters
paramtoderive.IncludeEntity = True
Next
Call derivedpartcomponents.Add(derivedpartuniformscaledefinition)
If surfaceBodyName.Contains("Panel") Then
SetMaterialToPart(partdocument, My.Settings.BalconyPanelMaterialName)
Else
SetMaterialToPart(partdocument, My.Settings.BalconyAluMaterialName)
End If
Dim newfilename As String = Regex.Replace(surfaceBodyName, "([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))", "$1 ")
Call partdocument.SaveAs(ResultsFolder + Thispartname + "-" + newfilename + ".ipt", False)
If IsMirrored Then
MirrorDerivedPart(partdocument, DerivedPartMirrorPlaneEnum.kDerivedPartMirrorPlaneYZ)
End If
Dim mx As Matrix = g_inventorApplication.TransientGeometry.CreateMatrix()
Dim oOcc1 As ComponentOccurrence = ThisAssembly.ComponentDefinition.Occurrences.AddByComponentDefinition(partdocument.ComponentDefinition, mx)
If surfaceBodyName = "C3" Then
Dim objCol As ObjectCollection = g_inventorApplication.TransientObjects.CreateObjectCollection
objCol.Add(oOcc1)
'Based on this:
' http://adndevblog.typepad.com/manufacturing/2012/12/inventor-create-pattern-of-component-occurrences.html
Call ThisAssembly.ComponentDefinition.OccurrencePatterns.AddRectangularPattern(objCol,
YAxis,
True,
Parameters.GetParameter(My.Settings.BalconyCSpacingParameterName).Expression,
My.Settings.BalconyChannelsCount)
ElseIf surfaceBodyName = "Fin" Then
Dim objCol As ObjectCollection = g_inventorApplication.TransientObjects.CreateObjectCollection
objCol.Add(oOcc1)
Call ThisAssembly.ComponentDefinition.OccurrencePatterns.AddRectangularPattern(objCol, YAxis, True, Parameters.GetParameter(My.Settings.BalconyCSpacingParameterName).Expression, My.Settings.BalconyFinsCount)
ElseIf surfaceBodyName.Contains("Panel") Then
If surfacebody.Name.StartsWith("PanelA") Then
PanelACollection.Add(oOcc1)
ElseIf surfacebody.Name.StartsWith("PanelB") Then
PanelBCollection.Add(oOcc1)
ElseIf surfacebody.Name.StartsWith("PanelC") Then
PanelCCollection.Add(oOcc1)
ElseIf surfacebody.Name.StartsWith("PanelD") Then
PanelDCollection.Add(oOcc1)
End If
ElseIf surfaceBodyName = "SpineConnectingPlateRight" Or surfaceBodyName = "SpineConnectingPlateLeft" Then
Dim objCol As ObjectCollection = g_inventorApplication.TransientObjects.CreateObjectCollection
objCol.Add(oOcc1)
Call ThisAssembly.ComponentDefinition.OccurrencePatterns.AddRectangularPattern(objCol, YAxis, True, Parameters.GetParameter(My.Settings.BalconyPanelDSpineFixingHoleParamName).Expression, My.Settings.BalconyConnectingPlateCount)
ElseIf surfaceBodyName = "ShortSpineC" Then
If thisbalcony.NumPanels > 3 Then
Dim objCol As ObjectCollection = g_inventorApplication.TransientObjects.CreateObjectCollection
objCol.Add(oOcc1)
Dim rectangpattern As RectangularOccurrencePattern = ThisAssembly.ComponentDefinition.OccurrencePatterns.AddRectangularPattern(objCol, XAxis, False, Parameters.GetParameter(My.Settings.T1BalconyShortSpineXSpacingParamName).Expression, 2)
Dim rectangColl2 As ObjectCollection = g_inventorApplication.TransientObjects.CreateObjectCollection
End If
ElseIf surfaceBodyName = "ShortSpineLeft" Or surfaceBodyName = "ShortSpineRight" Then
Dim objCol As ObjectCollection = g_inventorApplication.TransientObjects.CreateObjectCollection
objCol.Add(oOcc1)
Call ThisAssembly.ComponentDefinition.OccurrencePatterns.AddRectangularPattern(objCol, YAxis, True, Parameters.GetParameter(My.Settings.T1BalconySpineFixingHoleParamName).Expression, My.Settings.BalconyConnectingPlateCount)
ElseIf surfaceBodyName = "LongSpineB1" Then
MirrorPartInAssy(ThisAssembly, YZPlane, oOcc1) 'workplanes.item(1) = YZ
End If
Call partdocument.Close()
Next
Catch ex As Exception
MessageBox.Show("Error info: " & vbNewLine & ex.ToString)
End Try
End Sub
Can this run in a parallel fashion..? Is there a different method I can use..?
Thanks,
Alex.
{Edit: to tidy the code a little}
Alex Fielder
Inventor Expert
https://github.com/alexfielder/
LinkedIn - Github Inventor Extension Server - Bonkers polygon iLogic thing
Top ten iLogic Tips - API Shortcut In Google Chrome - Assembly Extrusion Example