/****************************************************************************** * * DESCRIPTION - * * This program shows how to use the following NX Open C API routine(s): * * UF_MODL_create_instantiated_udf1() * UF_MODL_require_udf_mapping_for_insert() * UF_MODL_udf_init_insert_data_from_def() * UF_MODL_register_udf_mapping_routine() * UF_MODL_ask_udf_mapping_for_insert() * UF_MODL_udf_free_mapping_data() * UF_MODL_unregister_udf_mapping_routine() * * * PROGRAM DESCRIPTION - * * This is a simple example of how to register a mapping routine and use it to do * mapping when instantiating a UDF. The user function when excuted, will ask for * a UDF definition part. This definition part will be loaded and input references * will be asked for. If an input reference is a selection intent object type * (like Sections, Face-Collectors, Wireframe-Collector), then the user-function * will prompt for the creation of new selection-intent objects for the new UDF. * It is necessary to create the same type of selection-intent object for each * reference as is in the UDF definition. * * After reference creation, a simple logic for mapping is implemented in the * mapping routine - user_mapping(). Note this is a way of doing things. It is upto * to the user to come up with his own way of determining how mapping needs to be done. * * Finally we unegister the mapping routines before exiting out of the user function * program * * ******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define UF_CALL(X) (report_error( __FILE__, __LINE__, #X, (X))) #define ECHO(X) { UF_UI_open_listing_window(); \ UF_UI_write_listing_window(X); \ UF_print_syslog(X, FALSE); } static int report_error( char *file, int line, char *call, int irc) { if (irc) { char err[133], msg[133]; sprintf(msg, "*** ERROR code %d at line %d in %s:\n+++ ", irc, line, file); UF_get_fail_message(irc, err); /* NOTE: UF_print_syslog is new in V18 */ UF_print_syslog(msg, FALSE); UF_print_syslog(err, FALSE); UF_print_syslog("\n", FALSE); UF_print_syslog(call, FALSE); UF_print_syslog(";\n", FALSE); if (!UF_UI_open_listing_window()) { UF_UI_write_listing_window(msg); UF_UI_write_listing_window(err); UF_UI_write_listing_window("\n"); UF_UI_write_listing_window(call); UF_UI_write_listing_window(";\n"); } } return(irc); } static tag_t ask_next_feature_of_type(tag_t part, char *type, tag_t feat) { char *this_type = NULL; while(!UF_CALL(UF_OBJ_cycle_objs_in_part(part, UF_feature_type, &feat)) && (feat != NULL_TAG)) { if (UF_OBJ_ask_status(feat) == UF_OBJ_ALIVE) { UF_CALL(UF_MODL_ask_feat_type(feat, &this_type)); if (!strcmp(this_type, type)) { UF_free(this_type); return feat; } UF_free(this_type); } } return NULL_TAG; } static void report_load_status(UF_PART_load_status_t *status) { char msg[133]; for(int ii=0; iin_parts; ii++) { UF_get_fail_message(status->statuses[ii], msg); printf(" %s - %s\n", status->file_names[ii], msg); } if (status->n_parts > 0) { UF_free(status->statuses); UF_free_string_array(status->n_parts, status->file_names); } } static void combine_directory_and_wildcard(char *dir, char *fltr, char *spec) { if (!strcmp(dir, "")) { strcpy(spec, fltr); } else { UF_CALL(uc4575(dir, 0, "junk.xxx", spec)); strcpy(strstr(spec, "junk.xxx"), fltr); } } static logical prompt_for_part_name(char *prompt, char *fspec) { int resp = 0; char filter[MAX_FSPEC_SIZE+1], *p_dir = NULL, *p_ext = NULL; UF_CALL(UF_UI_ask_dialog_directory(UF_UI_PART_DIR, &p_dir)); UF_CALL(UF_UI_ask_dialog_filter(UF_UI_PART_OPEN_FLTR, &p_ext)); combine_directory_and_wildcard(p_dir, p_ext, filter); UF_free(p_dir); UF_free(p_ext); if (!UF_CALL(UF_UI_create_filebox(prompt, "Part Name", filter, "", fspec, &resp)) && (resp != UF_UI_CANCEL)) return TRUE; else return FALSE; } static logical prompt_for_text(char *prompt, char *text) { int n = 0, resp = 0; resp = uc1600(prompt, text, &n); if (resp == 3 || resp == 5) return TRUE; return FALSE; } static int allocate_string_array(int n_elements, int n_chars, void ***where) { int ii = 0, resp = 0; *where =(void **) UF_allocate_memory(n_elements * sizeof(char *), &resp); for (ii = 0; ii < n_elements; ii++) { (*where)[ii] = UF_allocate_memory(n_chars * sizeof(char), &resp); if (resp) return resp; } return 0; } /*ARGSUSED*/ static int mask_add_faces_and_edges(UF_UI_selection_p_t select, void *type) { UF_UI_mask_t mask[3] = { { UF_solid_type, 0, UF_UI_SEL_FEATURE_ANY_FACE }, { UF_solid_type, 0, UF_UI_SEL_FEATURE_ANY_EDGE }, { UF_feature_type, UF_feature_instance_subtype, 0 } }; if (!UF_CALL(UF_UI_set_sel_mask(select, UF_UI_SEL_MASK_ENABLE_SPECIFIC, 3, mask))) return (UF_UI_SEL_SUCCESS); else return (UF_UI_SEL_FAILURE); } static tag_t select_anything(char *prompt) { double cp[3] = {0,0,0}; int resp = 0; tag_t object, view; UF_CALL(UF_UI_set_cursor_view(0)); UF_CALL(UF_UI_select_with_single_dialog( "Select an object", prompt, UF_UI_SEL_SCOPE_WORK_PART, mask_add_faces_and_edges, NULL, &resp, &object, cp, &view)); UF_CALL(UF_UI_set_cursor_view(1)); if (resp == UF_UI_OBJECT_SELECTED || resp == UF_UI_OBJECT_SELECTED_BY_NAME) { UF_CALL(UF_DISP_set_highlight(object, 0)); return object; } else return NULL_TAG; } /*ARGSUSED*/ static int mask_for_curves(UF_UI_selection_p_t select, void *type) { UF_UI_mask_t mask[8] = { { UF_line_type, 0, 0 }, { UF_circle_type, 0, 0 }, { UF_conic_type, UF_all_subtype, 0 }, { UF_spline_type, 0, 0 }, { UF_point_type, 0, 0 }, { UF_edge_type, 0, 0 }, { UF_section_edge_type, 0, 0 }, { UF_sketch_type, UF_sketch_type, 0} }; if (!UF_CALL(UF_UI_set_sel_mask(select, UF_UI_SEL_MASK_CLEAR_AND_ENABLE_SPECIFIC, 8, mask))) return (UF_UI_SEL_SUCCESS); else return (UF_UI_SEL_FAILURE); } static int select_curves(char *prompt, tag_t **curves) { int cnt, ii, resp; UF_CALL(UF_UI_select_with_class_dialog("Select curves", prompt, UF_UI_SEL_SCOPE_ANY_IN_ASSEMBLY, mask_for_curves, NULL, &resp, &cnt, curves)); for (ii = 0; ii < cnt; ii++) UF_CALL(UF_DISP_set_highlight((*curves)[ii], FALSE)); return cnt; } static tag_t create_dumb_curve_section(int n_curves, tag_t *curves) { int resp; tag_t section; UF_SC_section_data_t sec_rule; UF_MODL_initialize_section_data(&sec_rule); sec_rule.n_rules = 1; sec_rule.rule_types =(int *) UF_allocate_memory(sizeof(int), &resp); sec_rule.rules = (UF_SC_input_data_t*)UF_allocate_memory(sizeof(UF_SC_input_data_t), &resp); UF_MODL_init_sc_input_data(UF_SC_CURVE_DUMB_CURVES, &sec_rule.rules[0]); sec_rule.rule_types[0] = UF_SC_CURVE_DUMB_CURVES; sec_rule.rules[0].curve_dumb_input.num_curves = n_curves; sec_rule.rules[0].curve_dumb_input.curves = curves; UF_CALL(UF_MODL_create_section(curves[0], 1, &sec_rule, NULL_TAG, NULL, NULL, FALSE, §ion)); /* NOTE: This will free the input curves array automatically */ UF_CALL(UF_MODL_free_section_data(&sec_rule)); return section; } static tag_t create_sketch_section(int n_features, tag_t *features) { int resp; tag_t section; UF_SC_section_data_t sec_rule; tag_t sketch_feat; //tag_t* // features; //UF_MODL_ask_object_feat(curves[0], &sketch_feat); //features = (tag_t*)UF_allocate_memory(sizeof(tag_t), &resp); //features[0] = sketch_feat; UF_MODL_initialize_section_data(&sec_rule); sec_rule.n_rules = 1; sec_rule.rule_types =(int *) UF_allocate_memory(sizeof(int), &resp); sec_rule.rules = (UF_SC_input_data_t*)UF_allocate_memory(sizeof(UF_SC_input_data_t), &resp); UF_MODL_init_sc_input_data(UF_SC_CURVE_FEATURE_CURVES, &sec_rule.rules[0]); sec_rule.rule_types[0] = UF_SC_CURVE_FEATURE_CURVES; sec_rule.rules[0].curve_feature_input.num_features = n_features; sec_rule.rules[0].curve_feature_input.features = features; UF_CALL(UF_MODL_create_section(features[0], 1, &sec_rule, NULL_TAG, NULL, NULL, FALSE, §ion)); /* NOTE: This will free the input curves array automatically */ UF_CALL(UF_MODL_free_section_data(&sec_rule)); return section; } static tag_t create_dumb_edge_section(int n_edges, tag_t *edges) { int resp; tag_t section; UF_SC_section_data_t sec_rule; UF_MODL_initialize_section_data(&sec_rule); sec_rule.n_rules = 1; sec_rule.rule_types =(int *) UF_allocate_memory(sizeof(int), &resp); sec_rule.rules = (UF_SC_input_data_t*)UF_allocate_memory(sizeof(UF_SC_input_data_t), &resp); UF_MODL_init_sc_input_data(UF_SC_EDGE_DUMB_EDGES, &sec_rule.rules[0]); sec_rule.rule_types[0] = UF_SC_EDGE_DUMB_EDGES; sec_rule.rules[0].curve_dumb_input.num_curves = n_edges; sec_rule.rules[0].curve_dumb_input.curves = edges; UF_CALL(UF_MODL_create_section(edges[0], 1, &sec_rule, NULL_TAG, NULL, NULL, FALSE, §ion)); /* NOTE: This will free the input curves array automatically */ UF_CALL(UF_MODL_free_section_data(&sec_rule)); return section; } static tag_t create_single_face_collector(tag_t face, tag_t obj_in_part) { tag_t dumbfaces[1], face_cntr; int rule_types[1]; UF_SC_input_data_t rules [1]; UF_SC_FACE_dumb_data_t dumb_face_data ; rule_types[0] = UF_SC_FACE_DUMB_FACES; dumbfaces[0] = face; dumb_face_data.num_faces = 1 ; dumb_face_data.faces = dumbfaces; rules[0].face_dumb_input = dumb_face_data ; if (!UF_CALL(UF_MODL_create_smart_face_container( obj_in_part, 1, rule_types, rules, &face_cntr))) return face_cntr; else return NULL_TAG; } static tag_t create_point_section(int n_edges, tag_t *edges) { int resp; tag_t section; UF_SC_section_data_t sec_rule; UF_MODL_initialize_section_data(&sec_rule); sec_rule.n_rules = 1; sec_rule.rule_types =(int *) UF_allocate_memory(sizeof(int), &resp); sec_rule.rules = (UF_SC_input_data_t*)UF_allocate_memory(sizeof(UF_SC_input_data_t), &resp); UF_MODL_init_sc_input_data(UF_SC_EDGE_DUMB_EDGES, &sec_rule.rules[0]); sec_rule.rule_types[0] = UF_SC_EDGE_DUMB_EDGES; sec_rule.rules[0].curve_dumb_input.num_curves = n_edges; sec_rule.rules[0].curve_dumb_input.curves = edges; UF_CALL(UF_MODL_create_section(edges[0], 1, &sec_rule, NULL_TAG, NULL, NULL, FALSE, §ion)); /* NOTE: This will free the input curves array automatically */ UF_CALL(UF_MODL_free_section_data(&sec_rule)); return section; } static void set_undo_mark(char *label) { UF_UNDO_mark_id_t mark_id; UF_CALL(UF_UNDO_set_mark(UF_UNDO_visible, label, &mark_id)); } static int user_mapping ( tag_t udf_define_tag, /* UDF definition feature */ UF_MODL_udf_ref_data_p_t ref_data /* UDF parent data */ ) { /* Mapping is tough! Depending on the complexity of the UDF feature (indeed the member features of the UDF), this mapping scheme may not work at all. You may need to fine tune and check speicifc type such as UF_line_type, UF_circle_type, etc. For sections or collectors (where mapping is usually required), you may need to check the rules (tangent or single or connected etc.), and make sure the mapping wont lead to mutiple operations (say edge blend or chamfer) performed on the same set of edges that cannot be achieved at all. */ UF_initialize(); ECHO("********************Running the UDF Mapping Routine\n"); /* If there is any mapping to be done, continue. */ if(ref_data->mapping_data != NULL) { int num_refs = ref_data->num_refs, i = 0; tag_t *oldRefs = ref_data->old_refs; tag_t *newRefs = ref_data->new_refs; /* **************** needed for pre-NX7.5 releases only **************** */ /* If there is no mapping container for new reference (this would be true for all releases before NX7.5), we need to allocate the memory and blindly initialize the index value from the old data. For NX7.5 and later releases, this whole for- block code can be removed. */ for (i = 0; i < num_refs; i++) { UF_MODL_udf_mapping_data_t *mapping_data = (UF_MODL_udf_mapping_data_t *) &(ref_data->mapping_data[i]); int mapping_count = mapping_data->num_mapping_objs; if(mapping_count > 0) { if( mapping_data->defined_by.output_objs_ss.old_output_objs_index && mapping_data->defined_by.output_objs_ss.new_output_objs_index == NULL ) { int resp = 0; mapping_data->defined_by.output_objs_ss.new_output_objs_index = (int*) UF_allocate_memory( mapping_count * sizeof(int), &resp); for(int kk = 0; kk < mapping_count; kk++) { mapping_data->defined_by.output_objs_ss.new_output_objs_index[kk] = mapping_data->defined_by.output_objs_ss.old_output_objs_index[kk]; } } } } /* **************** needed for pre-NX7.5 releases only **************** */ /* User provided mapping comes here. */ for (i = 0; i < num_refs; i++) { UF_MODL_udf_mapping_data_t *mapping_data = (UF_MODL_udf_mapping_data_t *) &(ref_data->mapping_data[i]); int mapping_count = mapping_data->num_mapping_objs; if( mapping_count > 0 ) { int objType = 0, objSubType = 0; UF_OBJ_ask_type_and_subtype(oldRefs[i], &objType, &objSubType); if(objType == UF_smart_container_type) { /* Obtain the data for old and new references. */ int n_curves = 0, *indices = NULL; UF_CURVE_struct_p_t *curves_struct = NULL; UF_MODL_ask_output_curves_from_section(oldRefs[i], &n_curves, &indices, &curves_struct); int n_curves2 = 0, *indices2 = NULL; UF_CURVE_struct_p_t *curves_struct2 = NULL; UF_MODL_ask_output_curves_from_section(newRefs[i], &n_curves2, &indices2, &curves_struct2); /* Do the mapping here. */ for(int j = 0; j < mapping_count; j++) { int old_index = mapping_data->defined_by.output_objs_ss.old_output_objs_index[j]; int crv_type = curves_struct[old_index]->crv_type; /* Map based on curve type. May not alway work! */ logical found = false; for(int s = 0; s < n_curves2 && !found; s++) { int curr_crv_type = curves_struct2[s]->crv_type; if(curr_crv_type == crv_type) { curves_struct2[s]->crv_type = -1; //reset to avoid duplicate mapping to the same one! mapping_data->defined_by.output_objs_ss.new_output_objs_index[j] = s; found = true; } } /* For the rest of them, do a blind mapping! */ if(!found) { for(int s = 0; s < n_curves2 && !found; s++) { if(curves_struct2[s]->crv_type != -1) { curves_struct2[s]->crv_type = -1; mapping_data->defined_by.output_objs_ss.new_output_objs_index[j] = s; found = true; } } if(!found) { ECHO("********************Running the UDF Mapping Routine - failed to map!\n"); } } } /* Dont leak memory! */ for (int k = 0; k < n_curves; k ++) { UF_CURVE_free_curve_struct(curves_struct[k]); } UF_free(curves_struct); UF_free(indices); for (int m = 0; m < n_curves2; m ++) { UF_CURVE_free_curve_struct(curves_struct2[m]); } UF_free(curves_struct2); UF_free(indices2); } } } } ECHO("********************Exiting the UDF Mapping Routine\n"); UF_terminate(); return 0; } static void do_it(void) { int error, ii, n_curves, num_parents, num_expression, subtype, type; tag_t *expression = NULL, exp, feature = NULL_TAG, *new_parents = NULL, new_udf_feature, *parents = NULL, part, prev_work_part, *sc_curves; char **exp_rhs, **expression_prompt = NULL, *lhs, **parents_prompt = NULL, *rhs, *string, udf_part[MAX_FSPEC_SIZE+1] = { "" }, udf_cgm[MAX_FSPEC_SIZE+1]; UF_PART_load_status_t error_status; if (!prompt_for_part_name("UDF part", udf_part)) return; set_undo_mark("Insert UDF"); strcpy(udf_cgm, udf_part); if (strstr(udf_cgm, ".prt")) strcpy(strstr(udf_cgm, ".prt"), ".cgm"); else strcat(udf_cgm, ".cgm"); UF_CALL(UF_PART_open_quiet(udf_part, &part, &error_status)); if (error_status.n_parts > 0) report_load_status(&error_status); UF_CALL(UF_ASSEM_set_work_part_quietly(part, &prev_work_part)); feature = ask_next_feature_of_type(part, "UDF_DEF", feature); UF_CALL(UF_MODL_ask_udf_definition(feature, &parents, &parents_prompt, &num_parents, &expression, &expression_prompt, &num_expression)); UF_CALL(UF_ASSEM_set_work_part_quietly(prev_work_part, &part)); new_parents = (tag_t *)UF_allocate_memory(sizeof(tag_t)*num_parents, &error); //This is hard code for create a feature chain based section for this particular UDF! for (ii = 0; ii < num_parents; ii++) { tag_t selTag = select_anything(parents_prompt[ii]); new_parents[ii] = selTag; char smartOptions[4][38] = { "Edge Section?", "Face Container?", "Curve Section?", "Sketch Section?" }; int objType = 0, newObjType = 0; int objSubType = 0, newObjSubType = 0; UF_OBJ_ask_type_and_subtype(parents[ii], &objType, &objSubType); if(objType == UF_smart_container_type) { int contType = uc1603("Smart Container Type?", 0, smartOptions, 4); if(contType == 5) { int resp; tag_t* edgeArray = (tag_t*)UF_allocate_memory(sizeof(tag_t), &resp); edgeArray[0] = selTag; tag_t sectionTag = create_dumb_edge_section(1, edgeArray); new_parents[ii] = sectionTag; } else if(contType == 6) { tag_t scTag = create_single_face_collector(selTag, selTag); new_parents[ii] = scTag; } else if(contType == 7) { int resp; tag_t* curveArray = (tag_t*)UF_allocate_memory(sizeof(tag_t), &resp); curveArray[0] = selTag; tag_t sectionTag = create_dumb_curve_section(1, curveArray); new_parents[ii] = sectionTag; } else if(contType == 8) { int resp; tag_t* curveArray = (tag_t*)UF_allocate_memory(sizeof(tag_t), &resp); curveArray[0] = selTag; tag_t sectionTag = create_sketch_section(1, curveArray); new_parents[ii] = sectionTag; ECHO("********************Create a section from the selection\n"); } } UF_OBJ_ask_type_and_subtype(new_parents[ii], &newObjType, &newObjSubType); if(objType == UF_sketch_type && newObjType == UF_feature_type) { int n_eids = 0; tag_t *eids = NULL; UF_MODL_ask_feat_object ( new_parents[ii], &n_eids, &eids ); if ( eids != NULL ) { for(int jj = 0; jj < n_eids; jj++) { UF_OBJ_ask_type_and_subtype(eids[jj], &newObjType, &newObjSubType); if(newObjType == objType) { new_parents[ii] = eids[jj]; break; } } UF_free ( eids ); eids = NULL; } UF_OBJ_ask_type_and_subtype(new_parents[ii], &newObjType, &newObjSubType); } char typeMsg[133]; sprintf(typeMsg, "********************old %d(subtype=%d) vs new %d(subtype=%d)\n", objType, objSubType, newObjType, newObjSubType); ECHO(typeMsg); } UF_CALL(allocate_string_array(num_expression, UF_MAX_EXP_LENGTH, (void ***)&exp_rhs)); for (ii = 0; ii < num_expression; ii++) { UF_CALL(UF_MODL_ask_exp_tag_string(expression[ii], &string)); UF_CALL(UF_MODL_dissect_exp_string(string, &lhs, &rhs, &exp)); strcpy(exp_rhs[ii], rhs); UF_free(lhs); UF_free(rhs); UF_free(string); prompt_for_text(expression_prompt[ii], exp_rhs[ii]); } //UDF mapping is required? logical mapreq; int mapnum; tag_t* mapobjs; UF_MODL_require_udf_mapping_for_insert(feature, &mapreq, &mapnum, &mapobjs); UF_CALL(UF_MODL_register_udf_mapping_routine(user_mapping)); UF_MODL_udf_exp_data_t expr; UF_MODL_udf_ref_data_t refs; UF_CALL(UF_MODL_udf_init_insert_data_from_def(feature, &expr, &refs)); expr.new_exp_values = exp_rhs; refs.new_refs = new_parents; if(mapreq == TRUE) { UF_MODL_ask_udf_mapping_for_insert (feature, &refs); } int res = UF_CALL(UF_MODL_create_instantiated_udf1(feature, &expr, &refs, &new_udf_feature)); UF_MODL_udf_free_mapping_data(refs.mapping_data); UF_CALL(UF_MODL_unregister_udf_mapping_routine()); UF_CALL(UF_MODL_unregister_rpo_routine()); UF_free(parents); UF_free(new_parents); UF_free_string_array(num_parents, parents_prompt) ; UF_free(expression); UF_free_string_array(num_expression, expression_prompt); UF_free_string_array(num_expression, exp_rhs); UF_CALL(UF_PART_close(part, 0, 1)); } /*ARGSUSED*/ void ufusr(char *param, int *retcode, int paramLen) { if (UF_CALL(UF_initialize())) return; do_it(); UF_terminate(); } int ufusr_ask_unload(void) { /* Note: can NOT be unloaded - calls UF_MODL_register_rpo_routine. */ return (UF_UNLOAD_IMMEDIATELY); }