11 May, 2019

Building Trees With Custom Syntax Using EKL

Automation can make things quick and easy. Inspired by the idea of providing Syntactic sugar to execute tasks quickly, and more specifically Markdown-Mermaid, here is an example of generating assemblies using EKL with simple syntax.

The Syntax

I’ll define syntax to builds trees by describing parents and children relationships as instructions. Since tree nodes can be of type VPMReference or VPMRepReference (read more here), they can also have different usage and discipline values. So we’ll write syntax to capture that making use of special characters:
[] Square brackets to define variables
- Dashes to concatenate them
– Arrows > separate the left side and right side.

Parents are picked up by their title, which is the V_Name attribute in EKL, and children are created using three pieces of information: [vpmtype]-[usage]-[V_Name]. This will help us define children as follows:
– VPMType whether Physical Product–VPMReferences or Representation–VPMRepReference (which can detail further to include Shape, Skeleton, Drawing, or Knowledge Engineering Specification)
– Usage to define if it is a Part Or a Product (valid for Physical Products). For Representations, it will be left empty.
– Title of the instance to be added (used to set the V_Name attribute)

For example, the line below will create a Part titled “XYZ” under a node ABC.
[ABC]>[VPMReference]-[3DPart]-[XYZ]

To insert a node under the root, the instruction will be like this (passing empty variables):
[]>[VPMReference]-[3DPart]-[XYZ]

For this work, we need to make sure that the special characters [, ], - and > are reserved for our syntax.

Parsing

We’ll need to read the above syntax and process it. We can use the SplitString EKL function to do that. Wwe’ll also use the Substring method to remove the brackets. Here is an example run:

/* melkhaldi 5/11/2019 */

let instruction(String)
instruction ="[]>[VPMReference]-[3DPart]-[XYZ]"


let left, right(String)
let sides(List)

sides = SplitString(instruction, ">")
left= sides.GetItem(1)
right= sides.GetItem(2)

let parentName (String)
parentName = left

//lets create the left side first.
let childInfo(List)
childInfo= SplitString(right, "-")

let childName, childType, childUsage(String)
childType = childInfo.GetItem(1) 
childUsage = childInfo.GetItem(2)
childName = childInfo.GetItem(3)

//lets trim off the brackets 
parentName =parentName.Extract(1, parentName.Length()-2)

childType =childType.Extract(1, childType.Length()-2)
childUsage =childUsage.Extract(1, childUsage.Length()-2)
childName =childName.Extract(1, childName.Length()-2)

//get the root
let root(VPMReference)
root = GetEditorRoots("VPMReference").GetItem(1) 

let parent(VPMReference)
//check if the parent is a root.
if(parentName==""){
    parent =root

}
else{
    //find the parent by name (check it happens to be the root first.
     if(root.V_Name== parentName)
        parent = root
    else
        parent = root.Find("VPMReference", "x.V_Name==\""+parentName+"\"", true)


}

if(childType=="VPMReference"){
    let node(VPMReference)
    if(childUsage=="3DPart") 
        node = new("3DPart", childName, parent)
    else
        node = new("VPMReference", childName, parent)
}

if(childType=="3DShape"){
    let node(VPMRepReference)
    node = new("3DShape", childName, parent)
}
/*if you have the license, then uncomment this block
else if(childType=="CbaRepSkeleton"){ 
    let node(VPMRepReference)
    node = new("CbaRepSkeleton", childName, parent)
    //have to that again
    node.Name= childName
}
*/

Using the above action.

Let’s pass a list of instruction to the above action. We’ll make a slight modification. The action will take the instruction as an input string. To pass multiple strings at once, we can read them from a text file.
Here is how we can read a text file containing:

[]>[3DShape]-[]-[MyRep]
[]>[VPMReference]-[3DPart]-[MyPart]
[]>[VPMReference]-[]-[Product]
[Product]>[VPMReference]-[3DPart]-[AnotherPart]
//let's read a text file
let file(TextFile)
let filePath ="C:\Users\melkh\OneDrive\Desktop\tree.txt"
file = OpenTextFile(filePath, "r")
let i =1
let instruction(String)
for i while true {
    instruction= file.Read()    
    if(instruction.Length()>0)
        instructionList.Append( instruction)

    else //break the loop when the next line has zero length.
        break
}

Let’s combine reading instructions from the text file with creating tree nodes:

/* Action created by melkhaldi 5/11/2019 */

let instructionList(List)

//let's read a text file
let file(TextFile)
let path(TextFile)
path = ...
file = OpenTextFile(path, "r")
let i =1
let instruction(String)
for i while true {
    instruction= file.Read()    
    if(instruction.Length()>0)
        instructionList.Append( instruction)

    else
        break
}

 //we can call the action by name
let nodeBuilder(AdvisorAction)
nodeBuilder =`Knowledge Engineering Specification Physical00000119 A.1\Relations\Node_Builder` 

for instruction inside instructionList{
  //the action takes one input variable, this is we can pass it
    nodeBuilder.Run(instruction)
}

Finally, here is the file on bitbucket

Hits: 124

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.

Leave a Reply

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