Share

Post Toolpaths API Sample

Description

Demonstrates posting toolpaths in the active document.

Code Samples

/////////////////////////////////////////////////////////////////////////////////////////////////
// For this sample script to run, the active Fusion document needs at least one CAM operation. //
/////////////////////////////////////////////////////////////////////////////////////////////////

#include <Core/CoreAll.h>
#include <CAM/CAMAll.h>

#ifdef _WINDOWS
#include <shlwapi.h>
#else
#include <stdlib.h>
#endif

using namespace adsk::core;
using namespace adsk::cam;

// Define a base class pointer for common usage.
using CAMObjectPtr = Ptr<OperationBase>;

// Function to ensure pathnames use forward slashes as required by the NC Program Output Folder.
void replaceBackslashWithSlash(std::string& str)
{
    for (char& ch : str)
        if (ch == '\\')
            ch = '/';
}
// Customised messageBox to handle critical errors in one line
void criticalError(Ptr<UserInterface> ui, const std::string& message)
{
    ui->messageBox(
        message, "Critical Error", MessageBoxButtonTypes::OKButtonType, MessageBoxIconTypes::CriticalIconType);
}

extern "C" XI_EXPORT bool run(const char* context)
{
    Ptr<Application> app = Application::get();
    if (!app)
        return false;

    Ptr<UserInterface> ui = app->userInterface();
    if (!ui)
        return false;

    Ptr<Document> doc = app->activeDocument();
    if (!doc)
        return false;

    Ptr<Products> products = doc->products();
    if (!products)
        return false;

    // Check if the document has a CAMProductType, abandon cleanly if not.
    std::string operationErrorMsg = "This script requires the active document to contain at least one CAM operation.";

    Ptr<CAM> camProduct = products->itemByProductType("CAMProductType");
    if (!camProduct)
    {
        criticalError(ui, operationErrorMsg);
        return false;
    }

    // Initialize the CAM manager to access the library manager and the post processor library.
    Ptr<CAMManager> camManager = CAMManager::get();
    Ptr<CAMLibraryManager> libraryManager = camManager->libraryManager();
    Ptr<PostLibrary> postLibrary = libraryManager->postLibrary();

    // Create a query to filter post processors from the Fusion library by the vendor "Autodesk".
    Ptr<PostConfigurationQuery> postQuery = postLibrary->createQuery(LibraryLocations::Fusion360LibraryLocation);
    postQuery->vendor("Autodesk");

    // Set the post configuration to use based on Operation Type of the first Setup.
    Ptr<Setup> setup;
    Ptr<Setups> setups = camProduct->setups();
    if (setups)
    {
        setup = setups->item(0);
        if (!setup)
        {
            criticalError(ui, operationErrorMsg);
            return false;
        }
    }

    OperationTypes opType = setup->operationType();

    switch (opType)
    {
    case adsk::cam::MillingOperation:
        postQuery->capability(adsk::cam::PostCapabilities::Milling);
        break;
    case adsk::cam::TurningOperation:
        postQuery->capability(adsk::cam::PostCapabilities::Turning);
        break;
    case adsk::cam::JetOperation:
        postQuery->capability(adsk::cam::PostCapabilities::Jet);
        break;
    default:
        postQuery->capability(adsk::cam::PostCapabilities::Milling);
        break;
    }

    std::vector<Ptr<PostConfiguration>> postConfigs = postQuery->execute();

    Ptr<URL> importedURL;
    std::string ncExtension;
    std::string postRequired = "RS-274D";
    std::string postDescription = "";

    // Find the required post in the post library and import it to local library.
    for (Ptr<PostConfiguration>& config : postConfigs)
    {
        if (config->description() == postRequired)
        {
            postDescription = postRequired;
            ncExtension = config->extension();
            Ptr<URL> configUrl = URL::create("user://");
            importedURL = postLibrary->importPostConfiguration(config, configUrl, "NCProgramSamplePost.cps");
            break;
        }
    }
    // Check if the required post was found, abandon cleanly if not.
    if (postDescription.empty())
    {
        criticalError(ui, "Unable to find postprocessor " + postRequired + ".");
        return false;
    }

    // Get the imported local post config.
    Ptr<PostConfiguration> postConfig = postLibrary->postConfigurationAtURL(importedURL);

    // Prompt the user with an option to view the resulting NC file.
    DialogResults dlgResults = ui->messageBox(
        "View nc file when done?",
        "Post-processing",
        MessageBoxButtonTypes::YesNoButtonType,
        MessageBoxIconTypes::QuestionIconType);
    bool viewResult = (dlgResults == DialogResults::DialogYes);

    // Create NCProgramInput object
    Ptr<NCProgramInput> ncInput = camProduct->ncPrograms()->createInput();

    // Set the value of scenario to 1, 2 or 3 to post all, post the first setup,
    // or post only the first operation of the first setup.
    int scenario = 1;
    std::string message = "Yes \t- All toolpaths will be posted.\n\n"
                          "No \t- Toolpaths in the first setup will be posted.\n\n"
                          "Cancel\t- The first toolpath in the first setup will be posted.\n";

    // Spaces appended to the title make the messageBox wider, preventing linw wrapping.
    DialogResults mbChoice = ui->messageBox(
        message,
        "Select what should be post-processed                                   ",
        MessageBoxButtonTypes::YesNoCancelButtonType,
        MessageBoxIconTypes::QuestionIconType);

    if (mbChoice == DialogResults::DialogYes)
    {
        scenario = 1;
    }
    else if (mbChoice == DialogResults::DialogNo)
    {
        scenario = 2;
    }
    else
    {
        scenario = 3;
    }

    // Adjust NC program parameters.
    ncInput->displayName("Sample NCProgram");

    Ptr<CAMParameters> ncParameters = ncInput->parameters();
    Ptr<StringParameterValue> nc_program_filename = ncParameters->itemByName("nc_program_filename")->value();

    // Embelish the nc filename to indicate chosen scenario and programming language.
    std::string programName = "NCProgramSampleCPP" + std::to_string(scenario);
    nc_program_filename->value(programName);

    // Provide a comment at the top of the file.
    Ptr<StringParameterValue> nc_program_comment = ncParameters->itemByName("nc_program_comment")->value();
    std::string comment = "This is the Post Toolpaths API Sample NC Program";
    nc_program_comment->value(comment);

    // Open nc file in editor if earlier requested.
    Ptr<BooleanParameterValue> nc_program_openInEditor = ncParameters->itemByName("nc_program_openInEditor")->value();
    nc_program_openInEditor->value(viewResult);

    // Set temp directory as output directory.
    std::string outputFolder = camProduct->temporaryFolder();

    // Variable outputFolder may contain backslashes but we need forward slashes.
    replaceBackslashWithSlash(outputFolder);
    Ptr<StringParameterValue> nc_program_output_folder = ncParameters->itemByName("nc_program_output_folder")->value();
    nc_program_output_folder->value(outputFolder);

    // We have already declared a setups Ptr for all 3 scenarios.
    // Scenarios 2 and 3 use firstSetup.
    Ptr<Setup> firstSetup = setups->item(0);

    switch (scenario)
    {
    case 1:
        {
            // ncInput->operations() expects a list of type 'OperationBase'.
            // For example: Operation, CAMFolder, CAMPattern, Setup.
            // It will not accept CAMFolders, CAMPatterns or Setups (all plural)
            // as they are derived from core.Base. We make our own list instead.

            // Create a vector for the content of core.Base objects.
            std::vector<CAMObjectPtr> camObjects;

            for (size_t i = 0; i < setups->count(); ++i)
            {
                // Add the operation to the operations list.
                camObjects.push_back(setups->item(i));
            }
            ncInput->operations({camObjects}); // Include all setups
            break;
        }
    case 2:
        {
            ncInput->operations({firstSetup}); // Only include the first setup
            break;
        }

    case 3:
        {
            Ptr<Operation> firstOperation = firstSetup->allOperations()->item(0);

            if (firstOperation->hasToolpath())
            {
                ncInput->operations({firstOperation}); // First operation of first setup
            }
            else
            {
                criticalError(ui, "Operation has no toolpath to post");
                return false;
            }
            break;
        }
    }

    // Create a new NC program using NC Program input and specified parameters and operations.
    Ptr<NCProgram> newProgram = camProduct->ncPrograms()->add(ncInput);

    // Configure the post processor
    newProgram->postConfiguration(postConfig);

    // Example of changing a post parameter. Parameters need to be declared as their correct type.
    Ptr<CAMParameters> postParams = newProgram->postParameters();

    // Parameter builtin_tolerance is of Type FloatParameterValue.
    Ptr<FloatParameterValue> builtInTolerance = postParams->itemByName("builtin_tolerance")->value();

    // Demonstrating how to check current parameter value and modify it.
    std::string previous = "Previous builtin_tolerance: " + std::to_string(builtInTolerance->value());
    builtInTolerance->value(0.004);
    app->log(previous + "\tNew value: " + std::to_string(builtInTolerance->value()));

    // The next assignment returns null if you use a post-processor that does not support
    // block numbering - for example "XYZ" or "Generic 2D", however you will not need it in that case.
    Ptr<CAMParameter> showSequenceNumbersParam = postParams->itemByName("showSequenceNumbers");
    if (showSequenceNumbersParam)
    {
        // Parameter showSequenceNumbers is of type ChoiceParameterValue so "false" is a string not a boolean.
        Ptr<ChoiceParameterValue> showSequenceNumbers = postParams->itemByName("showSequenceNumbers")->value();

        // Demonstrating how to check current parameter value and modify it.
        previous = "Previous showSequenceNumbers: " + showSequenceNumbers->value();
        showSequenceNumbers->value("false");
        app->log(previous + "\tNew value: " + showSequenceNumbers->value());
    }
    // Update to apply changes.
    newProgram->updatePostParameters(postParams);

    // Finally post the process.
    Ptr<NCProgramPostProcessOptions> postOptions = adsk::cam::NCProgramPostProcessOptions::create();
    newProgram->postProcess(postOptions);

    // Activate CAM workspace if it is not the active one.
    if (ui->activeWorkspace()->name() != "Manufacture")
    {
        DialogResults result = ui->messageBox(
            "Activate the CAM Workspace?",
            "CAM Workspace Activate",
            MessageBoxButtonTypes::YesNoButtonType,
            MessageBoxIconTypes::QuestionIconType);
        if (result == DialogResults::DialogYes)
        {
            Ptr<Workspace> camWorkspace = ui->workspaces()->itemById("CAMEnvironment");
            camWorkspace->activate();
        }
    }

    // Indicate completion.
    ui->messageBox(
        "Post processing is complete. See file:\n" + outputFolder + "/" + programName + ncExtension,
        "Post Toolpath API Sample  \t\t\t\t\t"); // Prevent line breaks

    return true;
}


Was this information helpful?