CATIA V5 Automation

Efficiently navigating parameter collections

Advertisements

Many times over the years, I have seen a common problem posted in CATIA forums.  The problem is that some macro runs great on smaller parts or products, but it slows down tremendously on larger ones.  The programmer has noticed that the slowness happens when trying to retrieve a parameter from a parameters collection.  Fortunately, the problem is very easy to correct.  In this article I will show how to work with smaller parameter collections to boost performance and also show how to more reliably get at the specific parameters you need.

The problem

Before looking at the solution, lets clearly understand what the problem is here.  The slowness that you see when dealing with larger parts or products is simply caused by parameter collections that are also very large.  You may not realize it but every parametric feature typically has about one to ten parameters associated with it.  For example, every feature has an Activity parameter (allows it to be deactivated) as well as others that might control things like offset values, angles, tolerances, etc.  So, a part with 500 geometric features could easily have several thousand parameters in the root parameters collection!  Products can be even worse because their root parameter collection contains all parameters in the product itself as well as all parameters in all parts and products below them!

When you request a parameter from a parameter collection by name, the API has to go one by one through the entire collection and perform string comparisons to find a match.  That can be an expensive process, in terms of CPU time.

As a quick scripting exercise let us see how large the parameter count can be.  Open some different parts with many features or a product that has many parts below it (each with many features) then run the code below:


Sub CATMain()

     Dim strType As String
     Dim objParams As Parameters

     'Get at the root parameters collection based on the type of document
     strType = TypeName(CATIA.ActiveDocument)
     If strType = "ProductDocument" Then
          Set objParams = CATIA.ActiveDocument.Product.Parameters
     ElseIf strType = "PartDocument" Then
          Set objParams = CATIA.ActiveDocument.Part.Parameters
     End If

     'Display the parameter count
     MsgBox "The active document has " &objParams.Count &" parameters."

End Sub

The solution

The solution to the problem is to get creative and retrieve a only a subset of the total parameters, then get at a specific parameter in that smaller collection.  I usually accomplish this by one of two techniques depending on the situation.

Method 1: Access only parameters belonging to a parameter set

Parameter sets can be found inside many different CATIA documents and are easily recognized by a special node in the tree that looks like this:

Typically, this node will be located near the top of the tree for a particular document and will be called “Parameters” but it is also possible to make many parameter sets inside a single document.  They can be nested under one another to build a structured set of parameters and can even be nested within geometrical sets and bodies.  I utilize parameter sets often when making reusable template models in order to organize related parameters.

When you get at a parameter set, you have several options to access smaller collections of parameters within it.  You can either access all parameters, only the direct parameters or other parameter sets nested under the parameter set.  I will show all of these techniques in one simple example below.  In this scenario, there are many parameters with the same name (Radius) in different places.

I will assume a part is open in its own window and contains the objects shown in the tree above. Follow along by reading the comments in the code.


Sub CATMain()

     Dim objPart As Part
     Dim objParamSetRoot As ParameterSet
     Dim objParamSet As ParameterSet
     Dim objParams As Parameters
     Dim objParam As Parameter
     Dim intCount As Integer
     Dim intIndex As Integer
     Dim strName As String
     Dim strMsg As String

     'Get at the part object
     Set objPart = CATIA.ActiveDocument.Part

     'Get at all parameters in the part...
     'This collection could be very large in some cases and therefore slow
     'Could also be hard to get at a specific Radius parameter
     'since .Item("Radius") will always return only the first one found

     Set objParams = objPart.Parameters
     intCount = 0
     For intIndex = 1 To objParams.Count
          If objParams.Item(intIndex).Name = "Radius" Then 
               intCount = intCount + 1
          End If
     Next
     strMsg = "This part has " &objParams.Count & " total parameters" & vbCrLf
     strMsg = strMsg & "and has " & intCount & " parameters named ""Radius"""
     MsgBox strMsg, 0, "Test1"

     'Now get at the root parameter set and check its direct parameters
     'There will be none in this example because the root parameter set
     'only has other parameter sets below it but no parameters

     Set objParamSet = objParams.RootParameterSet
     intCount = objParamSet.DirectParameters.Count
     MsgBox "The root parameter set has " & intCount _
             & " parameters directly under it.", 0, "Test2"

     'Get at the root parameter set and retrieve all its parameters
     'There will be seven in this example
     'For this we will use the AllParameters method.
     'Note that IF we were sure there was ONLY ONE Radius Parameter
     'somewhere under this set, we could get it from this parameters collection
     'by using the .Item method

     Set objParamSet = objParams.RootParameterSet
     intCount = objParamSet.AllParameters.Count
     MsgBox "The root parameter set has " & intCount _
                     & " parameters under it (all levels).", 0, "Test3"

     'Get at just the Radius parameter in the "Holes" parameter set
     'For this we access a specific ParameterSet object and get its
     'DirectParameters
     Set objParamSet = objParams.RootParameterSet.ParameterSets.Item("Holes")
     Set objParam = objParamSet.DirectParameters.Item("Radius")
     strName = objParams.GetNameToUseInRelation(objParam)
     strMsg = "The full name of the radius param in the Holes param set is,"
     strMsg = strMsg & vbCrLf & strName
     MsgBox strMsg, 0, "Test4"

End Sub

Method 2: Access only the parameters aggregated under some object

This can be achieved with a call to the Sublist method which is provided by the Parameters object.  The general syntax looks like this:

Set Params2 = Params1.Sublist(iObject, iRecursively)

Params1

A Parameters object

iObject

The object whose child parameters should be retrieved

iRecursively

Boolean specifying whether to retrieve only the parameters directly under the object or also for all parameters nested under that object at all levels

Params2

The returned Parameters object containing the subset of parameters

Lets look back at the earlier example.  The Sublist method would be very useful to quickly get at that Radius parameter that is nested directly under Geometrical Set.1


Sub CATMain

     Dim objPart As Part
     Dim objGeoSet As HybridBody
     Dim objParams As Parameters
     Dim objParam As Parameter
     Dim strName As String
     Dim strMsg As String

     'Get at Geometrical Set.1
     Set objPart = CATIA.ActiveDocument.Part
     Set objGeoSet = objPart.HybridBodies.Item(“Geometrical Set.1”)

     'Get at ONLY the parameters aggregated directly under the geo set
     'by specifying False for the 2<sup>nd</sup> argument.  This will prevent
     'retrieving the Radius parameter under the circle
     Set objParams = objPart.Parameters.SubList(objGeoSet,False)

     'Get the radius parameter and display its full name
     Set objParam = objParams.Item("Radius")
     strName = objParams.GetNameToUseInRelation(objParam)
     strMsg = "The full name of the radius parameter directly " & vbCrLf
     strMsg = strMsg & "under Geometrical Set.1 is," & vbCrLf & strName
     MsgBox strMsg, 0, "Test5"

End Sub

Conclusions

The techniques shown above are very powerful ways to increase performance in your program and to get at specific parameters.  Even though I showed several examples above, this is really only the “tip of the iceberg”.  I have used these basic techniques in hundreds of different scenarios. You can even use these techniques to get at just the collection of parameters under a specific object object then create new parameters nested under it…I’ll let you experiment with that on your own.

Anyway, here are some general things to take away from this article.

  1. When you retrieve a parameter by name using the Item method, it will always return the first match it finds in the collection.
  2. If a parameter is inside a parameter set, first access a parent parameter set above the parameter you want then either use the AllParameters or DirectParameters method.
  3. If a parameter is aggregated under some other object use the SubList method. Remember to properly specify whether you want to retrieve parameters recursively.
  4. As mentioned earlier, when you retrieve the Parameters object for a product, it contains all parameters in the product itself as well as all parameters in all parts and products below it.  To get ONLY the parameters belonging to the product itself, get at its RootParameterSet then use either the AllParameters or DirectParameters method.

Please take a moment to rate this article…Just click the stars up near the title.

Add to: del.icio.us, StumbleUpon, Digg, Google

Advertisements