Developing proper names to use in product relations
In the last article, I introduced some scenarios where you need to develop the proper name of an object to use in a part relation. This article follows up by discussing some other scenarios where the relation is created in a product and refers to various objects in both parts and products.
The table below summarizes four common scenarios you are likely to encounter when creating or modifying relations inside a product.
|Case||Where is the relation?||Object referred to by the relation||Example syntax|
|#3||Product||Parameter in same product||NumberOfHoles|
|#4||Product||Non-published parameter in another product *||`Product3\Hole Spacing`|
|#5||Product||Published parameter in another product *||..!Product4!Product5!OverallWidth|
|#5||Product||Published object in another part *||..!Product2!Part5!ResultArea|
|#6||Product||Non-published object in another part *||`Part1\Geometrical Set.1\Join.1`|
* The item should be in the same assembly and in a common branch of the tree
Case #3 – Parameter in same product
In this case, we want to create a relation inside a product that refers to a parameter in the same product. As shown in the table above for case #3, the name used is typically just the parameter name itself. In this case just like in the previous article, the best way to develop the proper name is to use the GetNameToUseInRelation method of a Parameters object. The only real difference is that instead of accessing the parameters collection of a part, this time we will access the parameters collection of the product.
Let’s look at an example. Below, I will create a formula in a product that simply divides one parameter value in half and assigns that value to a second parameter. Both of those parameters also exist in the same product.
Sub Example_Case3() 'Assume there are two real parameters in the main 'parameter set of the root product in the active window Dim objProd As Product Dim objParams As Parameters Dim objParam1 As Parameter Dim objParam2 As Parameter Dim strName As String 'Get at the two parameters Set objProd = CATIA.ActiveDocument.Product Set objParams = objProd.ReferenceProduct.Parameters.RootParameterSet.DirectParameters Set objParam1 = objParams.Item("Real.1") strName = objParams.GetNametoUseInRelation(objParam1) Set objParam2 = objParams.Item("Real.2") 'Create the formula objProd.Relations.CreateFormula "", "", objParam2, strName &"/2" End Sub
Case #4 – Non-published parameter in another product
In this case, we want to create a relation in a product that refers to a parameter in another product within the same assembly. Note that the other product should share a common branch in the assembly as well. Typically, in this scenario the name of the parameter will be made up of the product part number followed by a backslash then the parameter name. However, it is possible that the parameter is in a nested parameter set so the name could be something like, `Product3\ParameterSet1\ParameterSet2\Hole Spacing` instead of `Product3\Hole Spacing`. As in Case #3, the best way to develop this name is the GetNameToUseInRelation method. It will consider these special scenarios and always return the proper name.
To show some example code for this scenario, lets assume we have a product structure as shown below. The goal is to create a formula that simply makes the Hole Spacing parameter in Product1 equal to the Hole Spacing parameter in Product3.
Sub Example_Case4() Dim objProd1 As Product Dim objProd3 As Product Dim objParams As Parameters Dim objParam1 As Parameter Dim objParam3 As Parameter Dim strName As String 'Access the 2 product objects Set objProd1 = CATIA.ActiveDocument.Product Set objProd3 = objProd1.Products.Item("Product2").Products.Item("Product3") 'Get at the 2 parameters Set objParams = objProd1.Parameters.RootParameterSet.DirectParameters Set objParam1 = objParams.Item("Hole Spacing") Set objParams = objProd3.Parameters.RootParameterSet.DirectParameters Set objParam3 = objParams.Item("Hole Spacing") 'Develop the proper name for objParam3 'Then create the formula inside Product1 Set objParams = objProd1.Parameters strName = objParams.GetNameToUseInRelation(objParam3) objProd1.Relations.CreateFormula "", "", objParam1, strName End Sub
Case #5 – Published parameter in another product or published item in another part
In this case, we want to create a relation in a product that refers to either a published parameter in another product or to some published object inside a part in the same assembly. This is one of the unique cases where the GetNameToUseInRelation method cannot be used. Instead, I created a custom function that will return the proper name of a published object.
For this case I will show two examples. First, lets use the same scenario as in Case #4, except we will assume that the Hole Spacing parameter in Product3 is published. In this example, if we want to use the Hole Spacing publication from Product3 in a relation that exists in Product1, the proper name would be `..!Product2!Product3!Hole Spacing`. You can see some differences when publications are involved:
- The name will always start with a ..!
- The path between the products or product and part is important
- The path will separate each node in the assembly with the ! character
Now lets develop that custom function. The idea here is to start at the product or part that has the publication and crawl back up the tree until we get to the product where the relation will be created. Along the way, we will add the ! character to separate each node in the assembly.
Function GetPubNameToUseInRelation(ByRef iRelationProd As Product, ByRef iPubProd As Product, ByRef iPub as Publication) As String ' iRelation product The product where the relation is created ' iPubProd The product containing the publication ' iPub the publication Dim objParent As Object Dim strName As String 'Get the name of the publication and its product Set objParent = iPubProd strName = objParent.ReferenceProduct.PartNumber &"!" &iPub.Name 'Walk back up the tree to the RelationProduct Set objParent = objParent.Parent Do While TypeName(objParent) <> "Application" If TypeName(objParent) = "Product" Then strName = objParent.ReferenceProduct.PartNumber &"!" &strName If objParent.Parent.Parent.ReferenceProduct.PartNumber = iRelationProd.ReferenceProduct.PartNumber Then Exit Do End If Set objParent = objParent.Parent Loop strName = "`..!" &strName &"`" GetPubNameToUseInRelation = strName End Function
A few things to take note of in this function…
- We don’t know how many product nodes might exist between the relation product and the publication product, so we have to loop an unknown number of times. Since this could result in an infinite loop, I added a while condition to the loop to check whether we have somehow walked all the way up the tree and never reached the product where the relation will be created. Here, I check for an object of type Application because the parent of the root product document will be the application object so we should stop the loop in this case. If we didn’t stop here, it will actually loop forever because the parent of the CATIA application is the CATIA application so it will never end.
- The parent of a Product object is always a Products object unless the product is the root node in the assembly. This means that when we walk up the tree, every other loop cycle will access a Products object, not an actual product. This is why I check the TypeName and only add to strName if we have accessed a Product object.
- It is safe to compare the PartNumber property of two products to see if they are the same product because CATIA requires that every part number must be unique in an assembly.
Here is an example showing how to use this new function in the scenario mentioned above.
Sub Example_Case5() Dim objProd1 As Product Dim objProd3 As Product Dim objParams As Parameters Dim objParam1 As Parameter Dim objPub As Publication Dim strName As String Dim objFormula As Formula 'Access Product1 and its parameter Set objProd1 = CATIA.ActiveDocument.Product Set objParams = objProd1.Parameters.RootParameterSet.DirectParameters Set objParam1 = objParams.Item("Hole Spacing") 'Access Product3 and its publication Set objProd3 = objProd1.Products.Item("Product2").Products.Item("Product3") Set objPub = objProd3.ReferenceProduct.Publications.Item("Hole Spacing") 'Develop the proper name for the publication 'Then create the formula inside Product1 strName = GetPubNameToUseInRelation(objProd1, objProd3, objPub) Set objFormula = objProd1.Relations.CreateFormula("", "", objParam1, "") objFormula.Modify strName End Sub
You can handle a similar scenario involving a publication in a part with the same code shown above. This might seem strange because the code above involves products, not parts. The key point to realize here is that every part actually has its own product object as well. You don’t see that product when a part is open in its own window but in an assembly it appears as the instance. Publications made in a part are always accessed through this product object, not the part object. This means that the code above would remain unchanged if you were to replace Product3 in the assembly with a part named Product3 that had the same publication called Hole Spacing.
Case #6 – Non-published object in another part
In this final scenario, we want to refer to an unpublished object that exists within some part in the assembly. This happens to be another case where the GetNameToUseInRelation method cannot be used on its own to get the proper name of that object. However, the solution does still utilize the GetNameToUseInRelation method with a bit of a twist.
In this scenario, the proper naming will look follow this convention: PartNumber\PathOfObjectInPart Unfortunately, the GetNameToUseInRelation function will return the second portion that I referred to as PathOfObjectInPart but it doesn’t include the part number and backslash in between. So this is another case where I use a custom function to give me the proper name every time. The custom function simply gets the part number and concatenates it to the object path. Here is the code:
Function GetObjectNameInPartToUseInProduct(ByRef iPart As Part, ByRef iObject As Object) As String ' iPart Part that contains the object ' iObject Object inside the part whose name we want ' This could be geometry, surface, etc. Dim strName As String 'Get the proper name within the part strName = iPart.Parameters.GetNameToUseInRelation(iObject) 'Strip any of the special quotes if they exist strName = Replace(strName, "`", "") 'Concatenate this name to the part number 'and add the special quotes to the start and end strName = "`" &iPart.Name &"\" &strName &"`" 'Return the final string GetObjectNameInPartToUseInProduct = strName End Function
To see this function in action, lets picture the following scenario – we want to create a formula in the root product that computes a value for the TotalArea parameter by adding the area of a join surface in Part1 and the area of a join surface in Part2. The simplified tree looks like this:
And here is the code:
Sub Example_Case6() Dim objProd As Product Dim objPart1 As Part Dim objPart2 As Part Dim objJoin1 As HybridShapeAssemble Dim objJoin2 As HybridShapeAssemble Dim strName1 As String Dim strName2 As String Dim objParam As Parameter Dim strFormula As String 'Get at the root product and the first two parts under it Set objProd = CATIA.ActiveDocument.Product Set objPart1 = objProd.Products.Item(1).ReferenceProduct.Parent.Part Set objPart2 = objProd.Products.Item(2).ReferenceProduct.Parent.Part 'Get at the two join surfaces Set objJoin1 = objPart1.HybridBodies.Item(1).Hybridshapes.Item("Join_Result") Set objJoin2 = objPart2.HybridBodies.Item(1).Hybridshapes.Item("Join_Result") 'Get the proper names to use in the formula strName1 = GetObjectNameInPartToUseInProduct(objPart1, objJoin1) strName2 = GetObjectNameInPartToUseInProduct(objPart2, objJoin2) 'Get at the TotalArea parameter Set objParam = objProd.Parameters.RootParameterSet.DirectParameters.Item("TotalArea") 'Create the formula strFormula = "area(" &strName1 &") + area(" &strName2 &")" objProd.Relations.CreateFormula "", "", objParam, strFormula End Sub
- When trying to access parameters that belong to a product, you should always access them specifically through the root parameter set of that product. This is because the parameter collection you will get with the syntax Product.Parameters will include all parameters of that product as well as every parameter in every product and part below it. As shown in the above examples, the way to do this is to access Product.Parameters.RootParameterSet instead. To read more about this, check out this article.
- You may have noticed that CATIA will surround the name of an object used in a relation with special quote characters in some situations such as when the name has spaces in it. The GetNameToUseInRelation method as shown in this article will always judge whether those quotes are needed and will automatically return the name with them if required. However, when developing names to use in relations yourself (like in the custom functions above), always include the special quotes at the start and end of the name. If they are not needed, CATIA will remove them.
Sorry this article ended up so long! I generally try to keep the topics quite a bit shorter than this one and still cover the important points. When I started it, I grabbed some pieces from old projects and it didn’t look too bad, but it ended up really long. Anyway, I think it shows most of the common scenarios you will encounter and I hope it is helpful when you are working with relations in your automation projects.
Please take a moment to rate this article…Just click the stars up near the title.