Learning EKL Enterprise Knowledge Language Intro
The Enterprise Knowledge Language formally known as the Engineering Knowledge Language in V5 is extensively used through out the 3DX Platform for both thick and thin clients. This post will focus on the thick client side predominantly on geometry creation and edition from the basics to advanced concepts.
Variables and Data Types
All programing languages have the ability to reserve blocks of memory for storing data values, EKL is no different. When reserving blocks of memory there are two pieces of information required the reservation name or variable name which must be unique and the data type.
With EKL there is an additional requirement, which is the variable name can not start with a number or contain spaces unless the variable name is wrapped with grave symbols i.e. `2DProfile`, the same can also be said for the data type.
// The Syntax is as follows Let <VariableName> ( <DataType> ) Let iPoint ( Point ) Let oLine ( Line ) Let ioPlane ( Plane ) Let ioGeoSet ( OpenBodyFeature )
Multiple variables of the same data type can be defined at once by comma separating the variable names.
// The Syntax is as follows Let <VariableName> , <VariableName> , ... ( <DataType> ) Let ioPoint1 , ioPoint2 , ioPoint3 ( Point ) Let ioLine1 , ioLine2 , ioLine3 , ioLine4 ( Line )
The Variable Name can be anything, however it’s best to use a name that’s meaningful. In addition to this a prefix of ‘i’, ‘o’, ‘io’ can be used to define if the variable is used for input, output or internal variables.
Let iSurface ( Surface ) Let ioPlane ( Plane ) Let oResultantSurface ( Surface )
The variable name can contain multiple words, as a result CamelCase is suggested, this is where the first letter of each word is capitalized and there are no space between the separate words.
Let ioMultiPatchFinalSurface ( Surface ) Let oResultingMultiResultantCurveSet ( Curve )
There is a special case for late bound variables, where the data type is not defined but the variable is initialized. It is strongly advised to strongly type your variables at the time of definition and not to use late bound variables, as shown below.
Let ioCounter = 1 Let ioIndex = 2 Let ioActivity = True
Typically used data types are, however there are thousands;
Let iPoint ( Point ) Let oLine ( Line ) Let ioPlane ( Plane ) Let ioCircle ( Circle ) Let ioCurve ( Curve ) Let ioSurface ( Surface ) Let ioList ( List ) Let ioAxisSystem ( AxisSystem ) Let ioInteger ( Integer ) Let ioReal ( Real ) Let ioString ( String ) Let ioLength ( Length ) Let ioAngle ( Angle ) Let ioMass ( Mass ) Let ioVolume ( Volume ) Let ioGeoSet ( OpenBodyFeature ) Let ioAdvisorAction ( AdvisorAction ) Let ioUserFeature ( UserFeature )
Within the EKL programming language we can either comment a single line or comment out blocks of code.
// This is a Single Line Comment /* This is a Single MultiLine Comment */
Its often very useful to add comments into your code to help either yourself or others when later editing the code. Also while debugging there are occasions when you will need to comment out a single or multiple lines.
Specification Tree Objects
There are two occasions when we will need to reference objects in the specification tree; when equating a variable to a spec object and equating a spec object to a variable. The difference is which side of the equals sign is the spec object.
// When Equating Variables to Spec Objects the Spec object is on the Righhand Side of the Equals Symbol Let iSurface ( Surface ) iSurface = `Part1/Geometrical Set.1/Surface.1` // When Equating Spec Objects to Variables the Spec Object is on the Lefthand Side of the Equals Symbol Let oSurface ( Surface ) Let ioCircle ( Circle ) ioCircle = circlecenterptradius( point(0mm,0mm,0mm) , plane(0,0,1,0mm) , 10mm , 1 , 0deg , 180deg ) oSurface = extrude( ioCircle , direction(plane(0,0,1,0mm)) , 100mm , 100mm , True ) `Part1/Geometrical Set.1/Surface.1` = oSurface
To include a specification tree object within the code, double click on the spec object.
Basic Wireframe Constructors
Point by Coordinates
// Construct a Point by coordinates Let ioPoint ( Point ) oPoint = point( 0mm , 10mm , 20mm ) // Equate the Spec Object to the Point in Memory `Part1/Geometrical Set.1/Point.1` = oPoint
// Construct a Point Between Let ioPoint1, ioPoint2 ( Point ) ioPoint1 = point( 0mm , 10mm , 20mm ) ioPoint2 = point( 0mm , 0mm , 0mm ) Let oPoint ( Point ) oPoint = pointbetween( ioPoint1, ioPoint2 ) // Equate the Spec Object to the Point in Memory `Part1/Geometrical Set.1/Point.1` = oPoint
Line Pt to Pt
// Construct a Line by Two Points Let ioPoint1 , ioPoint2 ( Point ) Let oLine ( Line ) ioPoint1 = point( 0mm , 10mm , 20mm ) ioPoint2 = point( 0mm , 0mm , 0mm ) oLine = line( ioPoint1 , ioPoint2 ) // Equate the Spec Object to the Line in Memory `Part1/Geometrical Set.1/Line.1` = oLine
Its important to understand this is the expanded form we can compress the code by a process of substitution. This is referred to as in-lining, where constructors contain other constructors.
// Construct a Line by Two Points Let oLine ( Line ) oLine = line( point( 0mm , 10mm , 20mm ) , point( 0mm , 0mm , 0mm ) ) // Equate the Spec Object to the Line in Memory `Part1/Geometrical Set.1/Line.1` = oLine
Point On Curve Ratio
// Construct a Point On Curve Ratio Let ioLine ( Line ) ioLine = line( point( 0mm , 10mm , 20mm ) , point( 0mm , 0mm , 0mm ) ) Let oPoint ( Point ) oPoint = pointoncurveRatio( ioLine, NULL , 0.5 , True ) // Support Curve, Reference Point, Ratio , Orientation // Equate the Spec Object to the Point in Memory `Part1/Geometrical Set.1/Point.1` = oPoint
Within the CAD application there is an object inheritance hierarchy for example at the top of the geometry hierarchy is an object of type ‘Wireframe‘, since all geometry can be classified as ‘Wireframe‘. The ‘Wireframe‘ object has certain property’s and Methods that will be inherited by all subtypes, for example ‘.Name‘, ‘.Color‘, ‘.Show‘, ‘->Update()‘, etc. Next in the inheritance would be ‘Curve‘, ‘Surface‘, ‘Point‘, ‘AxisSystem‘, below ‘Curve‘, ‘Line‘, ‘Circle‘, ‘Arc‘, ‘Spline‘ etc., and below ‘Surface‘, ‘Plane‘. Since ‘Wireframe‘ has the attribute ‘.Name‘ then all inherited subtypes will have the ‘.Name‘ attribute. Any attributes or methods defined at the ‘Curve‘ object will be inherited down to ‘Line‘, ‘Circle‘, ‘Arc‘, ‘Spline‘ etc.
This is important to understand that there is an inheritance hierarchy and which types are related to each other. When we define an object such as ‘Wireframe‘ in memory we can directly equate that to any object in the specification tree of any type, because ‘Wireframe‘ is the higher type.
Let ioWireframe ( Wireframe ) ioWireframe = `Part1/Geometrical Set.1/Point.1` ioWireframe = `Part1/Geometrical Set.1/Line.1` ioWireframe = `Part1/Geometrical Set.1/Plane.1` ioWireframe = `Part1/Geometrical Set.1/Circle.1` ioWireframe = `Part1/Geometrical Set.1/Surface.1`
However we can’t go in the opposite direction and equate directly a ‘Point‘ to a ‘Wireframe‘ element. This happens with some EKL functions the best example of this is ‘translate‘. When we translate geometry we can select any type ‘Point‘ , ‘Line‘, ‘Plane‘, ‘Curve‘ etc. So the translate function has to be written to accept ‘Wireframe‘ elements, but as a result the output also has to be ‘Wireframe‘, since we never know what object type is being translated.
This can be seen below with the ‘ToTranslate‘ object which is defined as ‘Wireframe‘ and the last part of the method signature is ‘Wireframe‘ shown out side of the last parenthesis.
translate(ToTranslate : Wireframe , Direction : Direction , Offset : Length ) : Wireframe
So if I translate a ‘Point‘ and I get back a ‘Wireframe‘ element how do I convert this back to a ‘Point‘. This is where the ‘Set‘ keyword comes in or the Cast method. Here we can see a point by coordinates is created along with a direction these are then used to define a translation in +Z of 10mm.
The ‘Set‘ Keyword is used to force the ‘ioTranslatedPoint‘ object to be equivalent to the translated ‘Wireframe‘ object.
Where as the ‘: Point‘ Casts (Converts) the resulting translated ‘Wireframe‘ object to a ‘Point‘ object. When Casting we must match the object type to the left-hand side of the equals symbol. The Cast method becomes really useful when in-lining constructors, since we can cast the correct type within a line of code where as the ‘Set‘ keyword can only be used at the start of a line of code.
Let ioPoint ( Point ) ioPoint = point( 0mm , 0mm , 0mm ) // Create a Point at 0,0,0 Let ioDirection ( Direction ) ioDirection =direction( 0mm , 0mm , 1mm ) // Create a Direction in +Z Let ioTranslatedPoint ( Point ) ioTranslatedPoint = translate( ioPoint , ioDirection , 10mm ) : Point // Or Set ioTranslatedPoint = translate( ioPoint , ioDirection , 10mm ) // Or Let ioTranslatedWireframe ( Wireframe ) ioTranslatedWireframe = translate( ioPoint , ioDirection , 10mm ) Set ioTranslatedPoint = ioTranslatedWireframe // Or ioTranslatedPoint = ioTranslatedWireframe : Point