Making a virtual component with solid body copies from all other components
-
- Posts: 6
- Joined: Tue May 11, 2021 9:39 am
- x 1
Making a virtual component with solid body copies from all other components
Hi,
I am trying to write a macro that goes through the assembly, collects all solid bodies from all the components, then creates a virtual part inside the assembly, and places copies of all these solid bodies into that virtual part as temporary bodies. I need the temporary bodies in that virtual part to be in the exact same position as they are in the top-level assembly. Problem is, when I call Body2.Copy on bodies of components that are not inserted at the origin in the top-level assembly or the sub-assemblies, the position of the resulting temporary bodies in the virtual component do not match the original body positions in the top-level assembly.
I know I could call on Transform2 to get transform matrices from all the components, reverse them, and then use ApplyTransform on the temporary bodies to move them back to the original position as it is in the top-level assembly, but ApplyTransform really hurts the performance. Also, it is damn complicated when there are many levels of sub-assemblies, and each of them might have their own transform matrices that have to be combined together in order to get that temporary body back into it's right place in the virtual component.
Basically what I want is like Save Assembly As Part, but only saving solid bodies to a virtual part at the top-level assembly, preserving their current positions.
Any advice on the best way to do this?
I am trying to write a macro that goes through the assembly, collects all solid bodies from all the components, then creates a virtual part inside the assembly, and places copies of all these solid bodies into that virtual part as temporary bodies. I need the temporary bodies in that virtual part to be in the exact same position as they are in the top-level assembly. Problem is, when I call Body2.Copy on bodies of components that are not inserted at the origin in the top-level assembly or the sub-assemblies, the position of the resulting temporary bodies in the virtual component do not match the original body positions in the top-level assembly.
I know I could call on Transform2 to get transform matrices from all the components, reverse them, and then use ApplyTransform on the temporary bodies to move them back to the original position as it is in the top-level assembly, but ApplyTransform really hurts the performance. Also, it is damn complicated when there are many levels of sub-assemblies, and each of them might have their own transform matrices that have to be combined together in order to get that temporary body back into it's right place in the virtual component.
Basically what I want is like Save Assembly As Part, but only saving solid bodies to a virtual part at the top-level assembly, preserving their current positions.
Any advice on the best way to do this?
- mattpeneguy
- Posts: 1386
- Joined: Tue Mar 09, 2021 11:14 am
- x 2489
- x 1899
Re: Making a virtual component with solid body copies from all other components
This is interesting. Care to post the code you've got so far?
Hey @josh, @artem, and @gupta9665 do you have any pointers?
Hey @josh, @artem, and @gupta9665 do you have any pointers?
-
- Posts: 6
- Joined: Tue May 11, 2021 9:39 am
- x 1
Re: Making a virtual component with solid body copies from all other components
Sure thing! Here is what I got (in VB.NET):mattpeneguy wrote: ↑Tue May 11, 2021 10:38 am This is interesting. Care to post the code you've got so far?
Code: Select all
Function main()
Dim components As List(Of Component2) = GetPartComponentDocs(assemblyDoc) 'Get components which will be searched for solid bodies
Dim virtualComponent As Component2 = InsertVirtualComponent(assemblyDoc) 'Create new virtual component in top-level assembly
Dim bodiesInVirtualComponent as List(of Body2) = CopyBodiesAsTempBodiesToVirtualComponent(virtualComponent, components, assemblyDoc) 'Create temporary bodies in virtual component, and store their reference
End Function
'Get references to components that are parts
Function GetPartTypeComponents(swDoc As AssemblyDoc) As List(Of Component2)
Dim partTypeComponents As New List(Of Component2)
Dim allComponents() As Object = swDoc.GetComponents(False)
For Each component As Component2 In allComponents
Console.WriteLine(component.GetChildren().Length)
If component.GetChildren().Length < 1 Then
partTypeComponents .Add(component)
End If
Next
Return partTypeComponents
End Function
'Create a new component in the top-level assembly and get it's reference
Function InsertVirtualComponent(assemblyDoc As AssemblyDoc) As Component2
Dim virtualComponent As Component2 = Nothing
Dim status As Integer = assemblyDoc.InsertNewVirtualPart(Nothing, virtualComponent)
If status = 1 Then
Return virtualComponent
Else
Return Nothing
End If
End Function
'Wrapper class that stores component along with all the transform matrices from all the parent assemblies
Class ComponentWithMatrixes
Public componentDoc As Component2
Public matrixes As New List(Of MathTransform)
Sub New(_componentDoc As Component2)
componentDoc = _componentDoc
End Sub
End Class
'Find and copy solid bodies from provided component list to a virtual part as temporary bodies, preserving their positions
Function CopyBodiesAsTempBodiesToVirtualComponent(virtualComponent As Component2, PartComponents As List(Of Component2)) As List(Of Body2)
Dim partComponentsWithMatrixes As New List(Of ComponentWithMatrixes)
Dim temporaryBodiesList as new List(of Body2)
'Traverse up from each part-type component in the assembly and collect it's transform matrices
For Each partComponent In PartComponents
Dim partComponentWithMatrixes As New ComponentWithMatrixes(PartComponent)
partComponentWithMatrixes.matrixes.Add(PartComponent.Transform2)
partComponentsWithMatrixes.Add(PartComponentWithMatrixes)
Dim parentComponentToParse As Component2 = partComponent.GetParent()
Do While parentComponentToParse IsNot Nothing
partComponentWithMatrixes.matrixes.Add(parentComponentToParse.Transform2)
parentComponentToParse = parentComponentToParse.GetParent
If parentComponentToParse Is Nothing Then Exit Do
Loop
Next
'Create bodies by copying them from each part component, and move them to the original location using the stored transform matrices
For Each partComponentWithMatrixes In partComponentsWithMatrixes
Dim componentBodies As Object = partComponentWithMatrixes.componentDoc.GetBodies3(swBodyType_e.swSolidBody, False)
If componentBodies IsNot Nothing Then
For Each componentBody As Body2 In componentBodies
Dim newBody As Body2 = virtualComponent.GetModelDoc2.CreateNewBody()
newBody = componentBody.Copy()
For Each matrix In partComponentWithMatrixes.matrixes '.ToArray.Reverse()
newBody.ApplyTransform(matrix)
newBody.Display3(modelDoc, Information.RGB(255, 0, 0), 1)
Next
temporaryBodiesList.Add(newBody)
Next
End If
Next
End Function
But anyway, I am pretty sure that this isn't the right way to go about it, right? This is way too slow. Surely Save Assembly As Part doesn't do it by transforming the solid body positions like this?
EDIT: Surprisingly, I just discovered that there is actually no need to collect all the transform matrices - the transform matrix of the part component seems to have all the other matrices combined into it, so there is just one ApplyTransform call needed per body. Which is really weird... But alright. Still, I don't think this is the right way to go about copying solid bodies into a vritual component...
- mattpeneguy
- Posts: 1386
- Joined: Tue Mar 09, 2021 11:14 am
- x 2489
- x 1899
Re: Making a virtual component with solid body copies from all other components
I can pick apart VBA and sometimes make it do what I want. VB.net and C# give me a headache when I try to figure it out. Hopefully one of the three I pinged will come along and help.
-
- Posts: 6
- Joined: Tue May 11, 2021 9:39 am
- x 1
Re: Making a virtual component with solid body copies from all other components
Well it's super simple in this case. I added plenty of comments to make it even simpler to understandmattpeneguy wrote: ↑Tue May 11, 2021 3:01 pm I can pick apart VBA and sometimes make it do what I want. VB.net and C# give me a headache when I try to figure it out. Hopefully one of the three I pinged will come along and help.
- mattpeneguy
- Posts: 1386
- Joined: Tue Mar 09, 2021 11:14 am
- x 2489
- x 1899
Re: Making a virtual component with solid body copies from all other components
I saw your comments and that's really nice. The problem I have is if I try to modify VB.net, I have real trouble because I just don't have enough experience with the calls and structure. I "have a feel" for VBA.Justinas Rubinovas wrote: ↑Tue May 11, 2021 3:24 pm Well it's super simple in this case. I added plenty of comments to make it even simpler to understand
-
- Posts: 6
- Joined: Tue May 11, 2021 9:39 am
- x 1
Re: Making a virtual component with solid body copies from all other components
Alright, then let's wait for the cavalry to show up. Thanks for tagging them, I'm really looking forward to some comments.
Re: Making a virtual component with solid body copies from all other components
You do not need to reverse the transform rather use direct IComponent2::Transform2. Also, you do not need to apply sub-assemblies transform, if you get your component from the root level the transform will be related to the top assembly coordinate system regardless of the level of the component. Then you do IBody2::ApplyTransform - this should not hurt performance that much, then you can call IPartDoc::CreateFeatureFromBody.Justinas Rubinovas wrote: ↑Tue May 11, 2021 10:22 am Hi,
I am trying to write a macro that goes through the assembly, collects all solid bodies from all the components, then creates a virtual part inside the assembly, and places copies of all these solid bodies into that virtual part as temporary bodies. I need the temporary bodies in that virtual part to be in the exact same position as they are in the top-level assembly. Problem is, when I call Body2.Copy on bodies of components that are not inserted at the origin in the top-level assembly or the sub-assemblies, the position of the resulting temporary bodies in the virtual component do not match the original body positions in the top-level assembly.
I know I could call on Transform2 to get transform matrices from all the components, reverse them, and then use ApplyTransform on the temporary bodies to move them back to the original position as it is in the top-level assembly, but ApplyTransform really hurts the performance. Also, it is damn complicated when there are many levels of sub-assemblies, and each of them might have their own transform matrices that have to be combined together in order to get that temporary body back into it's right place in the virtual component.
Basically what I want is like Save Assembly As Part, but only saving solid bodies to a virtual part at the top-level assembly, preserving their current positions.
Any advice on the best way to do this?
Thanks,
Artem
xarial.com - making your CAD better
codestack.net - SOLIDWORKS API macros and tutorials
Artem
xarial.com - making your CAD better
codestack.net - SOLIDWORKS API macros and tutorials
-
- Posts: 6
- Joined: Tue May 11, 2021 9:39 am
- x 1
Re: Making a virtual component with solid body copies from all other components
Thank you for your comment, Artem. That is what I am doing in my latest code, calling Transform2 once on that component from the root level, and then calling ApplyTransform on the copied body. Still, is this really the way how the Save Assembly As Part works in the backstage..? Isn't there a more direct approach to get all the solid bodies from the assembly into one part?artem wrote: ↑Tue May 11, 2021 7:35 pm You do not need to reverse the transform rather use direct IComponent2::Transform2. Also, you do not need to apply sub-assemblies transform, if you get your component from the root level the transform will be related to the top assembly coordinate system regardless of the level of the component. Then you do IBody2::ApplyTransform - this should not hurt performance that much, then you can call IPartDoc::CreateFeatureFromBody.
Re: Making a virtual component with solid body copies from all other components
This seems very roundabout... Why not actually save the dang assembly as a part, insert to assembly, and then make it virtual? Same end result, right?
-
- Posts: 6
- Joined: Tue May 11, 2021 9:39 am
- x 1
Re: Making a virtual component with solid body copies from all other components
Possible, but in the end, I need these bodies as temporary bodies in the virtual component in that assembly, so after this saving, inserting, making virtual, I would still need to copy all these bodies again... So basically it would be copying bodies twice, first with Save Assembly as Part, and then with Body.Copy. I don't suppose that would be any faster...
Re: Making a virtual component with solid body copies from all other components
Yeah, brain fart. I forgot about the temporary thing.