0

I have a CATIA Script that does the following job in the product document:

  1. Asks the user to select target points (which are geometrical points and not from a sketch) where they want bolts to be inserted,
  2. Retrieves the location of the part file of the bolt from the user,
  3. Creates a level 1 product in the tree (i.e., a subassembly),
  4. Inserts the bolts in the subassembly as many times as there were points selected in step 1.

Now, every part file of the bolt that is inserted has only one geometrical point (which differs from a sketch point) in it. I want the macro to add a coincidence constraint on each selected point in the parent part (i.e., points which were selected by the user in step 1) with the point in each inserted part. How can I achieve this? Is it possible to create references from parts inserted via AddComponentsFromFiles? Also, I will be working with different bolts (meaning the names of files will vary) but each of them contains a geometrical point (like described above), so I want it to be generalised. My design tree may contain other subassemblies or parts so I do not know how can I use something like CreateReferenceFromName for this. I have very, very little knowledge about scripting macros, and I got the following script from the internet but I understand almost all of it. The script I am using is as follows.

Sub CATMain()

'====================SELECT THE ACTIVE DOCUMENT
Dim mysel
set mysel = CATIA.ActiveDocument.selection

'====================CREATE A FILTER SO THAT THE USER CAN SELECT POINTS ONLY
dim myfilter(0)
myfilter(0)="Point"

'====================TELL CATIA TO PROMPT THE USER TO SELECT THE POINTS
dim mypoints
mypoints = mysel.SelectElement3(myfilter,"Select the target points for insertion of parts",true,CATMultiSelTriggWhenUserValidatesSelection,false)
if (status = "Cancel") then exit sub

'====================COUNT THE POINTS 
for x=1 to mysel.count
set point=mysel.item(x).value
next

'====================RETRIEVE THE PATH OF THE PART FROM THE USER USING DIALOG BOX
Dim strFilePath As String
strFilePath = CATIA.FileSelectionBox("Select Part File", "*.CATPart", 0)
 
'====================IF USER CLICKED CANCEL (i.e., empty string is returned), EXIT THE PROGRAM
if strFilePath = "" Then Exit Sub

Dim ofilesys as filesystem
Set ofilesys=CATIA.filesystem

if (not ofilesys.fileexists(strfilepath)) then
'err.raise 9999,,sfilepath & ": This file does not exist."
msgbox "Error: The file does not exist."
else

dim arrayOfVariantOfBSTR1(0)
arrayOfVariantOfBSTR1(0)=strfilepath
dim partdocument1 as document
set partdocument1 = CATIA.ActiveDocument

'====================GET THE ROOT PRODUCT FROM PRODUCT DOCUMENT
dim product1 as product
set product1 = partdocument1.product
Dim products1 as products
Set products1 = product1.products

'====================CREATE A SUBASSEMBLY
Dim Product2 as product
Set Product2 = products1.AddNewComponent("Product", "")
Dim products2 as products
Set products2 = product2.products

'====================INSERTING PARTS AS MANY TIMES
dim instancesss
  For instancesss=1 to mysel.count
     products2.AddComponentsFromFiles arrayOfVariantOfBSTR1,"All"
  Next

Msgbox "Parts succesfully inserted." & vbnewline & "No. of parts inserted: " & mysel.count, 0
end if

End Sub

I have tried creating the reference using reference1=product2.CreateReferenceFromName(___ & "/" & ____ "/!" & ____) etc., but got lost because I do not know much about scripting.

5
  • I suggest you to move the product by a Matrix instead of using constraints. Use Move method on each product you insert . catiadoc.free.fr/online/interfaces/interface_Move.htm
    – Disvoys
    Commented Nov 28, 2023 at 23:43
  • Using an additional sub-product would only work, if you create the constains in the root-product and the sub-product is flexible.
    – Shrotter
    Commented Nov 29, 2023 at 6:46
  • @Disvoys Thank you for the suggestion! I have just done that and it does a great job. I am linking my updated script here [drive.google.com/file/d/1IFSVYtfxq582qdEowAqMfWqgyL8kYDst/…. Now that I have translated the coordinate system of the inserted product (using the array/matrix of 12 elements), how do I rotate it? I mean, what values do I have to plug into the transformation matrix?
    – user39154
    Commented Nov 30, 2023 at 16:35
  • @Shrotter Can you explain that in a little bit more detail? The addition of the sub-product is optional for me and I can skip that step (so the parts will be added directly under the root product). Thanks for your comment!
    – user39154
    Commented Nov 30, 2023 at 16:39
  • @user39154 The 3 last values of your matrix are the point coordonates, as you understood. Matrix is x1, x2, x3, y1, y2, y3, z1, z2, z3, ptX, ptY, ptZ You will need to select Lines (you will be able to get easliy direction of these lines, see the GetDirection method) instead of the points. You will need then Vectorize the direction and apply vector products. And finally, the matrix obtained must be transformed into the global matrix. You can check this link for mathematics help: link
    – Disvoys
    Commented Dec 1, 2023 at 17:59

3 Answers 3

0

The string for CreateReferenceFromName has (in most cases) following structure:

RootProductName/InstanceName/!NameOfGeometricElement

Here an example how to build the references and create the constraints for a point named MyPointForConstraint in the inserted part.

The parts are inserted in the root-product.

(replaces your code from line CREATE A SUBASSEMBLY on)

Dim oInstanceProduct1 as Product
Dim oInstanceProduct2 as Product
Dim oPoint1 as Point
Dim oPoint2 as Point
Dim sRef1 as String
Dim sRe21 as String
Dim oRef1 as Reference
Dim oRef2 as Reference
dim i as integer
Dim sElementName as string

sElementName = "MyPointForConstraint"

Dim constraints1 As Constraints
Set constraints1 = product1.Connections("CATIAConstraints")

'====================INSERTING PARTS AS MANY TIMES

  For i = 1 to mysel.count2
     products1.AddComponentsFromFiles arrayOfVariantOfBSTR1,"CATPart"
     
     'create Reference for selected Point
     Set oInstanceProduct1 = mysel.item2(i).LeafProduct
     Set oPoint1 = mysel.item2(i).value
     sRef1 = product1.Name & "/" & oInstanceProduct1.Name & "/!" & oPoint1.Name
         
     Set oRef1 = product1.CreateReferenceFromName(sRef1)
     
     'create reference for previous added part
     Set oInstanceProduct2 = products1.Item(products1.count)
     sRef2 = product1.Name & "/" & oInstanceProduct2.Name & "/!" & sElementName
         
     Set oRef2 = product1.CreateReferenceFromName(sRef2)
     
     'create constraint
     constraints1.AddBiEltCst catCstTypeOn, oRef1, oRef2     
     
  Next
2
  • I really appreciate your big help! This works great. Since your answer, I have been trying to modify it more so that I select a point and its axis, another point and the corresponding axis, and so on, (where the points and the axes specify my target locations for inserting bolts,) and the bolts get placed AND oriented there. I want to select the axis by just hovering over the hole (which is possible by applying Reference as the filter). My bolt will have a point and an axis (whose names I'd know). But I can't get anywhere in this modification journey.
    – user39154
    Commented Dec 8, 2023 at 13:52
  • Here's the under-modification code I am currently working on if anyone wants to take a look at drive.google.com/file/d/17-t055dG9degR4911J-XfSUCPETGddTs/…
    – user39154
    Commented Dec 11, 2023 at 13:17
0

Suggestion with the 'Move method' to answer your question about the rotation of the matrix.

Your actual code: https://drive.google.com/file/d/1IFSVYtfxq582qdEowAqMfWqgyL8kYDst/view

Assuming that you know OOP programming and that you know how to create a "yourObject" object. It's been a long time since I developed in VBA, sorry if there are a few errors, but the principle is generally respected.

Please use this like : products2.Item(instancesss).Move.Apply TransformedMatrice(yourObject)

' yourObject is an Object with xDirection, yDirection, zDirection, xPoint, yPoint, zPoint
' you should this function like:

' products2.Item(instancesss).Move.Apply TransformedMatrice(yourObject)

Function TransformedMatrice(yourObject As youtTypeObject) As Variant
    
    'Variable declaration
    Dim matrice1(1 To 12) As Variant
    Dim matrice2(1 To 13) As Double
    Dim vector1(1 To 3) As Double
    Dim vector2(1 To 3) As Double
    Dim x As Double
    
    'your global matrix
    matrice2 = Array(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0)
            
    'initialize your vector1
    x = 0
    If yourObject.Xdirection <> 0 Then
        x = (yourObject.Ydirection + yourObject.Zdirection) / yourObject.Xdirection
        Dim normale As Double
        normale = Sqr(x * x + 1 + 1)
        vector1(1) = x / normale
        vector1(2) = 1 / normale
        vector1(3) = 1 / normale
    End If
    
    ' Initialize your vector2
    vector2(1) = yourObject.Xdirection:
    vector2(2) = yourObject.Ydirection:
    vector2(3) = yourObject.Zdirection
    
    ' If you want to apply a direction (1 or -1) and an offset
    Dim offset As Double
    Dim direction As Double
    offset = 0
    direction = 1
        
    ' Calculate the Matrice1 according to the vectors
    matrice1(1) = vector1(1) * direction
    matrice1(2) = vector1(2) * direction
    matrice1(3) = vector1(3) * direction
    matrice1(4) = CrossProduct(vector1, vector2)(1)
    matrice1(5) = CrossProduct(vector1, vector2)(2)
    matrice1(6) = CrossProduct(vector1, vector2)(3)
    matrice1(7) = yourObject.Xdirection * direction
    matrice1(8) = yourObject.Ydirection * direction
    matrice1(9) = yourObject.Zdirection * direction
    matrice1(10) = yourObject.xPoint + (itemXDir * offset)
    matrice1(11) = yourObject.yPoint + (itemYDir * offset)
    matrice1(12) = yourObject.zPoint + (itemZDir * offset)
    
    ' Return the matrix
    TransformedMatrice = TransposeMatrices(matrice1, matrice2)
    
End Function


Public Function CrossProduct(vector1() As Double, vector2() As Double) As Double()
    Dim result(1 To 3) As Double
    result(1) = vector1(2) * vector2(3) - vector1(3) * vector2(2)
    result(2) = vector1(3) * vector2(1) - vector1(1) * vector2(3)
    result(3) = vector1(1) * vector2(2) - vector1(2) * vector2(1)
    CrossProduct = result
End Function

Public Function TransposeMatrices(matrice1 As Variant, matrice2 As Variant) As Variant
    Dim result(1 To 12) As Double
    
    result(1) = matrice1(1) * matrice2(1) + matrice1(4) * matrice2(2) + matrice1(7) * matrice2(3)
    result(2) = matrice1(2) * matrice2(1) + matrice1(5) * matrice2(2) + matrice1(8) * matrice2(3)
    result(3) = matrice1(3) * matrice2(1) + matrice1(6) * matrice2(2) + matrice1(9) * matrice2(3)
    
    result(4) = matrice1(1) * matrice2(4) + matrice1(4) * matrice2(5) + matrice1(7) * matrice2(6)
    result(5) = matrice1(2) * matrice2(4) + matrice1(5) * matrice2(5) + matrice1(8) * matrice2(6)
    result(6) = matrice1(3) * matrice2(4) + matrice1(6) * matrice2(5) + matrice1(9) * matrice2(6)
    
    result(7) = matrice1(1) * matrice2(7) + matrice1(4) * matrice2(8) + matrice1(7) * matrice2(9)
    result(8) = matrice1(2) * matrice2(7) + matrice1(5) * matrice2(8) + matrice1(8) * matrice2(9)
    result(9) = matrice1(3) * matrice2(7) + matrice1(6) * matrice2(8) + matrice1(9) * matrice2(9)
    
    result(10) = matrice1(1) * matrice2(10) + matrice1(4) * matrice2(11) + matrice1(7) * matrice2(12) + matrice1(10)
    result(11) = matrice1(2) * matrice2(10) + matrice1(5) * matrice2(11) + matrice1(8) * matrice2(12) + matrice1(11)
    result(12) = matrice1(3) * matrice2(10) + matrice1(6) * matrice2(11) + matrice1(9) * matrice2(12) + matrice1(12)
    
    TransposeMatrices = result
End Function
0

Thanks everyone for their input. I could not do this myself. The following script does the job that is stated in the question.

'  Language is CATScript
'  ***********************************************************************************
'  Purpose: I made this macro to ease my task of adding a bolt frequently in an 
'           assembly that has many holes. This macro reduces the manual work by
'           adding x no. of bolts and creating a coincidence constraint between 
'           a point (of arbitrary name) present in the parent part and and a point
'           (with name "Point.1") present in the added part.

'*************************************************************************************

Sub CATMain()

'   SELECT THE ACTIVE DOCUMENT
'   ==============================
    Dim mysel
    Set mysel = CATIA.ActiveDocument.selection

'   CREATE A FILTER SO THAT THE USER CAN SELECT POINTS ONLY
'   ===========================================================
    Dim myfilter(0)
    myfilter(0)="Point"

'   TELL CATIA TO PROMPT THE USER TO SELECT THE POINTS
'   ======================================================
    Dim mypoints
    mypoints = mysel.SelectElement3(myfilter,"Select the target points for insertion of parts"_
    ,true,CATMultiSelTriggWhenUserValidatesSelection,false)
    if (mysel.count= 0) then Exit Sub

'    RETRIEVE THE PATH OF THE PART FROM THE USER USING DIALOG BOX
'    ================================================================
    Dim strFilePath As String
    strFilePath = CATIA.FileSelectionBox("Select Part File", "*.CATPart", 0)
 
'   IF USER CLICKED CANCEL, EXIT THE PROGRAM
'   ============================================
    if strFilePath = "" Then Exit Sub

    Dim ofilesys as filesystem
    Set ofilesys=CATIA.filesystem

    if (not ofilesys.fileexists(strfilepath)) then
        'err.raise 9999,,sfilepath & ": This file does not exist."
        msgbox "Error: The file does not exist."
    else

        Dim arrayOfVariantOfBSTR1(0)
        arrayOfVariantOfBSTR1(0)=strfilepath
        Dim partdocument1 as document
        Set partdocument1 = CATIA.ActiveDocument

'       GET THE ROOT PRODUCT FROM PRODUCT DOCUMENT
'       ==============================================
        Dim product1 as product
        Set product1 = partdocument1.product
        Dim products1 as products
        Set products1 = product1.products

'       GET EVERYTHING READY FOR CREATING CONSTRAINTS
'       =================================================
        Dim i as integer
        Dim oInstanceProduct1 as Product
        Dim oInstanceProduct2 as Product
        Dim oPoint1 as Point
        Dim sRefP1 as String
        Dim sRefP2 as String
        Dim oRefP1 as Reference
        Dim oRefP2 as Reference
        Dim sPointName as string
        sPointName = "Point.1"
        Dim constraints1 As Constraints
        Set constraints1 = product1.Connections("CATIAConstraints")

'       INSERT PARTS AS MANY TIMES
'       ==============================
        For i = 1 to mysel.count
            products1.AddComponentsFromFiles arrayOfVariantOfBSTR1,"CATPart"

'           CONSTRAIN EACH POINT
'           ========================
            'create reference for ith selected point
            Set oInstanceProduct1 = mysel.item(i).LeafProduct
            Set oPoint1 = mysel.item(i).value
            sRefP1 = product1.Name & "/" & oInstanceProduct1.Name & "/!" & oPoint1.Name
            Set oRefP1 = product1.CreateReferenceFromName(sRefP1)
            'create reference for previous added part
            Set oInstanceProduct2 = products1.Item(products1.count)
            sRefP2 = product1.Name & "/" & oInstanceProduct2.Name & "/!" & sPointName
            Set oRefP2 = product1.CreateReferenceFromName(sRefP2)
            'create constraint
            constraints1.AddBiEltCst catCstTypeOn, oRefP1, oRefP2
     
        Next
        product1.Update
    End if
End sub

Not the answer you're looking for? Browse other questions tagged or ask your own question.