Making a virtual component with solid body copies from all other components

Programming and macros
Justinas Rubinovas
Posts: 6
Joined: Tue May 11, 2021 9:39 am
Answers: 0
x 1

Making a virtual component with solid body copies from all other components

Unread post by Justinas Rubinovas »

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?
User avatar
mattpeneguy
Posts: 1380
Joined: Tue Mar 09, 2021 11:14 am
Answers: 4
x 2487
x 1888

Re: Making a virtual component with solid body copies from all other components

Unread post by mattpeneguy »

This is interesting. Care to post the code you've got so far?
Hey @josh, @artem, and @gupta9665 do you have any pointers?
Justinas Rubinovas
Posts: 6
Joined: Tue May 11, 2021 9:39 am
Answers: 0
x 1

Re: Making a virtual component with solid body copies from all other components

Unread post by Justinas Rubinovas »

mattpeneguy wrote: Tue May 11, 2021 10:38 am This is interesting. Care to post the code you've got so far?
Sure thing! Here is what I got (in VB.NET):

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

This code is an attempt to create these temporary bodies, get all the transform matrices up the assembly hierarchy, and apply them to every body to move it back to it's correct location in that virtual component. It is slow as hell, and not very reliable either - it usually works on the first build with a fresh assembly, but sometimes the resulting temporary bodies result in totally weird places, not coinciding with the original bodies. I am not sure why that happens, still trying to figure it out...

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...
User avatar
mattpeneguy
Posts: 1380
Joined: Tue Mar 09, 2021 11:14 am
Answers: 4
x 2487
x 1888

Re: Making a virtual component with solid body copies from all other components

Unread post by mattpeneguy »

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.
Justinas Rubinovas
Posts: 6
Joined: Tue May 11, 2021 9:39 am
Answers: 0
x 1

Re: Making a virtual component with solid body copies from all other components

Unread post by Justinas Rubinovas »

mattpeneguy 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.
Well it's super simple in this case. I added plenty of comments to make it even simpler to understand :)
User avatar
mattpeneguy
Posts: 1380
Joined: Tue Mar 09, 2021 11:14 am
Answers: 4
x 2487
x 1888

Re: Making a virtual component with solid body copies from all other components

Unread post by mattpeneguy »

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 :)
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
Posts: 6
Joined: Tue May 11, 2021 9:39 am
Answers: 0
x 1

Re: Making a virtual component with solid body copies from all other components

Unread post by Justinas Rubinovas »

Alright, then let's wait for the cavalry to show up. Thanks for tagging them, I'm really looking forward to some comments.
artem
Posts: 26
Joined: Thu Mar 18, 2021 1:31 pm
Answers: 3
x 9
x 73

Re: Making a virtual component with solid body copies from all other components

Unread post by artem »

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?
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.
Thanks,
Artem
xarial.com - making your CAD better
codestack.net - SOLIDWORKS API macros and tutorials
Justinas Rubinovas
Posts: 6
Joined: Tue May 11, 2021 9:39 am
Answers: 0
x 1

Re: Making a virtual component with solid body copies from all other components

Unread post by Justinas Rubinovas »

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.
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?
User avatar
josh
Posts: 263
Joined: Thu Mar 11, 2021 1:05 pm
Answers: 11
x 19
x 453

Re: Making a virtual component with solid body copies from all other components

Unread post by josh »

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?
Justinas Rubinovas
Posts: 6
Joined: Tue May 11, 2021 9:39 am
Answers: 0
x 1

Re: Making a virtual component with solid body copies from all other components

Unread post by Justinas Rubinovas »

josh wrote: Wed May 12, 2021 4:19 pm 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?
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...
User avatar
josh
Posts: 263
Joined: Thu Mar 11, 2021 1:05 pm
Answers: 11
x 19
x 453

Re: Making a virtual component with solid body copies from all other components

Unread post by josh »

Yeah, brain fart. I forgot about the temporary thing.
Post Reply