Hide menu
Loading...
Searching...
No Matches
MTK Converter Example

Demonstrates how to run manufacturing analyses, convert a model to MTKWEB, and export JSON.

Overview

MTKConverter is a console example that imports a CAD model, runs one or more manufacturing processes, and exports:

  • the original model as <export_target>/scenegraph.mtkweb,
  • process_data.json with manufacturing data,
  • thumbnail.png for the source model unless screenshot generation is disabled,
  • an additional processed model when the selected process produces one.

The example supports both part-oriented and drawing-oriented workflows.

  • Part-oriented workflows write data to the top-level parts array in JSON.
  • Drawing-oriented nesting workflows write data to the top-level sheets array.

The supported processes are listed below.

Process tools description
Process Toolkit components Supported representation Description
CNC Machining Machining_FeatureRecognizer BRep solids Recognizes holes, milling faces, and other machining features .
DFMMachining_Analyzer Reports machining DFM issues for drilling, milling, and turning.
Molding Molding_FeatureRecognizer Recognizes ribs, bosses, and other molding features.
DFMMolding_Analyzer Reports molding DFM issues such as draft-angle and wall thickness problems.
Sheet Metal SheetMetal_FeatureRecognizer BRep solids and shells Recognizes bends, holes, cutouts, and other sheet metal features.
SheetMetal_Unfolder Creates an unfolded representation and an associated drawing.
DFMSheetMetal_Analyzer Reports sheet metal DFM issues for both the folded and unfolded states.
Wall Thickness WallThickness_Analyzer BRep solids and mesh bodies Computes minimum, maximum, and average wall thickness and creates an extra colorized model for visualization.
Nesting Nesting_Computer Drawing sheets Creates nested layouts from source drawing sheets or from sheet metal flat-pattern drawing.
Note
Thumbnail and screenshot generation uses OpenGL 2.1 or newer with FBO support. On Linux it typically requires an X11 display; on headless machines use Xvfb or disable screenshots with --no-screenshot.

Running the example

The command line is interpreted as a sequence of actions:

MTKConverter -i <import_file> -p <process> ... -e <export_target> [options]

-i, -p, and -e may appear multiple times. This allows the example to import once, run several processes, and export intermediate or final results in one run.

Possible process parameter values
Parameter value Process Description
machining_milling CNC Machining Milling feature recognition and DFM analysis.
machining_turning Lathe+Milling feature recognition and DFM analysis.
molding Molding Feature recognition and DFM analysis.
sheet_metal Sheet Metal Feature recognition, unfolding, and DFM analysis.
wall_thickness Wall Thickness Computes minimum, maximum, and average thickness and exports a colorized extra model.
nesting Nesting Nesting from a source drawing or, when available, from the unfolded drawing produced by sheet_metal.
Optional arguments
Option Description
--no-screenshot Disables thumbnail.png generation.
--export_mtk Additionally saves the processed model as <import file>_<process>_processed.mtk.
--sheet-size <L> <W> Sets nesting sheet size in millimeters. Default is 500 x 500.
--pattern-count <N> Sets how many copies of every drawing pattern must be nested. Default is 4.
--nesting-mode per-sheet | all-sheets Runs nesting independently for each source sheet or for all sheets together. Default is per-sheet.

Examples

The following examples show how to run different MTKConverter processes and export their results.

Machining Milling:

MTKConverter.exe -i C:\\models\\test.step -p machining_milling -e C:\\models\\machining_milling

Sheet metal followed by nesting of the unfolded drawing:

MTKConverter.exe -i C:\\models\\test.step -p sheet_metal -e C:\\models\\sheet_metal_nesting -p nesting -e C:\\models\\sheet_metal_nesting --nesting-mode all-sheets --sheet-size 500 500 --pattern-count 4 --export_mtk

Wall thickness:

MTKConverter.exe -i C:\\models\\test.step -p wall_thickness -e C:\\models\\wall_thickness

Nesting directly from a source drawing:

MTKConverter.exe -i C:\\models\\test.mtk -p nesting -e C:\\models\\nesting --sheet-size 1000 500

Implementation

The example is organized around three stages:

  1. Import() reads the source model with ModelData::ModelReader . If nesting is requested, drawing import is enabled before execution.
  2. Process() selects and invokes either a part processor or a deawing processor to handle the requested process.
  3. Export() writes the source model, the optional processed model, and process_data.json.

Import

The import stage reads the source model and configures reader parameters through MTKConverter_ImportParameters.

MTKConverter_ReturnCode Import (
const UTF16String& theFilePath,
ModelData::Model& theModel,
const MTKConverter_ImportParameters& theImportParameters)
{
std::cout << "Importing " << theFilePath << "..." << std::flush;
ModelData::ModelReader aReader;
aReader.SetParameters (theImportParameters.myReaderParameters);
if (!aReader.Read (theFilePath, theModel)) {
std::cerr << std::endl << "ERROR: Failed to import " << theFilePath << ". Exiting" << std::endl;
return MTKConverter_ReturnCode::ImportError;
}
return MTKConverter_ReturnCode::Ok;
}

Process

Part-oriented processing uses ModelData::ModelElementUniqueVisitor so that every unique part gets a persistent Uuid. These UUIDs are reused in JSON and in process models. Nesting is handled separately through a drawing processor because it works on drawing sheets rather than 3D parts.

MTKConverter_ReturnCode Process (
const UTF16String& theProcess,
ModelData::Model& theModel,
MTKConverter_Report& theReport,
ModelData::Model& theProcessModel,
const MTKConverter_Parameters& theParameters = MTKConverter_Parameters())
{
std::cout << "Processing " << theProcess << "..." << std::flush;
auto anApplyPartProcessorToModel = [&theModel, &theReport] (MTKConverter_PartProcessor& theProcessor)
{
ModelData::ModelElementUniqueVisitor aVisitor (theProcessor);
theModel.Accept (aVisitor);
for (const auto& i : theProcessor.myData) {
theReport.AddData (i);
}
return MTKConverter_ReturnCode::Ok;
};
auto anApplyDrawingProcessorToModel =
[&theModel, &theProcessModel, &theReport] (MTKConverter_DrawingProcessor& theProcessor)
{
Drawing::Drawing aDrawing = theProcessModel.Drawing();
if (!aDrawing) {
aDrawing = theModel.Drawing();
}
if (!aDrawing) {
std::cerr << std::endl
<< "ERROR: Drawing is required, but none was found in the process/source model." << std::endl;
return MTKConverter_ReturnCode::ProcessError;
}
if (!theProcessor.Apply (aDrawing)) {
return MTKConverter_ReturnCode::ProcessError;
}
for (const auto& i : theProcessor.myData) {
theReport.AddData (i);
}
return MTKConverter_ReturnCode::Ok;
};
switch (FindProcessType (theProcess)) {
case MTKConverter_ProcessType::WallThickness: {
theProcessModel.SetName ("extra");
MTKConverter_WallThicknessProcessor
aProcessor (theProcessModel, theParameters.myWallThicknessParameters);
return anApplyPartProcessorToModel (aProcessor);
}
case MTKConverter_ProcessType::MachiningMilling: {
MTKConverter_MachiningProcessor aProcessor (Machining_OT_Milling);
return anApplyPartProcessorToModel (aProcessor);
}
case MTKConverter_ProcessType::MachiningTurning: {
MTKConverter_MachiningProcessor aProcessor (Machining_OT_LatheMilling);
return anApplyPartProcessorToModel (aProcessor);
}
case MTKConverter_ProcessType::Molding: {
theProcessModel.SetName (theModel.Name() + "_extra");
MTKConverter_MoldingProcessor aProcessor (theProcessModel);
return anApplyPartProcessorToModel (aProcessor);
}
case MTKConverter_ProcessType::SheetMetal: {
theProcessModel.SetName (theModel.Name() + "_unfolded");
MTKConverter_SheetMetalProcessor aProcessor (theProcessModel);
return anApplyPartProcessorToModel (aProcessor);
}
case MTKConverter_ProcessType::Nesting: {
theProcessModel.SetName (theModel.Name() + "_nested");
MTKConverter_NestingProcessor aProcessor (theProcessModel, theParameters.myNestingParameters);
return anApplyDrawingProcessorToModel (aProcessor);
}
default: return MTKConverter_ReturnCode::InvalidArgument;
}
}
@ Machining_OT_Milling
Milling operation type.
Definition Machining_OperationType.hxx:28
@ Machining_OT_LatheMilling
Lathe + Milling operation type.
Definition Machining_OperationType.hxx:29

Part processor

MTKConverter_PartProcessor traverses each part and handles both BRep bodies and mesh bodies (for wall thickness).

void MTKConverter_PartProcessor::operator() (const ModelData::Part& thePart)
{
bool aPartWasProcessed = false;
auto aProcessData = CreateProcessData (thePart);
const auto& aBodies = thePart.Bodies();
for (const auto& aBody : aBodies) {
if (aBody.IsOfType<ModelData::MeshBody>()) {
const auto& aMeshBody = static_cast<const ModelData::MeshBody&> (aBody);
if (ProcessMeshBody (aProcessData, aMeshBody)) {
aPartWasProcessed = true;
}
} else if (ProcessBRepBody (aProcessData, aBody)) {
aPartWasProcessed = true;
}
}
if (aPartWasProcessed) {
PostProcessPart (thePart);
myData.push_back (aProcessData);
}
}

Sheet Metal processing

MTKConverter_SheetMetalProcessor runs feature recognition and unfolding together, stores the unfolded shell in a separate process model, and also converts the flat pattern to a drawing. That drawing can then be reused by the subsequent nesting step.

MTKConverter_SheetMetalProcessor::MTKConverter_SheetMetalProcessor (cadex::ModelData::Model& theUnfoldedModel) :
myUnfoldedModel (theUnfoldedModel)
{
myAnalyzer.AddTool (SheetMetal_FeatureRecognizer());
myAnalyzer.AddTool (SheetMetal_Unfolder());
}
void MTKConverter_SheetMetalProcessor::ProcessSolid (DataType& theProcessData, const ModelData::Solid& theSolid)
{
auto anSMData = myAnalyzer.Perform (theSolid);
Process (theProcessData, anSMData);
}
Provides MTK data model.
Definition Model.hxx:39

Wall Thickness processing

The processor computes scalar thickness values with WallThickness_Analyzer, then converts the result to a colorized mesh so that the process model can be visualized in MTKWEB or saved as MTK.

void MTKConverter_WallThicknessProcessor::ProcessSolid (DataType& theProcessData, const Solid& theSolid)
{
WallThickness_Data aData = myAnalyzer.Perform (theSolid, myWallThicknessParameters.myResolution);
auto aMesh = ModelAlgo::MeshGenerator().Generate (theSolid, false);
if (aMesh) {
ProcessResult (theProcessData, static_cast<const ModelData::IndexedTriangleSet&> (aMesh), aData);
}
}
void MTKConverter_WallThicknessProcessor::ProcessMesh (
DataType& theProcessData,
{
WallThickness_Data aData = myAnalyzer.Perform (theMesh, myWallThicknessParameters.myResolution);
ProcessResult (theProcessData, theMesh, aData);
}
Defines a polygonal shape consisting of triangles.
Definition IndexedTriangleSet.hxx:32

Nesting processing

Nesting is implemented through MTKConverter_DrawingProcessor. It extracts source sheets, gathers the views that act as patterns, runs Nesting_Computer, and stores the resulting drawing in the process model. If sheet_metal is executed before nesting, the nesting step first tries to use the drawing stored in the current process model, so chaining works when the sheet metal step produced a flat-pattern drawing.

bool MTKConverter_NestingProcessor::Apply (const Drawing::Drawing& theDrawing)
{
myData.clear();
const auto aSourceSheets = MTKConverter_DrawingProcessor::ExtractDrawingSheets (theDrawing);
if (aSourceSheets.empty()) {
std::cerr << std::endl << "ERROR: Nesting requires at least one sheet in the source drawing." << std::endl;
return false;
}
if (myNestingParameters.myMode == MTKConverter_NestingParameters::NestingMode::AllSheets) {
return ProcessAllSheets (aSourceSheets);
}
return ProcessPerSheet (aSourceSheets);
}

Export and Reporting

The export stage always writes the source model as MTKWEB and process_data.json. If the selected process created an additional model or drawing, that process model is exported too. When --export_mtk is enabled, the process model is also saved as MTK.

UTF16String aJsonPath = theFolderPath + "/process_data.json";
if (!theReport.WriteToJSON (aJsonPath)) {
std::cerr << std::endl << "ERROR: Failed to create JSON file " << aJsonPath << ". Exiting" << std::endl;
return MTKConverter_ReturnCode::ExportError;
}

MTKConverter_Report::WriteToJSON() writes a single JSON report whose structure depends on the selected process:

  • Part-oriented process results are written to the top-level parts array.
  • Nesting results are written to the top-level sheets array.
  • Feature Recognition and DFM data are serialized with Utilities::JSONSerializer .
  • Wall Thickness and Nesting sections are written explicitly.

For feature-based results, shape IDs are taken from the part B-Rep representation, so JSON entries can be mapped back to model shapes.

Note
A public sample serializer is available in examples/helpers for reference only and is updated infrequently, so it may not reflect newly added features or issues. For production use, prefer Utilities::JSONSerializer .

Example output

The export folder always contains process_data.json and the source .mtkweb model. Depending on the selected process, it can also contain:

  • thumbnail.png,
  • extra.mtkweb for wall thickness visualization,
  • <model_name>_extra.mtkweb for molding visualization data,
  • <model_name>_unfolded.mtkweb for sheet metal results,
  • <model_name>_nested.mtkweb for nesting results.

When --export_mtk is enabled, the processed model is also saved as <processed_name>_processed.mtk.

thumbnail.png is skipped when --no-screenshot is used.

Below are representative outputs for different processes. The JSON samples are intentionally shortened, but they preserve the actual structure generated by the current example.

Machining Milling

The ./examples/models/Fresamento_CAM1_v3.stp model can be used to run machining_milling.

Output

{
"version": "1",
"parts": [
{
"partId": "5cbb91d0-f69e-4e22-aefa-e1e7791fc3d5",
"process": "CNC Machining Milling",
"featureRecognition": {
"name": "Feature Recognition",
"totalFeatureCount": "44",
"featureGroups": [
{
"name": "Concave Fillet Edge Milling Face(s)",
"color": "(129, 127, 38)",
"subGroups": [
{
"parameters": [
{
"name": "Radius",
"units": "mm",
"value": "5.00"
}
],
"features": [
...
]
}
]
},
...
]
},
"dfm": {
"name": "Design for Manufacturing",
"featureGroups": [
...
]
}
}
]
}

Machining Turning

The ./examples/models/senthi.step model can be used to run machining_turning. The JSON structure is the same as for machining milling, but the process name becomes CNC Machining Lathe+Milling and the feature/DFM content reflects the turning workflow.

Output

{
"version": "1",
"parts": [
{
"partId": "b9a9325d-63c7-48a9-993e-eb1cc826f967",
"process": "CNC Machining Lathe+Milling",
"featureRecognition": {
"name": "Feature Recognition",
"totalFeatureCount": "245",
"featureGroups": [
...
]
},
"dfm": {
"name": "Design for Manufacturing",
"featureGroups": [
...
]
}
}
]
}

Molding

The process keeps the same top-level parts structure, but the recognized features and DFM issues are molding-specific.

Output

{
"version": "1",
"parts": [
{
"partId": "1e43ec6c-9742-40b1-90b5-038f028eb8bb",
"process": "Molding Analysis",
"featureRecognition": {
"name": "Feature Recognition",
"featureGroups": [
{
"name": "Rib(s)",
"subGroups": [
{
"parameters": [
{ "name": "Length", "units": "mm", "value": "1.00" },
{ "name": "Height", "units": "mm", "value": "0.71" },
{ "name": "Thickness", "units": "mm", "value": "1.00" },
{ "name": "Draft Angle", "units": "deg", "value": "0.00" }
],
"features": [
...
]
}
]
}
]
},
"dfm": {
"name": "Design for Manufacturing",
"featureGroups": [
{
"name": "Small Draft Angle Rib(s)",
"subGroups": [
...
]
},
{
"name": "Small Wall(s)",
"subGroups": [
...
]
}
]
}
}
]
}

Sheet Metal

The ./examples/models/Part2.stp model is suitable for sheet_metal. In addition to the regular feature-recognition and DFM sections, the result also contains unfolded information.

Output

{
"version": "1",
"parts": [
{
"partId": "37e0442d-8adc-4e01-a11d-bc008b90cbd8",
"process": "Sheet Metal",
"featureRecognition": {
"name": "Feature Recognition",
"totalFeatureCount": "118",
"featureGroups": [
...
]
},
"dfm": {
"name": "Design for Manufacturing",
"featureGroups": [
...
]
},
"featureRecognitionUnfolded": {
"name": "Feature Recognition",
"parametersCount": "4",
"parameters": [
{ "name": "Length", "units": "mm", "value": "182.16" },
{ "name": "Width", "units": "mm", "value": "179.58" },
{ "name": "Thickness", "units": "mm", "value": "1.00" },
{ "name": "Perimeter", "units": "mm", "value": "1135.61" }
]
},
"dfmUnfolded": {
"name": "Design for Manufacturing",
"featureGroups": [
{
"name": "Non Standard Sheet Size(s)",
"subGroups": [
{
"parameters": [
{
"name": "Nearest Standard Size (LxW)",
"units": "mm",
"value": "300.00 x 200.00"
},
{
"name": "Actual Size (LxW)",
"units": "mm",
"value": "182.16 x 179.58"
}
],
"features": [
{
"shapeIDCount": "0",
"shapeIDs": []
}
]
}
]
}
]
}
}
]
}

Wall Thickness

Wall Thickness entries are stored in the parts array. Each entry contains the part UUID, the extreme thickness values, the point pairs where these values were found, and a compact parameter list.

Output

{
"version": "1",
"parts": [
{
"partId": "4b15cb5f-3fe7-4434-b036-7ecf3df80bc7",
"process": "Wall Thickness Analysis",
"minThickness": {
"name": "Minimum Thickness",
"units": "mm",
"value": "3.00",
"firstPoint": "(-68.74, 24.82, -20.58)",
"secondPoint": "(-62.97, 22.00, -19.03)"
},
"maxThickness": {
"name": "Maximum Thickness",
"units": "mm",
"value": "7.21",
"firstPoint": "(45.89, 29.00, 35.20)",
"secondPoint": "(47.65, 29.00, 32.77)"
},
"parameters": [
{
"name": "Minimum Thickness",
"units": "mm",
"value": "3.00"
},
{
"name": "Maximum Thickness",
"units": "mm",
"value": "7.21"
},
{
"name": "Average Thickness",
"units": "mm",
"value": "4.95"
}
]
}
]
}

Nesting

Nesting results are stored in the top-level sheets array rather than in parts. Every item references source sheets through sourceIds and contains one or more generated result sheets.

Output

{
"version": "1",
"sheets": [
{
"sourceIds": [
"ba687c4a-b6ee-4ab2-a2e8-512d07494d97"
],
"process": "Nesting",
"nesting": {
"sheets": [
{
"sheetId": "383da9d8-d3d2-4268-8a63-f909aa8d4264",
"parameters": [
{
"name": "Sheet Length",
"units": "mm",
"value": "370.00"
},
{
"name": "Sheet Width",
"units": "mm",
"value": "370.00"
},
{
"name": "Requested Pattern Count",
"units": "pcs",
"value": "4"
},
{
"name": "Nested Pattern Count",
"units": "pcs",
"value": "4"
}
]
}
]
}
}
]
}

When a run contains both part-oriented processes and nesting, both top-level arrays can appear in the same process_data.json.

Files