Convert an assembly to a standalone file

Hello @Rim-b
Excellent!! But not perfect... This is exactly the expected end result, except for the placement.

I insert a sheet metal part into the host sheet metal part, but I can't position it as desired. Is it possible to rotate the inserted sheet metal or are we limited to translation during insertion only?

The initial idea of going through an assembly was mainly to make the positioning simple, before it all ended up in a loan.

Hello

No, there are assembly functions (move with constraints).
But quite frankly, it's a gas factory, seen from my window, what you're trying to do.
You have to choose the right mode at startup (assembly or part within part) because "converting" afterwards is hours and hours of work. I'm not even sure that a macro can do it without generating positioning errors or at least will have to spend hours on this type of development.

2 Likes

I often use the insert part function and I confirm your dir cyril, the thing jumps at the slightest change in the tree sw doesn't like to play too much with the recovery bar,
For the copy of a function with macro I don't think either, I don't see how you can modify a hole or a removal of blind material or through everything without affecting the other bodies!

3 Likes

Hello

Inserting a part within a part works. On the other hand, if you have more than a dozen parts, it can very quickly be a hassle to manage. If you want it to work, the best thing to do is to probably not use constraints when inserting parts, but only positions.
A possible solution would perhaps be to make groupings of pieces that go together (so make sub-pieces) and then to insert a dozen pieces in a room.

NB: In terms of reconstruction, it may be difficult to manage in any case.

1 Like

Yes, I confirm and it's quite penalizing when a customer sends you an ASM in STEP format for example or other neutral format to make you do an RDM simulation. Not to mention that you lose all the constraints in the process.

Good luck :cold_face:

2 Likes

Hello.
Thank you all for your very informative answers!

So, I tested the insertion of a part in a part, the file weighs 2 times less than an assembly with the same part made virtual.
The fact that the weight goes from double to single is not negligible.

However, reading this topic, I have the impression that virtualizing the parts in an assembly remains by far the simplest, most practical and flexible solution.
What a shame that the file weighs twice as much...
The pee trick is indeed an interesting possibility, @froussel

Checking in lapi, it seems to me that it's playable:

  1. Browse the components one by one

  2. Retrieve the position and orientation of the component relative to the assembly origin.

  3. Insert the component into a part and break the link.

  4. Detecting new bodies (a bit of a headache!) .

  5. Apply orientation and displacement to these new bodies

By breaking the link, the functions of the inserted part are recovered in the tree, the miracle is that SW only applies them to new bodies (it modifies the definition and action areas of all bodies to an automatic😀 selection) which avoids the problem I mentioned earlier, so the link is broken the tree and stable,

The only bimol I find is that these bodies are positioned in relation to the part origin not by stress interactions.
Not to say that the tree structure will be very very long depending on the number of components and their complexities

3 Likes

If attached a description of the points
(thanks to @Rim-b who mentioned the main function)






Assemblage1.zip (355.9 KB)

Option Explicit

Dim swApp As Object
Dim swmodel As ModelDoc2
Dim swpart As PartDoc
Dim swassembly As AssemblyDoc
Dim swMathUtils As SldWorks.MathUtility
Dim featmgr As FeatureManager
Dim pbodies As Variant
Dim selmgr As SelectionMgr
Const PI As Double = 3.14159265359


Sub main()

    Set swApp = Application.SldWorks
    Set swMathUtils = swApp.GetMathUtility
    Set swassembly = swApp.ActiveDoc
    Set swmodel = swApp.NewDocument("C:\ProgramData\SOLIDWORKS\SOLIDWORKS 2022\templates\Pièce.PRTDOT", 0, 0, 0)
    Set swpart = swmodel
    Set featmgr = swmodel.FeatureManager
    Set selmgr = swmodel.SelectionManager
    Dim comp As Component2
    Dim vcomp As Variant, vc As Variant
    vcomp = swassembly.GetComponents(False)
        
    For Each vc In vcomp
        Set comp = vc
        Dim pos As Variant
        pos = get_position(comp)
        
        pbodies = swpart.GetBodies2(0, False)
        swpart.InsertPart3 comp.GetPathName, 512, comp.ReferencedConfiguration()
        select_bodies get_bodies(swpart, pbodies)
        featmgr.InsertMoveCopyBody2 0, 0, 0, 0, 0, 0, 0, pos(5), pos(4), pos(3), False, 1
        
        select_bodies get_bodies(swpart, pbodies)
        featmgr.InsertMoveCopyBody2 pos(0), pos(1), pos(2), 0, 0, 0, 0, 0, 0, 0, False, 1
    Next
End Sub

Function get_position(comp As Component2) As Variant
    Dim pos(5) As Variant
    Dim swTransform As SldWorks.MathTransform
    Set swTransform = comp.Transform2
    
    Dim r11 As Double, r12 As Double, r13 As Double
    Dim r21 As Double, r22 As Double, r23 As Double
    Dim r31 As Double, r32 As Double, r33 As Double
    
    Dim r41 As Double, r42 As Double, r43 As Double
    Dim r44 As Double
    
    r41 = swTransform.ArrayData(9)
    r42 = swTransform.ArrayData(10)
    r43 = swTransform.ArrayData(11)
    r44 = swTransform.ArrayData(12)
    pos(0) = r41 * r44
    pos(1) = r42 * r44
    pos(2) = r43 * r44
        
    Set swTransform = swTransform.Inverse
    r11 = swTransform.ArrayData(0)
    r12 = swTransform.ArrayData(1)
    r13 = swTransform.ArrayData(2)
    
    r21 = swTransform.ArrayData(3)
    r22 = swTransform.ArrayData(4)
    r23 = swTransform.ArrayData(5)
    
    r31 = swTransform.ArrayData(6)
    r32 = swTransform.ArrayData(7)
    r33 = swTransform.ArrayData(8)
    
    If r13 < 1 Then
        If r13 > -1 Then
            pos(3) = atan2(-r23, r33)
            pos(4) = asin(r13)
            pos(5) = atan2(-r12, r11)
        Else
            pos(3) = -atan2(r21, r22)
            pos(4) = -PI / 2
            pos(5) = 0
        End If
    Else
        pos(3) = atan2(r21, r22)
        pos(4) = PI / 2
        pos(5) = 0
    End If

    get_position = pos
    
End Function

Function get_bodies(part As PartDoc, pbodies As Variant) As Variant
    Dim cbodies As Variant, bod As Variant, bod1 As Variant
    Dim vbodies() As Variant
    Dim row As Integer
    row = 0
    Dim isnew As Boolean
    Dim body As Body2
    Dim body1 As Body2
    cbodies = part.GetBodies2(0, False)
    If Not IsEmpty(pbodies) Then
        For Each bod In cbodies
            isnew = True
            Set body = bod
            For Each bod1 In pbodies
                Set body1 = bod1
                If body.Name = body1.Name Then
                    isnew = False
                End If
            Next
            If isnew = True Then
                ReDim Preserve vbodies(row)
                Set vbodies(row) = body
                row = row + 1
            End If
        Next
        Dim v As Variant
        get_bodies = vbodies
    Else
        get_bodies = cbodies
    End If
End Function

Sub select_bodies(bodies As Variant)
    Dim seldata As SelectData
    Dim bod As Variant
    Dim body As Body2
    Set seldata = selmgr.CreateSelectData
    seldata.Mark = 1
    swmodel.ClearSelection2 True
    If Not IsEmpty(bodies) Then
        For Each bod In bodies
            Set body = bod
            body.Select2 True, seldata
        Next
    End If
End Sub

Function atan2(Y As Double, X As Double) As Double
    If X > 0 Then
        atan2 = Atn(Y / X)
    ElseIf X < 0 Then
        atan2 = Sgn(Y) * (PI - Atn(Abs(Y / X)))
    ElseIf Y = 0 Then
        atan2 = 0
    Else
        atan2 = Sgn(Y) * PI / 2
    End If
End Function

Function asin(X As Double) As Double
    If Abs(X) = 1 Then
        asin = X * PI / 2
    Else
        asin = Atn(X / Sqrt(1 - X * X))
    End If
End Function

<< the code is devoid of error handling, test as needed, modify the path template, API 2022>>

2 Likes

Hello @Lynkoa15
THANK YOU! This macro looks great. I test it as soon as possible.

Just one thing. On one of my macros in the process of dev' I needed to apply view rotations, and in order to have the most accurate PI value possible, I wrote this:

Dim DtR# '(DegToRad)
DtR = (4 * Atn(1)) / 180   ' "Constante" de conversion degrés en radians (Pi/180)

This code gets PI and divides it by 180 to change the degrees to radians.
(For example, (3 * DtR) converts 3 degrees to radians)

In short, to have a "perfect" PI in VBA you need this code:

Dim PI# '(THE_number)
PI = (4 * Atn(1))   ' "Constante" Pi calculée

When I say "perfect" it's obviously within the decimal limit of the Double (#) type.

Of course, there is an advantage to using a constant, as long as you remember the first 14/15 decimal places of pi (3.14159265358979)

1 Like