/* Copyright (c) 2024 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved. */ #include <ProToolkit.h> #include <ProMfg.h> #include <ProSolid.h> #include <ProSelection.h> #include <ProAsmcomppath.h> #include <ProElement.h> #include <ProElemId.h> #include <ProValue.h> #include <ProFeature.h> #include <ProUtil.h> #include <ProWcell.h> #include <ProUtil.h> #include <ProModelitem.h> #include <ProMfgOptions.h> #include <ProFeatType.h> #include <ProToolinput.h> #include <ProMdlUnits.h> #include <ProTool.h> #include <ProTKRunTime.h> #include <TestError.h> #include <UtilString.h> #include <UtilTree.h> #include <TestConsts.h> #include <UgMfg.h> /*====================================================================*\ FUNCTION : UserMfgWcellInitTools PURPOSE : Create tools and add to tool table \*====================================================================*/ static ProError UserMfgWcellInitTools( ProMfg mfg_model, ProElement tool_arr_elem ) { ProTool tool; ProError err = PRO_TK_NO_ERROR; static MfgPrmDblValue drill_params[] = { { "CUTTER_DIAM", 12.0 }, { "LENGTH", 80.0 }, { "POINT_ANGLE", 118.0 } }; static MfgPrmDblValue center_drill_params[] = { { "CUTTER_DIAM", 13.0 }, { "POINT_ANGLE", 118.0 }, { "LENGTH", 50.0 }, { "CSINK_ANGLE", 90.0 }, { "DRILL_DIAMETER", 5.0 }, { "DRILL_LENGTH", 5.0 }, }; static MfgPrmDblValue end_mill_params[] = { { "CUTTER_DIAM", 20.0 }, { "LENGTH", 60.0 } }; int n_params= 0; int pocket_num; ProPath tool_file; /*-----------------------------------------------*/ /* Add drill */ /*-----------------------------------------------*/ pocket_num = 1; n_params = sizeof( drill_params )/sizeof( MfgPrmDblValue ); err = UserParamToolCreate( mfg_model, PRO_TOOL_DRILL, L"DRILL_D12", drill_params, n_params, PRO_UNITLENGTH_MM, &tool ); ERROR_CHECK( "UserMfgWcellInitTools", "UserParamToolCreate", err ); err = UserMfgWcellAddToolSetup( &tool, pocket_num, tool_arr_elem ); ERROR_CHECK( "UserMfgWcellInitTools", "UserMfgWcellAddToolSetup", err ); /*-----------------------------------------------*/ /* Add center-drill */ /*-----------------------------------------------*/ pocket_num = 2; n_params = sizeof( center_drill_params )/sizeof( MfgPrmDblValue ); err = UserParamToolCreate( mfg_model, PRO_TOOL_CENTER_DRL, L"C-DRILL_D12", center_drill_params, n_params, PRO_UNITLENGTH_MM, &tool ); ERROR_CHECK( "UserMfgWcellInitTools", "UserParamToolCreate", err ); err = UserMfgWcellAddToolSetup( &tool, pocket_num, tool_arr_elem ); ERROR_CHECK( "UserMfgWcellInitTools", "UserMfgWcellAddToolSetup", err ); /*-----------------------------------------------*/ /* Add end mill */ /*-----------------------------------------------*/ pocket_num = 3; n_params = sizeof( end_mill_params )/sizeof( MfgPrmDblValue ); err = UserParamToolCreate( mfg_model, PRO_TOOL_END_MILL, L"END_MILL_D20", end_mill_params, n_params, PRO_UNITLENGTH_MM, &tool ); ERROR_CHECK( "UserMfgWcellInitTools", "UserParamToolCreate", err ); err = UserMfgWcellAddToolSetup( &tool, pocket_num, tool_arr_elem ); ERROR_CHECK( "UserMfgWcellInitTools", "UserMfgWcellAddToolSetup", err ); /*-----------------------------------------------*/ /* Add drill by reading a file */ /*-----------------------------------------------*/ pocket_num = 4; ProStringToWstring ( tool_file, "mill_d20.xml"); err = UserToolFileRead( mfg_model, L"MILL_D20", tool_file, PRO_B_TRUE, &tool ); ERROR_CHECK( "UserMfgWcellInitTools", "UserToolFileRead", err ); err = UserMfgWcellAddToolSetup( &tool, pocket_num, tool_arr_elem ); ERROR_CHECK( "UserMfgWcellInitTools", "UserMfgWcellAddToolSetup", err ); return ( err ); } /*====================================================================*\ Function : UserToolHeadSet() Purpose : Setup a tool table \*====================================================================*/ static ProError UserToolHeadSet( ProElement head_elem ) { ProError err = PRO_TK_NO_ERROR; ProMfg mfg_model; ProElement tool_arr_elem; err = ProMdlCurrentGet( (ProMdl*)&mfg_model ); ERROR_CHECK( "UserToolHeadSet","ProMdlCurrentGet", err ); err = ProElementAlloc( PRO_E_MFG_WCELL_TOOL_SETUP_ARR, &tool_arr_elem ); ERROR_CHECK( "UserToolHeadSet", "ProElementAlloc", err ); err = UserMfgWcellInitTools( mfg_model, tool_arr_elem ); ERROR_CHECK( "UserToolHeadSet","UserMfgWcellInitTools",err ); err = ProElemtreeElementAdd( head_elem, NULL, tool_arr_elem ); ERROR_CHECK( "UserToolHeadSet","ProElemtreeElementAdd",err ); return ( err ); } /*====================================================================*\ FUNCTION : UserWorkcellCreate PURPOSE : Create a workcell \*====================================================================*/ int UserWorkcellCreate () { ProMdl mfg_model; ProElement element = NULL; /* Individual element */ ProElement elem_tree = NULL; /* Entire tree */ ProValueData value_data; ProValue value; ProFeature wc_feature; ProError err = PRO_TK_NO_ERROR; int n_dbl_params = 0; int n_str_params = 0; int ii = 0, num_elems = 0; static ElemTable elem_table[] = { { PRO_E_FEATURE_TYPE, PRO_VALUE_TYPE_INT }, { PRO_E_WCELL_TYPE, PRO_VALUE_TYPE_INT }, { PRO_E_STD_FEATURE_NAME, PRO_VALUE_TYPE_WSTRING }, { PRO_E_MFG_WCELL_NUM_AXES, PRO_VALUE_TYPE_INT }, { PRO_E_MFG_PARAM_ARR, ARRAY }, { PRO_E_MFG_WCELL_HEAD_1, COMPOUND }, { PRO_E_MFG_COMMENTS, PRO_VALUE_TYPE_WSTRING } }; static MfgPrmDblValue dbl_params[] = /* example (not required) */ { { "RAPID_FEED_RATE", 500.0 } }; static MfgPrmStrValue str_params[] = /* examples (not required) */ { { "MACH_NAME", L"GPOST348" }, { "MACH_ID", L"5" }, { "CONTROLLER", L"FANUC 6M" }, { "LOADTL_OUTPUT", L"MODAL_OUTPUT" }, { "SPINDL_OFF_OUTPUT", L"NO" }, { "COOLNT_OFF_OUTPUT", L"NO" }, { "CUTCOM_GEOMETRY_TYPE", L"OUTPUT_ON_CENTER" } }; n_dbl_params = sizeof( dbl_params ) / sizeof( MfgPrmDblValue ); n_str_params = sizeof( str_params ) / sizeof( MfgPrmStrValue ); /* */ num_elems = sizeof( elem_table ) / sizeof( ElemTable ); err = ProElementAlloc( PRO_E_FEATURE_TREE, &elem_tree ); ERROR_CHECK( "UserWorkcellCreate","ProElementAlloc()", err ); for ( ii = 0 ; ii < num_elems; ii++ ) { err = ProElementAlloc( elem_table[ii].elem_type, &element ); ERROR_CHECK( "UserWorkcellCreate","ProElementAlloc()", err ); switch ( elem_table[ii].elem_type ) { case PRO_E_FEATURE_TYPE: value_data.v.i = PRO_FEAT_WORKCELL; break; case PRO_E_WCELL_TYPE: value_data.v.i = PRO_WCELL_MILL; break; case PRO_E_MFG_WCELL_NUM_AXES: value_data.v.i = PRO_WCELL_3_AXIS; break; case PRO_E_MFG_PARAM_ARR: if ( n_dbl_params != 0 || n_str_params != 0 ) { err = UserMfgParamArrSet( dbl_params, n_dbl_params, str_params, n_str_params, element ); ERROR_CHECK( "UserWorkcellCreate", "UserMfgParamArrSet()", err ); } else { err = ProElementFree( &element ); continue; } break; case PRO_E_STD_FEATURE_NAME: value_data.v.w = (wchar_t*) malloc( sizeof( ProName ) ); if ( value_data.v.w != NULL ) ProStringToWstring( value_data.v.w, "Mill_3_Axis" ); break; case PRO_E_MFG_COMMENTS: value_data.v.w = (wchar_t*) malloc( sizeof(ProComment) ); if ( value_data.v.w != NULL ) ProStringToWstring( value_data.v.w, "Just example" ); break; case PRO_E_MFG_WCELL_HEAD_1: err = UserToolHeadSet( element ); break; default: ProTKFprintf( stderr, "Error setting element type\n" ); err = PRO_TK_GENERAL_ERROR; ERROR_CHECK( "UserWorkcellCreate", "UserWorkcellCreate()", err ); break; } if ( elem_table[ii].val_type == PRO_VALUE_TYPE_INT) { err = ProElementIntegerSet (element, value_data.v.i); ERROR_CHECK( "UserWorkcellCreate","ProElementIntegerSet()", err ); } else if (elem_table[ii].val_type == PRO_VALUE_TYPE_WSTRING ) { err = ProElementWstringSet(element, value_data.v.w); ERROR_CHECK( "UserWorkcellCreate", "ProElementWstringSet()", err ); } err = ProElemtreeElementAdd( elem_tree, NULL, element ); ERROR_CHECK( "UserWorkcellCreate", "ProElemtreeElementAdd()", err ); } ProUtilElementtreePrint( elem_tree, PRO_TEST_INFO_WINDOW, NULL ); err = ProMdlCurrentGet( &mfg_model ); ERROR_CHECK( "UserWorkcellCreate","ProMdlCurrentGet", err ); /*********************************************/ /* Create feature */ /*********************************************/ err = UserMfgModelFeatureCreate( mfg_model, elem_tree, &wc_feature ); ERROR_CHECK( "UserWorkcellCreate", "UserMfgModelFeatureCreate()", err ); err = ProElementFree( &elem_tree ); ERROR_CHECK( "UserWorkcellCreate", "ProElementFree()", err ); return( (int)err ); } /*====================================================================*\ Function : UserWpieceSelCreate() Purpose : Create a selection handle for the mfg assembly or items in it \*====================================================================*/ ProError UserWpieceSelCreate ( /*--------------------------------------------------------------------*/ ProMfg mfg_model, int item_id, ProType item_type, ProSelection *selection ) /*--------------------------------------------------------------------*/ { ProSolid mfg_solid; ProAsmcomppath comp_path; ProModelitem wkpiece_item; ProError err = PRO_TK_NO_ERROR; err = ProMfgSolidGet( mfg_model, &mfg_solid ); ERROR_CHECK( "UserWpieceSelCreate", "ProMfgSolidGet()", err ); if ( err == PRO_TK_NO_ERROR ) { err= ProMfgFeatureOwnerGet( mfg_model, &comp_path ); ERROR_CHECK( "UserWpieceSelCreate", "ProMfgSolidGet()", err ); } if ( err == PRO_TK_NO_ERROR ) { err = ProModelitemInit( mfg_solid, item_id, item_type, &wkpiece_item ); ERROR_CHECK( "UserWpieceSelCreate", "ProModelitemInit()", err ); } if ( err == PRO_TK_NO_ERROR ) { err = ProSelectionAlloc( &comp_path, &wkpiece_item, selection ); ERROR_CHECK( "UserWpieceSelCreate", "ProSelectionAlloc()", err ); } return ( err ); } /*====================================================================*\ FUNCTION : UserToolSetupSet PURPOSE : Create tools and add to tool table \*====================================================================*/ ProError UserToolSetupSet( /*--------------------------------------------------------------------*/ ProTool *tool, int pocket_num, ProElement tool_setup_elem ) /*--------------------------------------------------------------------*/ { ProError err = PRO_TK_NO_ERROR; ProElement element = NULL; ProValueData value_data; ProValue value; int ii = 0, table_size = 0; static ElemTable tsetup_elem_table[] = { { PRO_E_MFG_WCELL_TOOL_POCKET_NUM, PRO_VALUE_TYPE_INT }, { PRO_E_MFG_WCELL_TOOL_ID, PRO_VALUE_TYPE_WSTRING } }; table_size = sizeof( tsetup_elem_table ) / sizeof( ElemTable ); for ( ii = 0; ii < table_size; ii++ ) { err = ProElementAlloc( tsetup_elem_table[ii].elem_type, &element ); ERROR_CHECK( "UserToolSetupSet","ProElementAlloc()", err ); switch ( tsetup_elem_table[ii].elem_type ) { case PRO_E_MFG_WCELL_TOOL_POCKET_NUM: value_data.v.i = pocket_num; err = ProElementIntegerSet (element, value_data.v.i); break; case PRO_E_MFG_WCELL_TOOL_ID: value_data.v.w = (wchar_t*) malloc( sizeof( ProName ) ); if ( value_data.v.w != NULL ) { err = ProWstringCopy( tool->tool_id, value_data.v.w, PRO_VALUE_UNUSED ); ERROR_CHECK( "UserToolSetupSet","ProWstringCopy()", err ); } err = ProElementWstringSet(element, value_data.v.w); ERROR_CHECK( "UserToolSetupSet","ProElementWstringSet()", err ); break; default: ProTKFprintf( stderr, "Error setting element type\n" ); err = PRO_TK_GENERAL_ERROR; ERROR_CHECK( "UserToolSetupSet","UserToolSetupSet()", err ); break; } err = ProElemtreeElementAdd( tool_setup_elem, NULL, element ); ERROR_CHECK( "UserToolSetupSet","ProElemtreeElementAdd", err ); } return ( err ); } /*====================================================================*\ FUNCTION : UserMfgWcellAddToolSetup PURPOSE : Adds tool setup element \*====================================================================*/ ProError UserMfgWcellAddToolSetup( ProTool *tool, int pocket_num, ProElement tool_arr_elem ) { ProError err = PRO_TK_NO_ERROR; ProElement tool_setup_elem = NULL; err = ProElementAlloc( PRO_E_MFG_WCELL_TOOL_SETUP, &tool_setup_elem ); ERROR_CHECK( "UserMfgWcellAddToolSetup", "ProElementAlloc", err ); err = UserToolSetupSet( tool, pocket_num, tool_setup_elem ); ERROR_CHECK( "UserMfgWcellAddToolSetup", "UserToolSetupSet", err ); err = ProElemtreeElementAdd( tool_arr_elem, NULL, tool_setup_elem ); ERROR_CHECK( "UserMfgWcellAddToolSetup","ProElemtreeElementAdd", err ); return ( err ); } /*====================================================================*\ FUNCTION : UserWorkcellTreeToolPocketGet PURPOSE : Finds pocket by tool id (first found) \*====================================================================*/ ProBool UserWorkcellTreeToolPocketGet( /*--------------------------------------------------------------------*/ ProElement wc_elem_tree, ProMfgToolHeadType head_num, ProLine tool_name, int *p_pocket_num ) /*--------------------------------------------------------------------*/ { ProError err = PRO_TK_NO_ERROR; ProElement elem_tree; ProElempath path; ProElempath id_path; ProElempath pocket_path; ProElement tool_arr_elem; ProElement *tool_setups; ProElement tool_id_elem; ProElement pocket_elem; ProLine tool_name_upper; ProValue value; wchar_t *tool_id = NULL; int tool_arr_path_size; int pocket_num = 1; int result; int ii, num; ProBool found = PRO_B_FALSE; ProElempathItem p_items[3]; ProElempathItem tooling_path_items[2] = { { PRO_ELEM_PATH_ITEM_TYPE_ID, PRO_E_MFG_WCELL_HEAD_1 }, { PRO_ELEM_PATH_ITEM_TYPE_ID, PRO_E_MFG_WCELL_TOOL_SETUP_ARR } }; tool_arr_path_size = sizeof( tooling_path_items )/sizeof( ProElempathItem ); /*-------------------------------------------------------*\ Get element PRO_E_MFG_WCELL_TOOL_SETUP_ARR \*-------------------------------------------------------*/ if ( head_num == PRO_MFG_TOOL_HEAD_2 ) tooling_path_items[0].path_item.elem_id = PRO_E_MFG_WCELL_HEAD_2; ProElempathAlloc( &path ); ProElempathDataSet( path, tooling_path_items, tool_arr_path_size ); ProArrayAlloc( 0, sizeof(ProElement), 4, (ProArray *)&tool_setups ); err = ProElementChildrenGet( wc_elem_tree, path, &tool_setups ); ERROR_CHECK( "UserWorkcellTreeToolPocketGet", "ProElementChildrenGet", err ); ProElempathFree( &path ); ProArraySizeGet( (ProArray)tool_setups, &num ); ProElempathAlloc( &pocket_path ); p_items[0].type = PRO_ELEM_PATH_ITEM_TYPE_ID; p_items[0].path_item.elem_id = PRO_E_MFG_WCELL_TOOL_POCKET_NUM ; ProElempathDataSet( pocket_path, p_items, 1 ); ProElempathAlloc( &id_path ); p_items[0].type = PRO_ELEM_PATH_ITEM_TYPE_ID; p_items[0].path_item.elem_id = PRO_E_MFG_WCELL_TOOL_ID ; ProElempathDataSet( id_path, p_items, 1 ); for ( ii = 0; ii < num; ii++ ) { /*-------------------------------------------------------*\ Get element PRO_E_MFG_WCELL_TOOL_ID \*-------------------------------------------------------*/ err = ProElemtreeElementGet( tool_setups[ii], id_path, &tool_id_elem ); ERROR_CHECK( "UserWorkcellTreeToolPocketGet", "ProElemtreeElementGet", err ); err = ProElementWstringGet( tool_id_elem, NULL, &tool_id ); ERROR_CHECK( "UserWorkcellTreeToolPocketGet", "ProElementWstringGet", err ); err = ProWstringCompare( tool_name, tool_id, PRO_VALUE_UNUSED, &result ); ERROR_CHECK( "UserWorkcellTreeToolPocketGet", "ProWstringCompare", err ); ProWstringFree( tool_id ); if ( result == 0 ) { err = ProElemtreeElementGet( tool_setups[ii], pocket_path, &pocket_elem ); ERROR_CHECK( "UserWorkcellTreeToolPocketGet", "ProElemtreeElementGet", err ); err = ProElementIntegerGet( pocket_elem, NULL, &pocket_num ); ERROR_CHECK( "UserWorkcellTreeToolPocketGet", "ProElementIntegerGet", err ); found = PRO_B_TRUE; break; } } if ( p_pocket_num != NULL ) *p_pocket_num = pocket_num; ProElempathFree( &id_path ); ProElempathFree( &pocket_path ); ProArrayFree( (ProArray *)&tool_setups ); return ( found ); } /*====================================================================*\ FUNCTION : UserWorkcellToolAdd PURPOSE : Add flat mill cutter to workcell tooling \*====================================================================*/ ProError UserWorkcellToolAdd( /*--------------------------------------------------------------------*/ ProMfg mfg_model, ProSelection workcell, ProMfgToolHeadType head_num, ProToolType tool_type, ProLine tool_name, MfgPrmDblValue params[], int n_params, ProUnitLength units, ProBool allow_reuse_existing, int *p_pocket_num ) /*--------------------------------------------------------------------*/ { ProError err = PRO_TK_NO_ERROR; ProErrorlist errors; ProElement elem_tree; ProFeature wcell_feat; ProTool tool; ProElempath path; ProElement tool_arr_elem; ProElement tool_setup_elem; ProBool found = PRO_B_FALSE; int path_size; int pocket_num = 1; ProElempathItem tooling_path_items[2] = { { PRO_ELEM_PATH_ITEM_TYPE_ID, PRO_E_MFG_WCELL_HEAD_1 }, { PRO_ELEM_PATH_ITEM_TYPE_ID, PRO_E_MFG_WCELL_TOOL_SETUP_ARR } }; ProFeatureCreateOptions opts[] = {PRO_FEAT_CR_NO_OPTS}; path_size = sizeof( tooling_path_items ) / sizeof( ProElempathItem ); err = ProToolInit( tool_name, mfg_model, &tool ); ERROR_CHECK( "UserWorkcellToolAdd", "ProToolInit", err ); /*-------------------------------------------------------*\ Verify that tool doesn't exist in mfg model \*-------------------------------------------------------*/ err = ProToolVerify( &tool ); if ( err == PRO_TK_E_NOT_FOUND ) { /*-------------------------------------------------------*\ Add tool to mfg model if it doesn't exist \*-------------------------------------------------------*/ err = UserParamToolCreate( mfg_model, tool_type, tool_name, params, n_params, units, &tool ); ERROR_CHECK( "UserWorkcellToolAdd", "UserParamToolCreate", err ); } /*-------------------------------------------------------*\ Extract workcell elem tree to modify (to add new tool) \*-------------------------------------------------------*/ err = ProSelectionModelitemGet( workcell, &wcell_feat ); ERROR_CHECK( "UserWorkcellToolAdd", "ProSelectionModelitemGet", err ); err = ProFeatureElemtreeExtract( &wcell_feat, NULL, PRO_FEAT_EXTRACT_NO_OPTS, &elem_tree ); ERROR_CHECK( "UserWorkcellToolAdd", "ProFeatureElemtreeExtract", err ); /*-------------------------------------------------------*\ Pocket number \*-------------------------------------------------------*/ if ( allow_reuse_existing ) { found = UserWorkcellTreeToolPocketGet( elem_tree, head_num, tool_name, &pocket_num ); if ( found ) { if ( p_pocket_num != NULL ) *p_pocket_num = pocket_num; return ( PRO_TK_NO_ERROR ); } } err = ProWcellMaxToolPosGet( &wcell_feat, head_num, &pocket_num ); ERROR_CHECK( "UserWorkcellToolAdd", "ProWcellMaxToolPosGet", err ); pocket_num++; /*-------------------------------------------------------*\ Get element PRO_E_MFG_WCELL_TOOL_SETUP_ARR \*-------------------------------------------------------*/ if ( head_num == PRO_MFG_TOOL_HEAD_2 ) tooling_path_items[0].path_item.elem_id = PRO_E_MFG_WCELL_HEAD_2; ProElempathAlloc( &path ); ProElempathDataSet( path, tooling_path_items, path_size ); err = ProElemtreeElementGet( elem_tree, path, &tool_arr_elem ); ERROR_CHECK( "UserWorkcellToolAdd", "ProElemtreeElementGet", err ); ProElempathFree( &path ); /*-------------------------------------------------------*\ Add tool setup \*-------------------------------------------------------*/ err = UserMfgWcellAddToolSetup( &tool, pocket_num, tool_arr_elem ); ERROR_CHECK( "UserWorkcellToolAdd", "UserMfgWcellAddToolSetup", err ); /*-------------------------------------------------------*\ Redefined workcell feature \*-------------------------------------------------------*/ err = ProFeatureRedefine( NULL, &wcell_feat, elem_tree, opts, 1, &errors ); if ( err != PRO_TK_NO_ERROR ) ProTKFprintf( stderr, "Error in element %d\n", errors.error_list[0].err_item_id ); ERROR_CHECK( "UserWorkcellToolAdd","ProFeatureRedefine", err ); if ( tool_name != NULL ) ProWstringCopy( tool.tool_id, tool_name, PRO_VALUE_UNUSED ); if ( p_pocket_num != NULL ) *p_pocket_num = pocket_num; return ( err ); }