Share

Macro functions

When you run a macro you can use arguments, such as the name of a toolpath, tool, or a tolerance. You must structure the macro to accept arguments by creating a FUNCTION called Main then specify the arguments and their type.

For example, a macro to polygonise a boundary to a specified tolerance is:

FUNCTION Main(REAL tol) {
    EDIT BOUNDARY ; SMASH $tol
}

A macro to set the diameter of a named tool is:

FUNCTION Main(
    STRING name
    REAL diam
)
{
    EDIT TOOL $name DIAMETER $dia
}

To run these macros with arguments add the arguments in the correct order to the end of the MACRO command:

MACRO MyBoundary.mac 0.5
MACRO MyTool.mac "ToolName" 6

If you use FUNCTION in your macro, then all commands must be within a function body. This means that you must have a FUNCTION Main, which is automatically called when the macro is run.

FUNCTION CleanBoundary(string name) {
    REAL offset = 1 mm
    REAL diam = entity('boundary';name).Tool.Diameter
    // Delete segments smaller than tool diameter
    EDIT BOUNDARY $name SELECT AREA LT $diam
    DELETE BOUNDARY $name SELECTED
    //Offset outwards and inwards to smooth boundary
    EDIT BOUNDARY $name OFFSET $offset
    EDIT BOUNDARY $name OFFSET ${-offset}
}
FUNCTION Main(string bound) {
    FOREACH bou IN folder(bound) {
        CALL CleanBoundary(bou.Name)
    }
}

Within a function, you can create and use variables that are local to the function, just as you can within a WHILE loop. However, a function cannot access any variable that is defined elsewhere in the macro, unless that variable has been passed to the function as an argument.

Note: In the CleanBoundary function, ${-offset} offset the boundary by a negative offset. When you want to substitute the value of an expression into a PowerMill command rather than the value of a parameter, use the syntax ${expression}. The expression can contain any valid PowerMill parameter expression including: inbuilt function calls; mathematical, logical, and comparison operators.
Note: As this macro requires an argument (the boundary name) you must run this from the command window. To run Clean_Boundary.mac macro on the Cavity boundary you must type macro Clean_Boundary "Cavity" in the command line.

Main function

If a macro has any functions:

  • It must have one, and only one, FUNCTION called Main.

  • The Main function must be the first function called.

Function names are not case sensitive: MAIN, main, and MaIn all refer to the same function.

Running a macro where the Main function is called with either the wrong number of arguments or with types of arguments that do not match, causes an error. For example:

MACRO MyTool.mac 6 "ToolName"

generates an error since the macro expects a string and then a number but is given a number and then a string.

If you want to repeat a sequence of commands at different points within a macro, you can use a FUNCTION.

For example, if you want to remove any small islands that are smaller than the tool diameter and smooth out any minor kinks after a boundary calculation. One solution is to repeat the same commands after each boundary calculation:

EDIT BOUNDARY ; SELECT AREA LT Boundary.Tool.Diameter
DELETE BOUNDARY ; SELECTED
EDIT BOUNDARY ; OFFSET "1 mm"
EDIT BOUNDARY ; OFFSET "-1 mm"

This is fine if you have a macro that creates one boundary, but if it creates a number of boundaries you end up with a macro with excessive repetition. However by using a FUNCTION you can define the sequence once:

FUNCTION CleanBoundary(string name) {
    REAL offset = 1 mm
    REAL diam = entity('boundary';name).Tool.Diameter
    // Delete segments smaller than tool diameter
    EDIT BOUNDARY $name SELECT AREA LT $diam
    DELETE BOUNDARY $name SELECTED
    //Offset outwards and inwards to smooth boundary
    EDIT BOUNDARY $name OFFSET $offset
    EDIT BOUNDARY $name OFFSET ${-offset}
}

Then call it whenever it is needed:

FOREACH bou IN folder('boundary') {
    CALL CleanBoundary(bou.Name)
}
CREATE BOUNDARY Shallow30 SHALLOW
EDIT BOUNDARY Shallow30 CALCULATE
CALL CleanBoundary('Shallow30')

Returning values from functions

There are two types of arguments to FUNCTIONS:

  • Input variables ($ Input arguments). If a parameter is an input then any changes to the parameter inside the function are lost when the function returns. This is the default.

  • Output variables ($ Output arguments) retain their value after the function returns.

When you call a function, PowerMill creates temporary copies of all the arguments to the function, these copies are removed when the function returns. However, if the macro contains an OUTPUT to an argument, then instead of creating a temporary copy of the variable, it creates an alias for the existing variable. Any changes that you make to the alias directly, change the actual variable.

In the example, the Test function has two arguments: aInput and aOutput. Within the Test function:

  • The argument aInput is a new temporary variable that only exists within the function, any changes to its value only affect the temporary, and are lost once the function ends.

  • The aOutput variable is an alias for the variable that was passed in the CALL command, any changes to its value are actually changing the value of the variable that was given in the CALL command.

      FUNCTION Test(REAL aInput, OUTPUT REAL aOutput) {
          PRINT $aInput
          $aInput = 5
          PRINT $aOutput
          $aOutput = 0
          PRINT $aOutput
      }
      FUNCTION Main() {
          REAL Par1 = 2
          REAL Par2 = 1
          CALL Test(Par1, Par2)
          // Prints 2 - value is unchanged
          PRINT $Par1
          // Prints 0 - value has been changed
          PRINT $Par2
      }

When the CALL command is executed in the MAIN function:

  1. PowerMill creates a new REAL variable called aInput. It is assigned the value of Par1, and passed into Test.

  2. PowerMill passes Par2 directly into Test where it is known as aOutput.

Sharing functions between macros

You can share functions between macros by using the INCLUDE statement. You can put all your common functions in a file which you then INCLUDE within other macros. For example, if you put the CleanBoundary function into a file called common.inc you could rewrite the macro as:

INCLUDE common.inc
FUNCTION Main(input string bound) {
    FOREACH bou IN folder(bound) {
        CALL CleanBoundary(bou.Name)
    }
}

To call this macro from PowerMill:

// Clean all the boundaries
MACRO Clean 'boundary'
// Clean all the Roughing boundaries
MACRO Clean 'boundary\Roughing'

Was this information helpful?