Built-in functions
This section details all the built-in functions that you can use in your macros.
- General mathematical functions
- Trigonometrical functions
- Vector and point functions
- Workplane functions
- String functions
- Date and time functions
- Returning the home directory
- Returning the user ID string
- Returning the path of the running macro
- Converting a numeric value into a string
- Length function in a string
- Position function in a string
- Replacing one string with another string
- Substrings
- Upper case function in a string
- Lower case function in a string
- Whitespace in a string
- Splitting a string
- List functions
- List components
- List fill
- List folder
- Empty list
- List member
- Adding lists
- Removing duplicate items in a list
- Intersecting items in lists
- Items present in one list, but not the other
- Adding items to a list
- Removing items from a list
- Extracting data from lists
- Filtering data from lists
- Sorted list
- Path functions
- Folder name
- Directory name
- Base name
- Project name
- Active folder name
- Stock model states
- Conditional functions
- Evaluation functions
- Type conversion functions
- Parameter functions introduction
- Automate a sequence of edits or actions
- Statistical functions
General mathematical functions
The basic structure of the general mathematical functions are:
Description of return value | Function |
---|---|
Exponential | real exp( real a ) |
Natural logarithm | real ln( real a ) |
Common (base 10) logarithm | real log( real a ) |
Square root | real sqrt( numeric a ) |
Absolute (positive value) | real abs( numeric a ) |
Returns either -1, 0 or 1 depending on the sign of the value | real sign( numeric a ) |
Returns either 1 or 0 depending on whether the difference between a and b is less than or equal to tol | real compare( numeric a, numeric b, numeric tol ) |
Trigonometrical functions
The basic structure of the trigonometrical functions are:
Description of return value | Function |
---|---|
Trigonometric sine | real sin( angle Ø ) |
Trigonometric cosine | real cos( angle Ø ) |
Trigonometric tangent | real tan( angle Ø ) |
Trigonometric arcsine | real asin( real a ) |
Trigonometric arccosine | real acos( real a ) |
Trigonometric arctangent | real atan( real a ) |
Trigonometric arctangent of a/b, quadrant is determined by the sign of the two arguments | real atan2( real a, real b ) |
Vector and point functions
In PowerMill vectors and points are represented by an array of three reals.
PowerMill contains point and vector parameters, for example the Workplane.Origin, Workplane.ZAxis, ToolAxis.Origin, and ToolAxis.Direction. You can create your own vector and point variables:
REAL ARRAY VecX[] = {1,0,0}
REAL ARRAY VecY[] = {0,1,0}
REAL ARRAY VecZ[] = {0,0,1}
REAL ARRAY MVecZ[] = {0,0,-1}
REAL ARRAY Orig[] = {0,0,0}
Length
The length()
function returns the length of a vector.
For example:
REAL ARRAY V[] = {3,4,0}
// Prints 5.0
PRINT = length(V)
The inbuilt function unit()
returns a vector that points in the same direction as the input vector, but has a length of 1:
PRINT PAR "unit(V)"
// [0] (REAL) 0.6
// [1] (REAL) 0.8
// [2] (REAL) 0.0
// prints 1.0
PRINT = length(unit(V))
Parallel
The parallel()
function returns TRUE if two vectors are either parallel (pointing in the same direction) or anti-parallel (pointing in the opposite direction) to each other.
For example:
// prints 0
PRINT = parallel(VecX,Vecy)
// prints 1
PRINT = parallel(VecX,VecX)
Print = parallel(MVecZ,VecZ)
Normal
The normal()
function returns a vector that is normal to the plane containing its two input vectors. If either vector is zero it returns an error. If the input vectors are either parallel or anti-parallel a vector of zero length is returned.
For example:
REAL ARRAY norm = normal(VecX,VecY)
Angle
The angle()
function returns the signed angle in degrees between two vectors, providing that neither vectors have a zero length.
For example:
// Prints 90
PRINT = angle(VecX,VecY)
// Prints 90
PRINT = angle(VecY,VecX)
The apparent_angle()
function returns the apparent angle between two vectors when looking along a reference vector. If a vector is parallel or anti-parallel to the reference vector, or if any of the vectors have a zero length it returns an error:
// prints 270
print = apparent_angle(VecX,VecY,MVecZ)
// prints 90
print = apparent_angle(VecY,VecX,MVecZ)
Setting
The set_vector()
and set_point()
functions return the value 1 if the vector or point is set.
For example:
REAL ARRAY Vec1[3] = {0,0,1}
REAL ARRAY Vec2[3] = {0,1,0}
// set vec1 to be the same as vec2
BOOL ok = set_vector(vec1,vec2)
// make a X-axis vector
$ok = set_vector(vec2,1,0,0)
REAL X = Block.Limits.XMax
REAL Y = Block.Limits.YMin
REAL Z = Block.Limits.ZMax
ok = set_point(ToolAxis.Origin, X,Y,Z)
Unit vector
The unit()
function returns the unit vector equivalent of the given vector.
For example:
REAL ARRAY V[3] = {3,4,5}
PRINT PAR "unit(V)"
BOOL ok = set_vector(V,0,0,6)
PRINT PAR "unit(V)"
Workplane functions
You can use the inbuilt function set_workplane()
to define the origin and axis of a workplane entity. You can call the function:
with two workplanes, where the values from the second workplane are copied into the first:
bool ok = set_workplane(Workplane,entity('workplane','3'))
which sets the active workplane to have the same values as workplane 3.
with a workplane, two vectors, and an origin:
REAL ARRAY YAxis[] = {0,1,0} REAL ARRAY ZAxis[] = {0,0,1} REAL ARRAY Origin = {10,20,30} bool ok = set_workplane(entity('workplane','reference'), YAxis, Zaxis,Origin)
String functions
PowerMill parameters and variables can contain strings of characters. There are a number of inbuilt functions that you can use to test and manipulate strings.
The basic structure of string functions are:
Description of return value | Function |
---|---|
Returns the number of characters in the string. For more information see Length function in a string. | int length( string str ) |
Returns the position of the string target from the start of the string str, or -1 if the target string is not found. If you use the optional argument start then scanning begins from that position in the string. For more information see Position function in a string. | int position( string str, string target[, numeric start] ) |
Replaces all occurrences of the target string with a replacement string. The original string is unchanged. For more information see Replacing one string with another string. | string replace( string str, string target, string replacement) |
Returns part of the string. You can define where the substring starts and its length. The original string is unchanged. For more information see Substrings. | string substring( string str, int start, int length) |
Returns an upper case string. The original string is unchanged. For more information see Upper case function in a string. | string ucase( string str) |
Returns a lower case string. The original string is unchanged. For more information see Lower case function in a string. | string lcase( string str) |
Returns the string without any leading whitespace. | string ltrim( string str) |
Returns the string without any trailing whitespace. | string rtrim( string str) |
Returns the string without any leading or trailing whitespace. | string trim( string str) |
Splits a string into a list of the strings, separated by whitespace | list tokens( string str) |
The first character of a string is always at index 0. You can append (add) strings together use the + operator. For example:
STRING One = "One"
STRING Two = "Two"
STRING Three = "Three"
PRINT = One + ", " + Two + ", " + Three
When you run the macro, the command window displays the result, One, Two, Three.
Another way of achieving the same result is:
STRING CountToThree = One + ", " + Two + ", " + Three
PRINT = CountToThree
When you run the macro, the command window displays the result, One, Two, Three.
Date and time functions
The following functions can be used to manipulate the date and time:
Function | Description |
---|---|
time() |
The current system time. This is useful for coarse timing in macros and getting the actual time and date. |
local_time(int time) |
A DateTime object representing the local time given a number of seconds. |
utc_time(int time) |
A DateTime object representing the time in Coordinated Universal Time. |
The DateTime object contains a number of string values, as follows:
String | String value |
---|---|
String year |
The year (1900-9999) |
String month |
The month of the year (01-12) |
String day |
The day of the month (01-31) |
String hour |
The hour of the day (00-23) |
String minute |
The minute of the hour (00-59) |
String second |
The second of the minute (00-59) |
String timestamp |
The date and time — the two values in the sting are separated by a hyphen (YYYY-mm-dd-HH-MM-SS). |
local_time()
or utc_time()
functions multiple times, like this: string year = local_time(tm)
.Year etc..Example
The following example shows how to use the time() function to measure how long an activity takes:
INT old_time = time()
EDIT TOOLPATH ; CALCULATE
INT cumulative_time = time() - old_time
STRING msg = "Toolpath calculation took " + (cumulative_time) + "secs"
MESSAGE INFO $msg
Example
Getting and formatting the current time:
INT tm=time()
STRING ARRAY $timestamp[] = tokens(utc_time(\$tm).timestamp, "-") STRING clock = $timestamp[3] + ":" + $timestamp[4] $clock = $clock + ":" + $timestamp[5] PRINT $clock
Returning the home directory
Use the home()
function to return the pathname of the home directory, including its subdirectories. This can save you time when entering pathnames in macros and user menus.
To use the home() function:
PRINT PAR $HOME()
STRING H = HOME()
PRINT $H
Returning the user ID string
Use the user_id()
function to return the user ID string. This can save you time
when entering pathnames in macros and user menus.
To use the user_id()
function:
PRINT PAR $USER_ID()
STRING user = USER_ID()
PRINT $user
Returning the path of the running macro
Use macro_path
and include_filename
to return the path of the running macro.
If the argument include_filename
is true, PowerMill prints the macro file name.
If the argument include_filename
is false, PowerMill does not print the macro file name.
For example, if you run C:\\Macros\\macro.mac
:
macro_path(0)
// Returns "C:\Macros"
macro_path(1)
// Returns "C:\Macros\macro.mac"
Converting a numeric value into a string
The string
function converts a numeric value into a string value.
The basic structure is:
STRING string( numeric str )
This is useful when you want to append a number to a string. For example, to name tools so they contain the type of tool and the diameter, use:
CREATE TOOL ; BALLNOSED
EDIT TOOL ; DIAMETER 5
STRING TName = string(Tool.Type) + " Diam: " + string(Tool.Diameter)
RENAME TOOL ; $TName
PRINT = Tool.Name
When you run the macro, PowerMill creates a ball nosed tool with a diameter of 5 and gives the tool the name, ball_nosed Diam: 5.0.
The command window displays the result,ball_nosed Diam: 5.0.
Length function in a string
The length
function returns the number of characters in the string.
The basic structure is:
int length( string str )
For example:
STRING One = "One"
PRINT = length(One)
The command window displays the result, 3.
Another example:
STRING One = "One"
STRING Two = "Two"
STRING CountToTwo = One + ", " + Two
PRINT = length(CountToTwo)
The command window displays the result, 8.
Another way of producing the same result:
PRINT = length(One + ", " + Two )
The command window displays the result, 8.
Position function in a string
The position
string returns the position of the string target from the start of the string str, or -1 if the target string is not found.
If you use the optional argument start then scanning begins from that position in the string.
The basic structure is:
int position( string str, string target [, numeric start] )
For example:
PRINT = position("Scooby doo", "oo")
The command window displays the result, 2. PowerMill finds the first instance of oo and works out what its position is (S is position 0, c position 1 and o position 2).
position("Scooby doo", "oo", 4)
The command window displays the result, 8. PowerMill finds the first instance of oo after position 4 and works out what its position is (b is position 4, y position 5, " "is position 7 and o position 8).
position("Scooby doo", "aa")
The command window displays the result, -1 as PowerMill cannot find any instances of aa.
You can use this function to check whether a substring exists within another string. For example, if you have a part that contains a cavity and you machined it using various strategies with a coarse tolerance and each of these toolpaths has CAVITY in its name. You have toolpaths with names such as, CAVITY AreaClear, CAVITY flats. To recalculate those toolpath with a finer tolerance use the macro commands:
// loop over all the toolpaths
FOREACH tp IN folder('Toolpath') {
// if toolpath has 'CAVITY' in its name
IF position(tp.Name, "CAVITY") >= 0 {
// Invalidate the toolpath
INVALIDATE TOOLPATH $tp.Name
$tp.Tolerance = tp.Tolerance/10
}
}
BATCH PROCESS
Replacing one string with another string
The replace
function replaces all occurrences of the target string with a replacement string. The original string is unchanged.
The basic structure is:
string replace( string str, string target, string replacement)
For example:
STRING NewName = replace("Scooby doo", "by", "ter")
PRINT = NewName
The command window displays the result, Scooter doo.
For example, whilst trying different values in the strategy dialogs you add DRAFT to the name each toolpath.
When you are satisfied with a particular toolpath you want to change DRAFT to FINAL. To save yourself from manually editing the toolpath name, you could use a macro to rename the active toolpath:
FOREACH tp IN folder('Toolpath') {
ACTIVATE TOOLPATH $tp.Name
STRING NewName = replace(Name, 'DRAFT', 'FINAL')
RENAME TOOLPATH ; $NewName
}
This macro renames the toolpaths to:
Alternatively, you could write a macro to rename a toolpath name without activating the toolpath:
FOREACH tp IN folder('Toolpath') {
STRING NewName = replace(tp.Name, 'DRAFT', 'FINAL')
RENAME TOOLPATH $tp.Name $NewName
}
Substrings
The substring
function returns part of the string. You can define where the substring starts and its length. The original string is unchanged.
The basic structure is:
string substring( string str, int start, int length)
For example:
PRINT = substring("Scooby doo", 2, 4)
The command window displays the result, ooby.
Upper case function in a string
The upper case
function converts the string to upper case. The original string is unchanged.
The basic structure is:
string ucase( string str)
For example:
PRINT = ucase("Scooby doo")
The command window displays the result, SCOOBY DOO.
In the Replace one string with another example instances of DRAFT are replaced with FINAL, but instances of Draft are not.
The ucase
statement replaces instances of Draft, draft, dRAft with DRAFT. The rest of the macro replaces DRAFT with FINAL.
FOREACH tp IN folder('Toolpath') {
// Get the upper case version of the name
STRING UName = ucase(tp.Name)
// check if the name contains 'DRAFT'
if position(UName, 'DRAFT') >= 0 {
// replace DRAFT with FINAL
STRING NewName = replace(UName, 'DRAFT', 'FINAL')
RENAME TOOLPATH $tp.Name \$NewName
}
}
This macro renames the toolpaths to:
Previously Draft_ConstZ was not renamed, but it is this time. All the toolpath names are now upper case.
Lower case function in a string
The lower case
function converts the string to lower case. The original string is unchanged.
The basic structure is:
string lcase( string str)
For example:
PRINT = lcase("SCOOBY DOO")
The command window displays the result, scooby doo.
In the Replace one string with another example instances of DRAFT are replaced with FINAL, but instances of Draft are not.
In the Upper case function in a string example instances of Draft, draft, dRAft are replaced with DRAFT.
The lcase
statement changes the upper case toolpath names to lower case. It replaces instances of Draft, draft, dRAft are replaced with draft.
FOREACH tp IN folder('Toolpath') {
// Get the upper case version of the name
STRING UName = ucase(tp.Name)
// check if the name contains 'DRAFT'
if position(UName, 'DRAFT') >= 0 {
// replace DRAFT with FINAL
STRING NewName = replace(UName, 'DRAFT', 'FINAL')
RENAME TOOLPATH $tp.Name $NewName
// Get the lower case version of the name
STRING LName = lcase(tp.Name)
RENAME TOOLPATH $tp.Name \$LName
}
}
This macro renames the toolpaths to:
All the toolpath names are now lower case
Whitespace in a string
Use the following functions to remove whitespace from a string:
ltrim()
— Removes leading whitespace.rtrim()
— Removes trailing whitespace.trim()
— Removes leading and trailing whitespace.
For example:
STRING Original = " What's up Doc!"
STRING Trimmed = ltrim(Original)
print = Original
print = Trimmed
Where:
print = Original
displays " What's up Doc!" in the command window.
print = Trimmed
displays "What's up Doc!" in the command window.
Splitting a string
The tokens() function splits a string into a list of strings that were separated by the separator characters. By default the separator characters are spaces and tabs.
For example:
STRING InputStr = "One Two Three"
STRING LIST Tokens = tokens(InputStr)
FOREACH Tok IN Tokens {
PRINT = Tok
}
You can also give the tokens() function an optional extra argument that changes the separator character.
For example:
STRING InputStr = "10:20:30:40"
STRING LIST Tokens = tokens(InputStr,':')
FOREACH Tok IN Tokens {
PRINT = Tok
}
List functions
List functions control the content of a list or array.
The basic structure of list functions are:
Description | Function |
---|---|
Returns the components of another object. | list components( entity entity ) |
Returns a list of specified size containing elements with specified value. | list fill (int size, object value ) |
Returns a list of all the entities in the folder. | list folder( string folder ) |
Determines if the list has any content. | is_empty() |
Determines if the list contains a specific value. | member() |
Adding a list or array to another list or array | + |
Removes duplicate items from a list. | remove_duplicates() |
Creates a list by compiling the contents of two lists (can contain duplicate naming) | set_union() |
Creates a list containing items that are present in two lists. | intersection() |
Creates a list by subtracting from the first list those items that are present in the second list. | subtract() |
Returns a sorted list of numerics or stings. | list sort(list list) |
Returns a sorted list of objects or entities sorted on a field name. | list sort(list list, string field) |
Returns a list where the items have been reversed. | list reverse(list list) |
List components
The inbuilt components function returns the components of another object.
The basic structure is:
list components( entity entity )
For example if you want to batch process tool holder profiles for the tools in a group that contains toolpaths, boundaries, and tools:
FOREACH ent IN components(entity('Group', '1')) {
IF lcase(ent.RootType) == 'tool' {
EDIT TOOL $ent.Name UPDATE_TOOLPATHS_PROFILE
}
}
An example, to ensure that all the area clearance toolpaths in an NC program have flood coolant turned on and that mist is set for all the others:
FOREACH item IN components(entity('ncprogram','')) {
// only check nctoolpath items
IF lcase(item.RootType) == 'nctoolpath' {
// If the area clearance parameter is active then use flood
IF active(entity('toolpath',item.Name).AreaClearance) {
$item.Coolant.Value = "flood"
} else {
$item.Coolant.Value = "mist"
}
}
}
List fill
The fill()
function returns a list of a specified size, which contains elements of a specified value.
The basic structure is:
list fill(int size, object value)
For example, if you wanted to create a list in which abc was repeated three times:
STRING ARRAY str_arr[] = fill(3, "abc")
// str_arr = {"abc", "abc", "abc"}
If you wanted to create a list in which 5 was repeated five times:
INT LIST int_ls = fill(5, 5)
// int_ls = {5, 5, 5, 5, 5}
List folder
The folder()
function returns a list of all entities within a folder, including those in subfolders.
The basic structure is:
list folder( string folder )
The names of the root folders are:
MachineTool
NCProgram
Toolpath
Tool
Boundary
Pattern
Featureset
Workplane
Level
Model
StockModel
Group
You can use a FOREACH loop to process all of the entities within a folder. For example, to batch process tool holder profiles:
FOREACH tool IN folder ('Tool'){
EDIT TOOL $tool.Name UPDATE_TOOLPATHS_PROFILE
}
An example, to batch process all the boundaries in your project:
FOREACH bou IN folder('Boundary') {
EDIT BOUNDARY $bou.Name CALCULATE
}
Empty list
The is_empty()
function queries a list to determine whether it is empty or not.
REAL LIST MyList = {}
IF is_empty(MyList) {
PRINT "Empty List"
}
List member
The member()
function returns TRUE if the given value is one of the items in the list. For example, to check that a toolpath does not occur in more than one NC program, you can loop over all NCProgram and check that each toolpath is only seen once. Do this by building a list of toolpath names and checking that each time you add a name you have not already seen it.
// Create an empty list
STRING List names = {}
// Cycle through the NC programs
FOREACH ncp IN folder('NCProgram') {
// loop over the components in the nc program
FOREACH item IN components(ncp) {
// Check that it is a toolpath
IF item.RootType == 'nctoolpath' {
// Use MEMBER to check that we have not seen this name before
IF NOT member(names, item.Name) {
bool ok = add_last(names, item.Name)
} else {
// We have already added this name
STRING msg = "Toolpath: "+item.Name+crlf+" in more than one NCProgram"
MESSAGE ERROR $msg
MACRO ABORT
}
}
}
}
The is_empty()
function queries a list to determine whether it is empty or not.
REAL LIST MyList = {}
IF is_empty(MyList) {
PRINT "Empty List"
}
Adding lists
The + function
adds a list or array to another list or array. For example, you can add two lists together to get a list of all the tools used by the toolpaths and boundaries:
STRING LIST UsedToolNames = ToolpathTools + BoundaryTools
Removing duplicate items in a list
The remove_duplicates()
function removes duplicate values. For example, a tool may be used in both a toolpath and a boundary, so the UsedToolNames
list may contain duplicate values.
To remove the duplicate values:
INT n = remove_duplicates(UsedToolNames)
The set_union()
function returns a list containing the items from both sets, removing any duplicates. So you can create the UsedToolNames
list using:
STRING LIST UsedToolNames = set_union(ToolpathTools, BoundaryTools)
Intersecting items in lists
The inbuilt function intersection()
returns a list containing the items present in both lists or arrays. To obtain the names of the tools that are used in both toolpaths and boundaries use:
STRING LIST TP_Bound_Names = intersection(ToolpathTools, BoundaryTools)
Items present in one list, but not the other
The inbuilt function subtract()
returns the items that are in the first list, but not in the second list.
STRING UnusedToolNames = subtract(AllToolNames, UsedToolNames)
Adding items to a list
You can add items to the start or end of a list.
Adding items to the start of a list
The inbuilt function add_first(list, item)
adds an item to the start of a list. It returns the number of items in the list after the addition.
For example, to add the name of a pattern to the start of a list:
STRING LIST Patterns = {}
FOREACH pat IN folder('Pattern') {
// Add the name of the pattern to the start of the list
int s = add_first(Patterns, pat.Name)
}
Adding items to the end of a list
The inbuilt function add_last(list, item)
adds an item to the end of a list. It returns the number of items in the list after the addition.
For example, to add the name of a pattern to the end of a list:
STRING LIST Patterns = {}
FOREACH pat IN folder('Pattern') {
// Add the name of the pattern to the end of the list
int s = add_last(Patterns, pat.Name)
}
Removing items from a list
You can remove items from the start or end of a list.
Removing items from the start of a list
The inbuilt function remove_first(list)
removes an item from the start of a list. It returns the removed item.
For example, to print the names of patterns in a list:
// Print the names of the Patterns in reverse order
// Create a list of the pattern names
STRING LIST Patterns = {}
FOREACH pat IN folder('Pattern') {
// Add the name of the pattern to start of the list
int s = add_first(Patterns, pat.Name)
}
// Keep taking the first item from the list until
// there are no more
WHILE size(Patterns) > 0 {
STRING name = remove_first(Patterns)
PRINT $Name
}
If you have three patterns in the Explorer:
The FOREACH
loop adds each item to the start of the list. As the add_first command adds the next pattern to the start of the list. So you end up with a list {"Pattern_3","Pattern_2,"Pattern_1"}
.
The WHILE
loop takes the first item in the list, removes it from the list and pints it. This gives:
Pattern_3
Pattern_2
Pattern_1
Removing items from the end of a list
The inbuilt function remove_last(list)
removes an item to the end of a list. It returns the removed item.
For example, to print the names of patterns in a list:
// Print the names of the Patterns in reverse order
// Create a list of the pattern names
STRING LIST Patterns = {}
FOREACH pat IN folder('Pattern') {
// Add the name of the pattern to end of the list
int s = add_first(Patterns, pat.Name)
}
// Keep taking the last item from the list until
// there are no more
WHILE size(Patterns) > 0 {
STRING name = remove_last(Patterns)
PRINT $Name
}
If you have the same three patterns in the Explorer:
The FOREACH
loop adds each item to the end of the list. As the add_last
command adds the next pattern to the end of the list. So you end up with a list {"Pattern_1","Pattern_2,"Pattern_3"
}.
The WHILE
loop takes the last item in the list, removes it from the list and pints it. This gives:
Pattern_3
Pattern_2
Pattern_1
To end up with the patterns in the same order as they are in the Explorer either:
In the
FOREACH
loop use theadd_last
command and in the WHILE loop use theremove_first
command; orIn the
FOREACH
loop use theadd_first
command and in the WHILE loop use theremove_last
command.
Finding values in a list
The inbuilt function remove(list, value)
returns true if the value is in the list and false if it is not. If the value is in the list, it also removes the first instance of the value from the list.
For example, to print a list of tool diameters and the number of toolpaths using each tool:
// Print a list the tool diameters and the
// number of Toolpaths using each unique diameter.
REAL LIST Diameters = {}
FOREACH tp IN folder('Toolpath') {
INT s = add_last(Diameters, tp.Tool.Diameter)
}
// Create a list with just the unique diameters
REAL LIST UniqueD = Diameters
INT n = remove_duplicates(UniqueD)
// Loop over the unique diameters
FOREACH diam = UniqueD {
// set a counter
INT Count = 0
DO {
$Count = Count + 1
} WHILE remove(Diameters, diam)
STRING Msg = "There are "+Count+" toolpaths using "+diam+" tools"
PRINT $msg
}
Extracting data from lists
The inbuilt function extract(list, par_name)
returns a list containing par_name
parameters extracted from the input list.
For example, to get the names of all the toolpaths in a project:
STRING LIST names = extract(folder('toolpath'),'name')
The result could have been achieved with a FOREACH
loop that builds up the list of names item by item, however, the function allows for a more succinct expression, and it also lets .NET programs to interact with lists without having to use the PowerMill-control-flow statements.
folder()
is directly used as the list argument to extract.Another example is finding the maximum block zheight of the toolpaths:
REAL maxz = max(extract(folder('toolpath'),'Block.Limits.ZMax'))
Filtering data from lists
The inbuilt function filer(list, expression) returns a sub-list of the original list. The returned list only contains the items in the original list that match the expression you have specified. For example, suppose you want to obtain a list of raster toolpaths:
ENTITY LIST rasters = filter(folder('toolpath'), "strategy=='raster'")
Suppose that your toolpaths may contain the UserParameter 'laser'
and you want to change something on just the toolpaths that contain the parameter. You can determine whether a toolpath has the 'laser'
parameter with the expression 'member(UserParameters._keys,'laser')'
. This works because each OBJECT has a special parameter '_keys'
, which is a list of the immediate sub-parts of the object. So to just get the toolpaths that have the 'laser'
parameter, we can use the following code:
// create a string for the
// expression to help readability
STRING expr = "member(UserParameters._keys,'laser')"
ENTITY LIST laser_tps = filter(folder('toolpath'),$expr)
The filter()
function can also be combined with the extract()
function to build complex expressions within your macros. For example, to obtain the list of tools used by raster toolpaths:
ENTITY LIST tools =
extract(filter(folder('toolpath'),"strategy=='raster'"),'tool')
A special variable called 'this'
has been added to help with the filter()
function. The 'this'
variable can be used to refer to the element that the filter()
function is examining. For example suppose you have a list of numbers and only want the numbers that are greater than 10:
REAL LIST numbers = {1.0, 10.2, 3.5, 20.4, 11.0, 2.8}
REAL LIST numbs = filter(numbers, "this > 10.0")
The above returns the list {10.2, 20.4, 11.0}.
Sorted list
The sort function sorts lists and arrays of scalars (numerics or strings) or objects and entities. By default, the functions sort a list in ascending order. If you want to sort the list in descending order, you can apply the reverse function to the list.
If you are sorting a list of objects and entities, you must provide a field name for the sort.
The following examples sort lists of scalar values (numerics and strings):
STRING LIST l1 = {"The","Twelth","Night"}
$l1 = sort(l1)
// returns the list {"Night", "The", "Twelth"}
REAL ARRAY a1 = {23, 12, 4, 52, 32}
$a1 = sort(a1)
// Returns the list {4, 12, 23, 32, 52}
When sorting non-scalar values, such as entities or objects, you must provide a sort field that is a scalar value:
CREATE TOOL ; BALLNOSED
EDIT TOOL ; DIAMETER 2.0
CREATE TOOLPATH 'bbb' RASTER
CREATE TOOL ; BALLNOSED
EDIT TOOL ; DIAMETER 1.0
CREATE TOOLPATH 'ccc' RASTER
CREATE TOOL ; BALLNOSED
EDIT TOOL ; DIAMETER 1.5
CREATE TOOLPATH 'aaa' RASTER
For example:
ENTITY LIST ents = sort(folder('toolpath'),'name')
// Returns the list of toolpath {'aaa','bbb','ccc'}
ENTITY LIST ents_diam = sort(folder('toolpath'),'Tool.Diameter')
// Returns the list of toolpath {'ccc','aaa','bbb'}
You can reverse the order of a list by using the inbuilt function reverse(). The example above sorts the toolpaths based on tool diameter and returns the entries in ascending order, with the smallest diameter listed first. To sort the list in descending order, you can reverse the results.
ENTITY LIST ents_diam = reverse(sort(folder('toolpath'),'Tool.Diameter'))
// Returns the list of toolpaths {'bbb','aaa','ccc'}
Path functions
The path functions returns part of the pathname of the entity,
The basic structure of the path functions are:
Description of return value | Function |
---|---|
The Folder name function returns the full folder name of the entity, or an empty string if the entity does not exist. | string pathname( entity ref ) |
The Folder name function can also be used to return the full folder name of the entity. | string pathname( string type, string name ) |
The Directory name function returns the directory prefix from the path. | string dirname( string path) |
The Base name function returns the non-directory suffix from the path. | string basename( string path) |
The Project name functions returns the pathname of the current project on disk. | project_pathname(bool basename) |
The Active folder functions returns folder names of active entities. | String active_folder() |
The Folder list functions returns the names of folders in the PowerMill project. | String folder_list(folder_name) |
Folder name
The pathname function returns the full folder name of the entity, or, if the entity does not exist, an empty string.
The basic structure is:
string pathname( entity ref )
Also,
string pathname( string type, string name)
Returns the full folder name of the entity.
For example, if you have a BN 16.0 diam tool in a Ballnosed tool folder, then:
pathname('tool', 'BN 16.0 diam')
returns the string Tool\Ballnosed tools\BN 16.0 diam.
You can use this function in conjunction with the dirname() function to process all the toolpaths in the same folder as the active toolpath.
STRING path = pathname('toolpath',Name)
// check that there is an active toolpath
IF path != '' {
FOREACH tp IN folder(dirname(path)) {
ACTIVATE TOOLPATH tp.Name
EDIT TOOLPATH ; CALCULATE
}
} ELSE {
MESSAGE "There is no active toolpath"
RETURN
}
Directory name
The directory name function returns the directory prefix from the path.
The basic structure is:
string dirname( string path)
For example you can use this to obtain the argument for the inbuilt folder() function.
STRING folder = dirname(pathname('toolpath',Name))
Base name
The base name function returns the non-directory suffix from the path.
The basic structure is:
string basename( string path)
Usually basename(pathname('tool',tp.Name))
is the same as tp.Name
, but you can use this in conjunction with dirname to split apart the folder names.
For example, suppose your toolpaths are split in folders:
Toolpath\Feature1\AreaClear
Toolpath\Feature1\Rest
Toolpath\Feature1\Finishing
Toolpath\Feature2\AreaClear
Toolpath\Feature2\Rest
Toolpath\Feature2\Finishing
You can rename all your toolpaths so that they contain the feature name and the area clearance, rest, or finishing indicator.
FOREACH tp in folder('Toolpath') {
// Get the pathname
STRING path = pathname(tp)
// Get the lowest folder name from the path
STRING type = basename(dirname(path))
// get the next lowest folder name
STRING feat = basename(dirname(dirname(path)))
// Get the toolpath name
STRING base = basename(path)
// Build the new toolpath name
STRING NewNamePrefix = feat + "-" + type
// Check that the toolpath has not already been renamed
IF position(base,NewNamePrefix) \< 0 {
RENAME TOOLPATH \$base \${NewNamePrefix+" " + base}
}
}
Project name
The project pathname function returns the pathname of the current project on disk.
The basic structure is:
project_pathname(bool basename)
The argument dirname_only
gives a different result if it is true to if it is false.
If true, returns the name of the project.
If false returns the full path of the project.
For example if you have opened a project called:C:\PmillProjects\MyProject
project_pathname(0)
returns"C:\PmillProjects\MyProject.
project_pathname(1)
returns MyProject.
A PowerMill macro example is:
EDIT BLOCKTYPE TRIANGLES
STRING $ARBLOCK = project_pathname(0) + '' + 'block_test.dmt'
GET BLOCK $ARBLOCK
Active folder name
Use this to determine the folder names of currently active entities, for example the name of the active toolpath or workplane folder.
To display all of the folders in the toolpath branch:
STRING LIST MyToolpaths = GET_FOLDERS('toolpath')
To display a list of all of the subfolders below a given path:
STRING LIST MyFolderToolpaths = GET_FOLDERS('toolpath\Rough')
To display the name of the active folder:
STRING MyFolder = ACTIVE_FOLDER()
An empty list is returned if there are no folders, or if there are no active folders.
To find out if the given folder path exists or not, use:
document folder_exist()
This returns true or false depending on whether the path exists or not. For example, BOOL ok = folder_exists('toolpath\areaclearance')
folder_exist()
to interrogate PowerMill Explorer folders. To interrogate folders on disk, use the dir_exists()
functions.Stock model states
Use the PRINT PAR
function to print the parameters of each stock model state. You can use this to display the:
toolpaths that are applied to the block
block size
active state
The basic structure is:
PRINT PAR "entity('stockmodel','stockmodel name').States"
This can be extended to print specific parameters, for example:
PRINT PAR "entity('stockmodel','stockmodel name').States[0].Locked"
PRINT PAR "entity('stockmodel','stockmodel name').States[1].References[1]"
Conditional functions
The basic structure of conditional functions are:
Description of return value | Function |
---|---|
Returns the value of expression 1 if the conditional expression is true, otherwise it returns the value of expression 2. | variant select( conditional-expression; expression1;expression2) |
This example obtains either the tool radius or its tip radius, if it has one.
You can use an IF block of code:
REAL Radius = Tool.Diameter/2
IF active(Tool.TipRadius) {
$Radius = Tool.TipRadius
}
Or you can use the inbuilt select function:
REAL Radius = select(active(Tool.TipRadius), Tool.TipRadius, Tool.Diameter/2)
Evaluation functions
The evaluation function evaluate a string argument as an expression.
For example:
print = evaluate("5*5")
prints 25.
You can use evaluate to provide a different test at runtime.
This example provides a bubble sort for numeric values. By changing the comparison expression you can get it to sort in ascending or descending order.
FUNCTION SortReals(STRING ComparisonExpr, OUTPUT REAL LIST List) {
// Get number of items.
INT Todo = size(List)
// Set swapped flag before we start
Bool swapped = 1
// Repeat for number of items
WHILE Todo > 1 AND Swapped {
// start at the beginning
INT Idx = 0
// Signal that nothing has been done yes
$Swapped = 0
// loop over number of items still to do
WHILE Idx < ToDo-1 {
// swap if they are out of sequence
// Uses user supplied comparison function to perform test
IF evaluate(ComparisonExpr) {
REAL swap = List[Idx]
$List[Idx] = List[Idx+1]
${List[idx+1]} = swap
// signal that we've done something
$Swapped = 1
}
// look at next pair
$Idx = Idx + 1
}
// reduce number of items
$ToDo = ToDo - 1
}
}
FUNCTION Main() {
/Set up some data
REAL ARRAY Data[] = {9,10,3,4,1,7,2,8,5,6}
// Sort in increasing value
CALL SortReals("List[Idx] \> List[Idx+1]", Data)
PRINT PAR "Data"
REAL ARRAY Data1[] = {9,10,3,4,1,7,2,8,5,6}
// Sort in decreasing order
CALL SortReals("List[Idx] \< List[Idx+1]", Data1)
PRINT PAR "Data1"
}
Type conversion functions
The type conversion functions enable you to temporarily convert a variable from one type to another within an expression.
The basic structure of the type conversion functions are:
Description of return value | Function |
---|---|
Convert to integer value. | int int( scalar a) |
Convert to real value. | real real( scalar a) |
Convert to boolean value. | bool bool( scalar a) |
Convert to string value | string string( scalar a) |
Normally you would use inbuilt string() conversion function to convert a number to a string when building up a message:
STRING $Bottles = string(Number) + " green bottles ..."
In other cases, you may want convert a real number to an integer, or an integer to a real number:
INT a = 2
INT b = 3
REAL z = 0
$z = a/b
PRINT $z
This prints 0.0.
If you want the ratio then you have to convert either a or b to real within the assignment expression.
INT a = 2
INT b = 3
REAL z = 0
$z = real(a)/b
PRINT $z
This prints 0.666667.
Parameter functions introduction
All of the PowerMill parameters have an active state which determines whether the parameter is relevant for a particular type of object or operation.
The basic structure of the parameter functions are:
Description of return value | Function |
---|---|
Evaluates the active expression of par. | bool active( par ) |
Returns whether the parameter can be changed or not. | bool locked( par ) |
Returns the number of sub-parameters that par contains. | int size( par ) |
Returns a list of string descriptions for a enumerator type. | string list values(par) |
Returns the parameter one level above in the parameter tree. | par parent(par) |
Evaluate the active expression
For example, the Boundary.Tool parameter is not active for a block or sketch type boundaries. You can test whether a parameter is active or not with the inbuilt active() function. This can be useful in calculations and decision making.
The basic control structure is:
IF active(….) {
…
}
Check if you change a parameter
You can test whether a particular parameter is locked or not with the inbuilt locked() function. You cannot normally edit a locked parameter because its entity is being used as a reference by another entity. If you try to edit a locked parameter with the EDIT PAR command, PowerMill displays a query dialog asking for permission to make the change. You can suppress this message using the EDIT PAR NOQUERY command. The locked() function enables you to provide your own user messages and queries that are tailored to your application.
For example:
IF locked(Tool.Diameter) {
BOOL copy = 0
$copy = QUERY "The current tool has been used do you want to make a copy of it?"
IF NOT copy {
// cannot proceed further so get out
RETURN
}
COPY TOOL ;
}
$Tool.Diameter = 5
Check the number of sub-parameters
The inbuilt size() function returns the number of immediate items in the parameter. You can use this to determine the number of toolpaths in a folder:
PRINT = size(folder('Toolpath\Cavity'))
Enumerator parameter
The values() function returns a list of display names for an enumerator parameter, such as Tool.Type, CutDirection, or Strategy. The names are translated into the current language that a user is working in. This list can be used to gather input from the user with the CHOICE dialog. For example, to ask the user which cut direction they would like to use, you can use the following code:
// Get names for the choices the user can make for this parameter
STRING ARRAY Opts[] = values(CutDirection)
// Get the user input
INT C = INPUT CHOICE $Opts "Choose the Cut Direction you want"
// Use the returned value to set the direction
$CutDirection = $C
Parent parameter
The parent() function enables you to access and specify machine tool parameters in a more user friendly way. For example:
//To change the opacity of a machine tool/Robot table with AXIS ADDRESS T, the following syntax can be used
EDIT PAR "parent(machine_axis('T')).ModelList.Opacity" "25"
//Check the way the 'parent' function works...
CREATE TOOL ; BALLNOSED
EDIT TOOL "1" DIAMETER "20"
real error = 0
$error = ERROR parent(Tool)
print $error
//returns 1.0 as it fails finding the parent of a root - 'TOOL' is the root
$error = ERROR parent(Tool.Diameter)
print $error
//returns 0 as it finds the parent Tool of Tool.Diameter
Automate a sequence of edits or actions
Use the following functions to automate a sequence of edits or actions to a number of files and directories:
// return list of file and/or directory names
list file_list(<type>, directory, filespec)
// <type> == "all" returns both the files and directories
// <type> == "files" just returns the files
// <type> == "dirs" just returns the directories
// a '+' suffix to the type (eg "files+") will recurse down the directories
// get the current directory
string pwd()
// check whether a file exists
bool file_exists(path)
// check whether a directory exists
bool dir_exists(path)
Statistical functions
The statistical functions enable you to return the minimum and maximum values of any number of numeric arguments.
The basic structure of the statistical functions are:
Description of return value | Function |
---|---|
Returns the largest value in a list of numbers. | real max( list numeric a ) |
Returns the smallest value in a list of numbers. | real min( list numeric a ) |
This example finds the maximum and minimum block height of the toolpaths in the active NC program.
REAL maxz = -100000
REAM minz = abs(maxz)
FOREACH item IN components(entity('ncprogram','')) {
IF item.RootType == 'nctoolpath' {
$maxz = max(maxz,entity('toolpath',item.Name))
$minz - min(minz,entity('toolpath',item.Name))
}
}
MESSAGE "Min = " + string(minz) + ", max = " + string(maxz)