28 Apr, 2019

Session 1 Notes (PowerCopies and UDFs)

Here is what we went over during the April 27th 2019 session on PowerCopies and UDFs( User Defined Features).

Organizing The Tree:

I learn back in 2008 from BIlly Wong, a former colleague from Gehry Technologies (now Trimple Technologies), the good practice of organizing the content of PowerCopy and UDF templates into two owners: Input, and Output.

In todays examples, owners are Geometrical Sets. The idea is that all geometrical elements that serve as input for the template are created as Isolated geometry in the Input Owner. The reason to isolating them is ensuring that the template doesnot get affected by changes to the model, because, well, it is a template. The Output owner includes all construction geometry to be replicated when making instances of the template. Similar to geometry, Parameters and Rules go under ParameetrSets and RelationshipSets respectively.

Flat Panel Template

The template takes in 4 points, uses 3 points to define a plane, then projects all 4 points on the plane to return 4 new output points, and finally create a closed polyline and a fill surface.

The Difference

PowerCopies are best described as copy-paste then replace parents. Instantiating a PowerCopy will recreate the output (geometry, parameters, and relationships) and use the new inputs as parents (instead of those from the template).

Since PowerCopy instances are a copy-paste, users will get all geometry made by the template. This can clutter the model and tree. That said, users have full access to all elements.

Modifications to the construction of a PowerCopy instance does not affect other instances or the source template.

UDF templates are similar to PowerCopy Templates in that they allow for creating new instances using a new set of inputs. However, they differ in two ways:
– UDFs exist as Features. The main output of a UDF defines its type. If a surface, then the UDF is considered a Surface object. UDFs also have secondary outputs, which can be queries programmatically using EKL. Users are able to decide what the main output is, and which secondary outputs should be added to the template’s output. This allows users to conceal internal construction and reduce model size as needed.
– Because UDFs are Features, CATIA allows for synchronizing them with the source template if there are structural changes. For example, adding a new output (Plane) to instances of a UDF template is as simple adding to the template, then synchronizing the instances with the source template.

Instantiating UDFs With Knowledge Patterns

I broke the model into 3 Knowledge Patterns (KPTs). The first takes two groups of planes, representing two directions, then intersects them with a surface to generate intersection curves. The second takes the set of generated curves and intersects them withe ach other to generate intersect points, into groups of 4 points.

The benefit of breaking the automation in this example to 3 KPTs is to allow users to make changes to each KPT without having to rerun the previous KPTs. I learned that from working with projects that required many iterations to address changing requirements. Each KPT’s output (Lists) serve as input to the subsequent one.

Creating geometry with a KPT requires storing them in a list. This allows the KPT to manage updating, removing, and adding new instances as needed when the model changes.

Creating geometry also requires using one of the GenerativeFunctions of EKL. In this example I use the CreateOrModifyDatum to create datum geometry, and the CreateOrModifyTemplate to create UDFs.


This is the first KPT code (generate intersection curves)

let planeSet1(Feature)
let planeSet2(feature)
let srf(Surface)
//referencing planes features from the model
planeSet1 =`CONTEXT\Plane system.2` 
planeSet2 = `CONTEXT\Plane system.3` 
//referencing the surfacen from the model
//(just double click a feature in the model and its path will be added to the editor)
srf =`CONTEXT\Multi-sections Surface.1` 

let dirSet1, dirSet2(OpenBodyFeature)
set dirSet1 =CURVES\Dir1 
set dirSet2 =CURVES\Dir2 
let pln(Plane)
let crv(Curve)
//process first plane set
for pln inside planeSet1.Query("Plane", ""){
   //if the plane does not insert the surface continue... skip it and move to the next one
  if(distance(pln, srf)>0mm ) continue  

  //we nned the type, the owner, the KPT list, and the position in the list (i simply use the size +1 to define the position)
  crv = CreateOrModifyDatum("Curve",dirSet1, Relations\CURVES_KPT\Dir1 , Relations\CURVES_KPT\Dir1.Size()+1)
    crv = intersect(srf, pln)

//repeat for the other plane set
for pln inside planeSet2.Query("Plane", ""){
    if(distance(pln, srf)>0mm ) continue    
    crv = CreateOrModifyDatum("Curve",  dirSet2, Relations\CURVES_KPT\Dir2 , Relations\CURVES_KPT\Dir2.Size()+1)    
    crv = intersect(srf, pln)

This is the second KPT (generate points)

let groups(OpenBodyFeature) set groups =POINT_GROUPS //curve lists coming from the first KPT let crvSet1, crvSet2(List) crvSet1 =Relations\CURVES_KPT\Dir1 crvSet2 = Relations\CURVES_KPT\Dir2 let a, b, c, d(Curve) let i, j(Integer) let aGroup(OpenBodyFeature) i=1 //loop over curves for i while i< crvSet1.Size(){ j=1 for j while j< crvSet2.Size(){ aGroup = new ("OpenBodyFeature", TextFormat("Group#-#", i, j), groups) //grab two in i direction, and two in j direction, the intersect them //following a loop a to b to c to d a = crvSet1.GetItem(i) b = crvSet2.GetItem(j) c = crvSet1.GetItem(i+1) d = crvSet2.GetItem(j+1) let ab, bc, cd, da(Point) ab = CreateOrModifyDatum("Point", aGroup, Relations\POINT_GROUPS_KPT\PointGroups , Relations\POINT_GROUPS_KPT\PointGroups.Size()+1 ) ab = intersect(a, b):Point bc =CreateOrModifyDatum("Point", aGroup, Relations\POINT_GROUPS_KPT\PointGroups , Relations\POINT_GROUPS_KPT\PointGroups.Size()+1 ) bc = intersect(b,c):Point cd =CreateOrModifyDatum("Point", aGroup, Relations\POINT_GROUPS_KPT\PointGroups , Relations\POINT_GROUPS_KPT\PointGroups.Size()+1 ) cd = intersect(c,d):Point da = CreateOrModifyDatum("Point", aGroup, Relations\POINT_GROUPS_KPT\PointGroups , Relations\POINT_GROUPS_KPT\PointGroups.Size()+1 ) da = intersect(d ,a):Point } } groups.Update()

This is the third KPT (Instantiate UDFs)

let panelsGeoset(OpenBodyFeature) set panelsGeoset =PANELS //point list coming from second KPT let pointGroups(List) pointGroups =Relations\POINT_GROUPS_KPT\PointGroups let udf(UserFeature) let i=1 let a, b, c, d(Point) for i while i<= pointGroups.Size(){ //get the first 4 points based on the value of index i a = pointGroups.GetItem(i) b = pointGroups.GetItem(i+1) c = pointGroups.GetItem(i+2) d = pointGroups.GetItem(i+3) //call the generative function to make a udf udf = CreateOrModifyTemplate("UDF", panelsGeoset, Relations\PANEL_KPT\PANELS ,Relations\PANEL_KPT\PANELS.Size()+1) //set the inputs of the udf by their name. udf.SetAttributeObject("A", a) udf.SetAttributeObject("B", b) udf.SetAttributeObject("C", c) udf.SetAttributeObject("D", d) //finish instantiating the udfs. EndModifyTemplate(udf) i=i+4//jump tothe next four in the list. //alternatively, we could have looped over the geometrical sets instead of the list of points from the previous KPT. //which will give us even greater control over generated panels, because users can simply insert a new geometrical sets with 4 points, and a new udf panel will get created by the KPT. }

Demo And Files

Here is how the template is built

Here is the process of generation

Finally, here is the file!

Tags: , , ,

About : Maher Elkhaldi

Maher Elkhaldi is a senior applications engineer at Tesla Motors. He founded the 3DXAutomation blog to help make knowledge of programming CATIA easier to find, and contribute to the open-source community.

2 thoughts on “Session 1 Notes (PowerCopies and UDFs)”

    1. Thanks! the decomposition technique to break down code to stages was something I realized while iterating over a project that required user input in many areas. Billy was great in showing me how to start making organized power copies in 2008 🙂

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.