Convertir un assemblage en un fichier indépendant

Bonjour @Rim-b
Excellent !! Mais pas parfait… C’est exactement le résultat final attendu, sauf pour le placement.

J’insère une pièce de tôlerie dans la pièce de la tôlerie hôte, mais je ne peux pas la positionner à souhait. Est-il possible de pivoter la tôlerie insérée ou est-on limités à la translation lors de l’insertion uniquement ?

L’idée de départ de passer par un assemblage était principalement pour rendre les positionnements simples, avant que tout ça finisse en un prt.

Bonjour,

Non il y a des fonctions d’assemblages (déplacer avec des contraintes).
Mais très franchement c’est une usine à gaz, vu de ma fenêtre, ce que vous cherchez à faire.
Faut choisir le bon mode au démarrage (assemblage ou pièce dans pièce) car « convertir » par la suite c’est des heures et des heures de boulot. Je ne suis même pas certain qu’une macro y arrive sans générer des erreurs de positionnement ou tout du moins faudra passer des heures sur ce type de développement.

2 « J'aime »

J’utilise souvent la fonction insérer piece et je confirme vos dir cyril, le truc saute au moindre changement dans l’arborescence sw n’aime pas trop jouer avec la barre de reprise,
Pour la copie de fonction avec macro je pense pas non plus, je vois pas comment peut on modifier un perçage où un enlèvement de matière borgne ou à travers tout sans affecté les autres corps !

3 « J'aime »

Bonjour,

L’insertion de pièce dans une pièce fonctionne. Par contre si vous avez plus d’une dizaine de pièces ça risque de très vite être galère à gérer. Si vous voulez que ça fonctionne le mieux est de sûrement pas utiliser les contraintes lors de l’insertion de pièces mais que des positions.
Une piste de solution serait peut être de faire des regroupement de pièces qui vont ensemble (donc faire des sous pièces) et après d’insérer une dizaine de pièces dans une pièce.

NB : Au niveau des reconstructions ça risque d’être coton à gérer dans tous les cas.

1 « J'aime »

Oui je confirme et c’est assez pénalisant quand un client t’envoie un ASM au format STEP par exemple ou autre neutre pour te faire faire une simulation RDM. Sans compter que tu perds au passage toutes les contraintes.

Bon courage :cold_face:

2 « J'aime »

Bonjour.
Merci à tous pour vos réponses très instructives !

Alors, j’ai testé l’insertion de pièce dans une pièce, le fichier pèse 2 fois moins lourd qu’un assemblage avec la même pièce rendue virtuelle.
Que le poids passe du double au simple n’est pas négligeable.

Toutefois, au lu de ce topic, j’ai l’impression que virtualiser les pièces dans un assemblage reste de loin la solution la plus simple, pratique et flexible.
Quel dommage que le fichier pèse le double…
L’astuce des pipiP est effectivement une possibilité intéressante, @froussel

En vérifiant dans lapi, il me semble que c’est jouable:

  1. Parcourir les composants un par un

  2. Récupérer la position et orientation du composant par rapport à l’origine assemblage.

  3. Insérer le composant dans une pièce et rompre le lien .

  4. Détecter les nouveaux corps(un peu casse tête ! ) .

  5. Appliquer une orientation et un déplacement à ces nouveaux corps

En rompant le lien, les fonctions de la pièce insérée sont récupérés dans l’arborescence, le miracle c’est que SW les appliquent seulement aux nouveaux corps (il modifie les définition et les zones actions de tous les corps vers une sélection automatique😀) ce qui évite le souci que j’ai évoqué précédemment,aussi le lien est rompu l’arborescence et stable,

Le seul bimol que je trouve c’est que ces corps sont positionnés par rapport à l’origine pièce non pas par interactions de contraintes.
Sans dire que l’arborescence vas être très très longue en fonction du nombre de composants et leur complexités

3 « J'aime »

Si joint une description des points
(merci a @Rim-b qui a évoqué la fonction principale)






Assemblage1.zip (355,9 Ko)

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

<< le code est dépourvu de la gestion des erreurs, à tester selon besoin, à modifier le chemin template, api 2022>>

2 « J'aime »

Bonjour @Lynkoa15
MERCI ! Cette macro a l’air au top. Je la teste dès que possible.

Juste une chose. Sur une de mes macro en cours de dev’ j’avais besoin d’appliquer des rotations de vue, et dans le but d’avoir une valeur PI la plus précise possible, j’ai écrit ceci :

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

Ce code obtient PI et le divise par 180 pour passer les degrés en radians.
(Soit par exemple (3 * DtR) convertit 3 degrés en radians)

Bref, pour avoir un PI « parfait » en VBA il faut donc ce code :

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

Quand je dis « parfait » c’est évidemment dans la limite de décimales du type Double (#).

Certes, il y a un avantage à utiliser une constante, à condition de se souvenir des 14/15 premières décimales de pi (3.14159265358979)

1 « J'aime »