From 33f816854d2a4382f4cde9e2f47f714c5c3000ac Mon Sep 17 00:00:00 2001 From: Red Carrera Date: Wed, 22 Mar 2023 20:03:55 -0400 Subject: [PATCH] Creo to BRL-CAD Converter as of 3/22/2023 Signed-off-by: Red Carrera --- src/external/Creo/CMakeLists.txt | 16 +- src/external/Creo/assembly.cpp | 44 +- src/external/Creo/creo-brl.h | 87 ++-- src/external/Creo/csg.cpp | 8 +- src/external/Creo/main.cpp | 384 +++++++--------- src/external/Creo/part.cpp | 444 +++++++++--------- src/external/Creo/resources/creo_brl.res | 238 +++++----- src/external/Creo/shim.cpp | 3 +- src/external/Creo/shim.h | 6 +- src/external/Creo/util.cpp | 557 ++++++++++++++++------- 10 files changed, 1019 insertions(+), 768 deletions(-) diff --git a/src/external/Creo/CMakeLists.txt b/src/external/Creo/CMakeLists.txt index 42711cdee1..742cd61eab 100644 --- a/src/external/Creo/CMakeLists.txt +++ b/src/external/Creo/CMakeLists.txt @@ -2,6 +2,7 @@ # Title: CMakeLists.txt # # Purpose: Configure and generate build files for CREO2BRL project # # Note: Requires an active Creo Pro/Toolkit license # +# Revised: 3/22/2023 # #----------------------------------------------------------------------# # Establish the list of Source files - this is needed @@ -52,8 +53,8 @@ if(NOT DEFINED BRLCAD_BUILDTEST_EXTERNALS) # | | | | | | | # # v v v v v v v # - set(BRLCAD_ROOT_DIR "C:/Workspace/BRL-CAD/Source" CACHE PATH "BRL-CAD root directory") - set(CREO_ROOT_DIR "C:/Program Files/PTC/Creo 7.0.9.0" CACHE PATH "Creo root directory") + set(BRLCAD_ROOT_DIR "C:/Workspace/BRL-CAD/Source" CACHE PATH "BRL-CAD root directory") + set(CREO_ROOT_DIR "C:/Program Files/PTC/Creo 8.0.8.0" CACHE PATH "Creo root directory") # ^ ^ ^ ^ ^ ^ ^ # # | | | | | | | # @@ -295,7 +296,16 @@ if(NOT DEFINED BRLCAD_BUILDTEST_EXTERNALS) message("-- # safely ignored as long as the UNLOCK step is performed. #") message("-- #----------------------------------------------------------------------#") message("--") - endif() + message("-- #----------------------------------------------------------------------#") + message("-- # NOTICE: For installation follow this BUILD sequence #") + message("-- #----------------------------------------------------------------------#") + message("-- # BUILD: #") + message("-- # 1) creo-brl #") + message("-- # 2) unlock #") + message("-- # 3) install #") + message("-- #----------------------------------------------------------------------#") + message("--") + endif() endif() endforeach() diff --git a/src/external/Creo/assembly.cpp b/src/external/Creo/assembly.cpp index d8c69dc440..95bd0eaa36 100644 --- a/src/external/Creo/assembly.cpp +++ b/src/external/Creo/assembly.cpp @@ -94,9 +94,9 @@ find_empty_assemblies(struct creo_conv_info *cinfo) wchar_t *stable = stable_wchar(cinfo, *d_it); ProWstringToString(ename, *d_it); if (!stable) - creo_log(cinfo, MSG_DEBUG, "\"%s\" is an empty assembly, but no stable version of name found\n", ename); + creo_log(cinfo, MSG_PLAIN, " ASSEM: \"%s\" is empty, but no stable version of name found\n", ename); else { - creo_log(cinfo, MSG_DEBUG, "All contents of assembly \"%s\" are empty, skipping...\n", ename); + creo_log(cinfo, MSG_PLAIN, " ASSEM: All contents of \"%s\" are empty, skipping...\n", ename); cinfo->empty->insert(stable); steady_state = 0; } @@ -165,14 +165,14 @@ assembly_entry_matrix(struct creo_conv_info *cinfo, ProMdl parent, ProFeature *f id_table[0] = feat->id; err = ProAsmcomppathInit(ProMdlToSolid(parent), id_table, 1, &comp_path); if (err != PRO_TK_NO_ERROR) { - creo_log(cinfo, MSG_DEBUG, "\"%s\" failed to get path from \"%s\" to \"%s\", aborting...\n", pname, pname, cname); + creo_log(cinfo, MSG_PLAIN, "FAILURE: Unknown path from \"%s\" to \"%s\", aborting...\n", pname, cname); return err; } /* Accumulate the xform matrix along the path created above */ err = ProAsmcomppathTrfGet(&comp_path, PRO_B_TRUE, xform); if (err != PRO_TK_NO_ERROR) { - creo_log(cinfo, MSG_DEBUG, "Transformation matrix for \"%s\" failed: \"%s/%s\", aborting...\n", pname, pname, cname); + creo_log(cinfo, MSG_PLAIN, "FAILURE: Transformation matrix for \"%s\" failed: \"%s/%s\", aborting...\n", pname, pname, cname); return err; } @@ -314,7 +314,7 @@ output_assembly(struct creo_conv_info *cinfo, ProMdl model) /* Add children */ ProSolidFeatVisit(ProMdlToPart(model), assembly_write_entry, (ProFeatureFilterAction)component_filter, (ProAppData)ainfo); - creo_log(cinfo, MSG_DEBUG, "All children of assembly \"%s\" were visited\n", cname); + creo_log(cinfo, MSG_PLAIN, " ASSEM: All children of \"%s\" were visited\n", cname); /* Get BRL-CAD name */ comb_name = get_brlcad_name(cinfo, wname, NULL, N_ASSEM); @@ -327,32 +327,22 @@ output_assembly(struct creo_conv_info *cinfo, ProMdl model) * on the user-supplied list. */ struct directory *dp = db_lookup(cinfo->wdbp->dbip, bu_vls_addr(comb_name), LOOKUP_QUIET); - struct bu_attribute_value_set avs; - db5_get_attributes(cinfo->wdbp->dbip, &avs, dp); + db5_get_attributes(cinfo->wdbp->dbip, &cinfo->avs, dp); /* Write the object ID as an attribute */ obj_name = get_brlcad_name(cinfo, wname, NULL, N_CREO); - bu_avs_add(&avs, "ptc_name", bu_vls_addr(obj_name)); + bu_avs_add(&cinfo->avs, "ptc_name", bu_vls_addr(obj_name)); ProWVerstamp cstamp; if (ProMdlVerstampGet(model, &cstamp) == PRO_TK_NO_ERROR) { char *verstr; if (ProVerstampStringGet(cstamp, &verstr) == PRO_TK_NO_ERROR) - bu_avs_add(&avs, "ptc_version_stamp", verstr); + bu_avs_add(&cinfo->avs, "ptc_version_stamp", verstr); ProVerstampStringFree(&verstr); } - /* If we have a user-supplied list of attributes to save, do it */ - if (cinfo->attrs->size() > 0) - for (unsigned int i = 0; i < cinfo->attrs->size(); i++) { - char *attr_val = NULL; - const char *arg = cinfo->attrs->at(i); - creo_attribute_val(&attr_val, arg, model); - if (attr_val) { - bu_avs_add(&avs, arg, attr_val); - bu_free(attr_val, "value string"); - } - } + /* Export user-supplied list of parameters */ + param_export(cinfo, model, cname); /* * Solid mass properties are handled separately in Creo, @@ -364,29 +354,29 @@ output_assembly(struct creo_conv_info *cinfo, ProMdl model) if (err == PRO_TK_NO_ERROR) { if (massprops.volume > 0.0) { bu_vls_sprintf(&vstr, "%g", massprops.volume); - bu_avs_add(&avs, "volume", bu_vls_addr(&vstr)); + bu_avs_add(&cinfo->avs, "volume", bu_vls_addr(&vstr)); } if (massprops.surface_area > 0.0) { bu_vls_sprintf(&vstr, "%g", massprops.surface_area); - bu_avs_add(&avs, "surface_area", bu_vls_addr(&vstr)); + bu_avs_add(&cinfo->avs, "surface_area", bu_vls_addr(&vstr)); } if (massprops.density > 0.0) { bu_vls_sprintf(&vstr, "%g", massprops.density); - bu_avs_add(&avs, "density", bu_vls_addr(&vstr)); + bu_avs_add(&cinfo->avs, "density", bu_vls_addr(&vstr)); } if (massprops.mass > 0.0) { bu_vls_sprintf(&vstr, "%g", massprops.mass); - bu_avs_add(&avs, "mass", bu_vls_addr(&vstr)); + bu_avs_add(&cinfo->avs, "mass", bu_vls_addr(&vstr)); } bu_vls_free(&vstr); } /* Standardize and write */ - db5_standardize_avs(&avs); - db5_update_attributes(dp, &avs, cinfo->wdbp->dbip); + db5_standardize_avs(&cinfo->avs); + db5_update_attributes(dp, &cinfo->avs, cinfo->wdbp->dbip); - creo_log(cinfo, MSG_DEBUG, "Conversion of assembly \"%s\" complete\n", cname); + creo_log(cinfo, MSG_PLAIN, " ASSEM: Conversion of assembly \"%s\" complete\n", cname); /* Free local container */ BU_PUT(ainfo, struct assem_conv_info); return PRO_TK_NO_ERROR; diff --git a/src/external/Creo/creo-brl.h b/src/external/Creo/creo-brl.h index 967ba9f30b..d93f7369d7 100644 --- a/src/external/Creo/creo-brl.h +++ b/src/external/Creo/creo-brl.h @@ -42,6 +42,7 @@ #ifndef TEST_BUILD extern "C" { +#include #include #include #include @@ -77,9 +78,7 @@ extern "C" { #include #include #include -#include } - #else extern "C" { #include "shim.h" @@ -107,6 +106,9 @@ extern "C" { #define XFORM_X_TO_Z 1 #define XFORM_Y_TO_Z 2 +#define NAME_PARAMS 1 +#define ATTR_PARAMS 2 + #define FEAT_ID_BLOCK 64 /* number of slots to allocate in above list */ #define NUM_HASH_TABLE_BINS 4096 /* number of bins for part number to part name hash table */ #define TRI_BLOCK 512 /* number of triangles to malloc per call */ @@ -118,17 +120,20 @@ extern "C" { #define CREO_NAME_MAX 240*2 /* max part name length Creo supports is 240 chars */ #define CREO_MSG_MAX 4096 /* max message and/or response length */ -#define MAX_MATL_NAME 32 /* maximum allowed material name length */ -#define MAX_LINE_SIZE 80 /* maximum allowed input line length */ -#define MAX_FILE_RECS 256 /* maximum allowed material record count */ +#define MAX_MATL_NAME 32 /* maximum allowed material name length */ +#define MAX_LINE_SIZE 80 /* maximum allowed input line length */ +#define MAX_LINE_BUFFER 128 /* maximum allowed input line buffer length */ +#define MAX_FILE_RECS 256 /* maximum allowed material record count */ #define MAX_UNIQUE_NAMES 65535 /* maximum unique name generation count */ -#define MSG_FAIL 0 -#define MSG_SUCCESS 1 -#define MSG_DEBUG 2 -#define MSG_STATUS 3 /* Output for Creo msg window only */ -#define MSG_PLAIN 4 + + /* Log message types */ +#define MSG_FAIL 0 /* Failure */ +#define MSG_SUCCESS 1 /* Success */ +#define MSG_DEBUG 2 /* Debug */ +#define MSG_PLAIN 3 /* [unlabeled] */ +#define MSG_STATUS 4 /* Status window only */ #define PRO_FEAT_DELETE_NO_OPTS 0 /* Feature delete options */ #define PRO_FEAT_DELETE_CLIP 1 /* Delete with children */ @@ -202,15 +207,15 @@ struct creo_conv_info { FILE *fpmtl; /* material file data */ char mtl_fname[MAXPATHLEN]; - char mtl_key[MAX_MATL_NAME]; - char mtl_str[MAX_FILE_RECS][MAX_LINE_SIZE + 1]; + char mtl_key[MAX_MATL_NAME + 1]; + char mtl_str[MAX_FILE_RECS][MAX_MATL_NAME + 1]; int mtl_id[MAX_FILE_RECS]; int mtl_los[MAX_FILE_RECS]; int mtl_ptr; int mtl_rec; int xform_mode; /* coordinate transformation mode */ - long int reg_id; /* region ident number (incremented with each part) */ + int reg_id; /* region ident number (incremented with each part) */ int lmin; /* user-established minimum luminance threshold */ /* units - model */ @@ -218,21 +223,21 @@ struct creo_conv_info { double local_tol; /* tolerance in Creo units */ double local_tol_sq; /* tolerance squared */ - /* Facetization settings */ - ProBool do_facets_only; /* flag to indicate no CSG should be done */ + /* Conversion control settings */ + ProBool facets_only; /* flag to indicate no CSG should be done */ ProBool check_solidity; /* flag to control testing BoTs for solidity */ - ProBool get_normals; /* flag to indicate surface normals should be extracted from geometry */ - ProBool do_elims; /* flag to indicate that small features are to be eliminated */ - ProBool debug_bboxes; /* flag to indicate that bboxes should be written for parts that didn't convert */ - - double max_error; /* maximum allowable error in facetized approximation, mm */ - double min_error; /* minimum allowable error in facetized approximation, mm */ - double tol_dist; /* minimum distance between two distinct vertices, mm */ - double max_angle_cntrl; /* max angle control for tessellation ( 0.0 - 1.0 ), deg */ - double min_angle_cntrl; /* min angle control for tessellation ( 0.0 - 1.0 ), deg */ - long int max_to_min_steps; /* number of steps between max and min */ - double error_increment; - double angle_increment; + ProBool create_boxes; /* flag indicating that bounding boxes should replace failed parts */ + ProBool get_normals; /* flag indicating surface normals should be extracted from geometry */ + ProBool elim_small; /* flag indicating that small features are to be eliminated */ + + /* Tessellation settings */ + double max_chord; /* max chord height in facetized approximation, mm */ + double min_chord; /* min chord height in facetized approximation, mm */ + double tol_dist; /* min distance between two distinct vertices, mm */ + double max_angle; /* max angle control for tessellation ( 0.0 - 1.0 ) */ + double min_angle; /* min angle control for tessellation ( 0.0 - 1.0 ) */ + int max_steps; /* max number of tessellation attempts */ + int tess_adapt; /* adaptive tessellation settings are in use */ /* CSG settings */ double min_hole_diameter; /* if > 0.0, all holes features smaller than this will be deleted */ @@ -242,22 +247,26 @@ struct creo_conv_info { /* value will be deleted */ /* Bounding box results */ + double bbox_diag; /* bounding box diagonal, [L] */ double bbox_vol; /* bounding box volume, [L^3] */ double bbox_area; /* bounding box surface area, [L^2] */ /* Tessellation results */ - double tess_chord; /* chord error, mm */ - double tess_angle; /* angle error, deg */ + int tess_bbox; /* bounding box replaced failed tessellation */ + int tess_count; /* number of tessellation facets */ + double tess_chord; /* chord error, mm */ + double tess_angle; /* angle error, deg */ /* Conversion Process results */ int asm_count; /* number of assemblies processed */ int asm_total; /* number of assemblies found */ - int prt_count; /* number of assemblies processed */ + int prt_count; /* number of parts processed */ int prt_total; /* number of parts found */ /* ------ Internal ------ */ struct db_i *dbip; /* output database */ struct rt_wdb *wdbp; + struct bu_attribute_value_set avs; /* current attribute value set */ std::set *parts; /* list of all parts in Creo hierarchy */ std::set *assems; /* list of all assemblies in Creo hierarchy */ std::set *empty; /* list of all parts and assemblies in Creo that have no shape */ @@ -267,8 +276,8 @@ struct creo_conv_info { std::map *creo_name_map; /* wchar Creo names to char versions */ std::set *brlcad_names; /* set of active .g object names */ std::set *creo_names; /* set of active creo id strings */ - std::vector *model_parameters; /* model parameters to use when generating .g names */ - std::vector *attrs; /* attributes to preserve when transferring objects */ + std::vector *obj_name_params; /* model parameters used to create object names */ + std::vector *obj_attr_params; /* model parameters preserved as object attributes */ int warn_feature_unsuppress; /* flag to determine if we need to warn the user feature unsuppression failed */ }; @@ -307,17 +316,24 @@ extern "C" ProError output_part(struct creo_conv_info *, ProMdl model); /* util */ extern "C" ProError component_filter(ProFeature *, ProAppData *); -extern "C" ProError creo_attribute_val(char **val, const char *key, ProMdl m); extern "C" void creo_log(struct creo_conv_info *, int, const char *, ...); -extern "C" ProError creo_model_units(double *,ProMdl); +extern "C" ProError creo_model_units(double *, ProMdl); extern "C" char * creo_param_name(struct creo_conv_info *, wchar_t *, int); +extern "C" ProError creo_param_val(char **, const char *, ProMdl ); extern "C" int find_matl(struct creo_conv_info *); /* "C" struct bu_vls * get_brlcad_name (see comments below) */ extern "C" int get_mtl_input(FILE *, char *, int *, int *); extern "C" void lower_case( char *); +extern "C" ProError param_append(void *, ProError, ProAppData); +extern "C" ProError param_collect(ProModelitem *, ProParameter **); +extern "C" void param_export(struct creo_conv_info *, ProMdl, const char *); +extern "C" ProError param_preserve(struct creo_conv_info *, ProMdl , const char *); +extern "C" ProError params_to_attrs(struct creo_conv_info *, ProMdl, ProParameter *); +extern "C" void parse_param_list(struct creo_conv_info *, const char *, int); extern "C" ProError PopupMsg(const char *, const char *); -extern "C" ProError regex_key(ProParameter *, ProError , ProAppData ); +extern "C" ProError regex_key(ProParameter *, ProError, ProAppData ); extern "C" int rgb4lmin(double *, int); +extern "C" void scrub_vls(struct bu_vls *); extern "C" wchar_t* stable_wchar(struct creo_conv_info *, wchar_t *); extern "C" void trim(char *); extern "C" double wstr_to_double(struct creo_conv_info *, wchar_t *); @@ -342,7 +358,6 @@ extern "C" struct bu_vls *get_brlcad_name(struct creo_conv_info *cinfo, wchar_t extern "C" int subtract_hole(struct part_conv_info *pinfo); - #endif /*CREO_BRL_H*/ // Local Variables: diff --git a/src/external/Creo/csg.cpp b/src/external/Creo/csg.cpp index a93e3b9b33..97d3db63ec 100644 --- a/src/external/Creo/csg.cpp +++ b/src/external/Creo/csg.cpp @@ -172,12 +172,12 @@ tgc_hole_name(struct creo_conv_info *cinfo, wchar_t *wname, const char *suffix) while (db_lookup(cinfo->wdbp->dbip, bu_vls_addr(hname), LOOKUP_QUIET) != RT_DIR_NULL) { (void)bu_vls_incr(hname, NULL, "0:0:0:0:-", NULL, NULL); count++; - creo_log(cinfo, MSG_DEBUG, "Generating hole name \"%s\"\n", bu_vls_addr(hname)); + creo_log(cinfo, MSG_PLAIN, " NAME: Generating hole name \"%s\"\n", bu_vls_addr(hname)); if (count >= MAX_UNIQUE_NAMES) { bu_vls_free(hname); BU_PUT(hname, struct bu_vls); ProWstringToString(pname, wname); - creo_log(cinfo, MSG_DEBUG, "Hole \"%s\" failed name generation\n", pname); + creo_log(cinfo, MSG_PLAIN, " NAME: Hole \"%s\" failed name generation\n", pname); return NULL; } } @@ -207,7 +207,7 @@ subtract_hole(struct part_conv_info *pinfo) struct directory *dp = RT_DIR_NULL; vect_t a, b, c, d, h; - if (pinfo->cinfo->do_facets_only) + if (pinfo->cinfo->facets_only) return (pinfo->diameter < cinfo->min_hole_diameter) ? 1 : 0; struct hole_info *hinfo; @@ -369,7 +369,7 @@ subtract_hole(struct part_conv_info *pinfo) char pname[CREO_NAME_MAX]; ProWstringToString(pname, wname); lower_case(pname); - creo_log(cinfo, MSG_DEBUG, "Failed to recognize \"%s\" hole type\n", pname); + creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to recognize \"%s\" hole type\n", pname); BU_PUT(hinfo, struct hole_info); return 0; } diff --git a/src/external/Creo/main.cpp b/src/external/Creo/main.cpp index 6b818eda00..0caa61ed66 100644 --- a/src/external/Creo/main.cpp +++ b/src/external/Creo/main.cpp @@ -55,8 +55,6 @@ creo_conv_info_init(struct creo_conv_info *cinfo) cinfo->mtl_rec = -1; cinfo->xform_mode = XFORM_NONE; /* xform mode */ - cinfo->reg_id = 1000; /* region counter */ - cinfo->lmin = 30; /* minimum luminance */ cinfo->wdbp = NULL; @@ -65,15 +63,13 @@ creo_conv_info_init(struct creo_conv_info *cinfo) cinfo->local_tol = 0.0; cinfo->local_tol_sq = 0.0; - /* Facetization settings */ - cinfo->max_error = 1.5; - cinfo->min_error = 1.5; + /* Tessellation settings */ + cinfo->max_chord = 2.0; + cinfo->min_chord = 0.2; cinfo->tol_dist = 0.0005; - cinfo->max_angle_cntrl = 0.5; - cinfo->min_angle_cntrl = 0.5; - cinfo->max_to_min_steps = 1; - cinfo->error_increment = 0.0; - cinfo->angle_increment = 0.0; + cinfo->max_angle = 1.0; + cinfo->min_angle = 0.1; + cinfo->max_steps = 30; /* CSG settings */ cinfo->min_hole_diameter = 0.0; @@ -81,14 +77,7 @@ creo_conv_info_init(struct creo_conv_info *cinfo) cinfo->min_round_radius = 0.0; /* Tessellation results */ - cinfo->tess_chord = -1.0; - cinfo->tess_angle = -1.0; - - /* Conversion Process results */ - cinfo->asm_count = 0; - cinfo->asm_total = 0; - cinfo->prt_count = 0; - cinfo->prt_total = 0; + cinfo->tess_bbox = 0; cinfo->parts = new std::set; cinfo->assems = new std::set; @@ -102,8 +91,8 @@ creo_conv_info_init(struct creo_conv_info *cinfo) cinfo->brlcad_names = new std::set; cinfo->creo_names = new std::set; - cinfo->model_parameters = new std::vector; - cinfo->attrs = new std::vector; + cinfo->obj_name_params = new std::vector; + cinfo->obj_attr_params = new std::vector; cinfo->warn_feature_unsuppress = 0; @@ -148,14 +137,14 @@ creo_conv_info_free(struct creo_conv_info *cinfo) BU_PUT(v, struct bu_vls); } - for (unsigned int i = 0; i < cinfo->model_parameters->size(); i++) { - char *str = cinfo->model_parameters->at(i); - bu_free(str, "free model param string"); + for (unsigned int i = 0; i < cinfo->obj_name_params->size(); i++) { + char *str = cinfo->obj_name_params->at(i); + bu_free(str, "free obj name params string"); } - for (unsigned int i = 0; i < cinfo->attrs->size(); i++) { - char *str = cinfo->attrs->at(i); - bu_free(str, "free attrs string"); + for (unsigned int i = 0; i < cinfo->obj_attr_params->size(); i++) { + char *str = cinfo->obj_attr_params->at(i); + bu_free(str, "free obj attr params string"); } delete cinfo->parts; @@ -188,7 +177,7 @@ output_parts(struct creo_conv_info *cinfo) { std::set::iterator d_it; - unsigned int prt_count = 1; + unsigned int prt_count = 0; for (d_it = cinfo->parts->begin(); d_it != cinfo->parts->end(); d_it++) { wchar_t wname[CREO_NAME_MAX]; struct bu_vls *rname; @@ -212,9 +201,8 @@ output_parts(struct creo_conv_info *cinfo) rdp = db_lookup(cinfo->wdbp->dbip, bu_vls_addr(rname), LOOKUP_QUIET); if (rdp != RT_DIR_NULL && ProMdlVerstampGet(model, &cstamp) == PRO_TK_NO_ERROR) { const char *vs = NULL; - struct bu_attribute_value_set r_avs; - db5_get_attributes(cinfo->wdbp->dbip, &r_avs, rdp); - vs = bu_avs_get(&r_avs, "ptc_version_stamp"); + db5_get_attributes(cinfo->wdbp->dbip, &cinfo->avs, rdp); + vs = bu_avs_get(&cinfo->avs, "ptc_version_stamp"); if (vs && ProStringVerstampGet((char *)vs, &gstamp) == PRO_TK_NO_ERROR && ProVerstampEqual(cstamp, gstamp) == PRO_B_TRUE) { /* @@ -252,16 +240,14 @@ output_parts(struct creo_conv_info *cinfo) /* All set - process the part */ if (output_part(cinfo, model) == PRO_TK_NOT_EXIST) { creo_log(cinfo, MSG_STATUS, "Part \"%s\" failed to convert", bu_vls_addr(rname)); - cinfo->empty->insert(*d_it); - } else { - creo_log(cinfo, MSG_STATUS, "Part %d of %zu converted", prt_count, cinfo->parts->size()); - if (prt_count < cinfo->parts->size()) - prt_count++; - } + if (!cinfo->tess_bbox) + cinfo->empty->insert(*d_it); + } else + creo_log(cinfo, MSG_STATUS, "Part %d of %zu converted", ++prt_count, cinfo->parts->size()); } - /* Retain part process results */ + /* Retain conversion process results */ cinfo->prt_count = prt_count; cinfo->prt_total = cinfo->parts->size(); } @@ -272,7 +258,7 @@ output_assems(struct creo_conv_info *cinfo) { std::set::iterator d_it; - unsigned int asm_count = 1; + unsigned int asm_count = 0; for (d_it = cinfo->assems->begin(); d_it != cinfo->assems->end(); d_it++) { wchar_t wname[CREO_NAME_MAX]; struct bu_vls *aname; @@ -294,9 +280,8 @@ output_assems(struct creo_conv_info *cinfo) adp = db_lookup(cinfo->wdbp->dbip, bu_vls_addr(aname), LOOKUP_QUIET); if (adp != RT_DIR_NULL && ProMdlVerstampGet(parent, &cstamp) == PRO_TK_NO_ERROR) { const char *vs = NULL; - struct bu_attribute_value_set a_avs; - db5_get_attributes(cinfo->wdbp->dbip, &a_avs, adp); - vs = bu_avs_get(&a_avs, "ptc_version_stamp"); + db5_get_attributes(cinfo->wdbp->dbip, &cinfo->avs, adp); + vs = bu_avs_get(&cinfo->avs, "ptc_version_stamp"); if (vs && ProStringVerstampGet((char *)vs, &gstamp) == PRO_TK_NO_ERROR && ProVerstampEqual(cstamp, gstamp) == PRO_B_TRUE) { /* @@ -304,7 +289,8 @@ output_assems(struct creo_conv_info *cinfo) * version of the object that exists currently in the * Creo file */ - creo_log(cinfo, MSG_SUCCESS, "Assembly name \"%s\" exists and is current, skipping...\n", bu_vls_addr(aname)); + creo_log(cinfo, MSG_SUCCESS, "Assembly name \"%s\" exists and is current, skipping...\n", + bu_vls_addr(aname)); continue; } else { /* Kill the existing object - it's out of sync with Creo */ @@ -321,11 +307,9 @@ output_assems(struct creo_conv_info *cinfo) /* All set - process the assembly */ if (output_assembly(cinfo, parent) != PRO_TK_NO_ERROR) creo_log(cinfo, MSG_STATUS, "Assembly \"%s\" failed to convert", bu_vls_addr(aname)); - else { - creo_log(cinfo, MSG_STATUS, "Assembly %d of %zu succeeded", asm_count, cinfo->assems->size()); - if (asm_count < cinfo->assems->size()) - asm_count++; - } + else + creo_log(cinfo, MSG_STATUS, "Assembly %d of %zu succeeded", ++asm_count, cinfo->assems->size()); + } /* Retain assembly process results */ @@ -365,7 +349,7 @@ objects_gather(ProFeature *feat, ProError UNUSED(status), ProAppData app_data) lower_case(name); if (err != PRO_TK_NO_ERROR) { - creo_log(cinfo, MSG_DEBUG, "Failed to get the file type for \"%s\"\n", name); + creo_log(cinfo, MSG_PLAIN, " FILE: Failed to get type for \"%s\"\n", name); (void)ProWstringFree(wname); return PRO_TK_NO_ERROR; } @@ -373,21 +357,21 @@ objects_gather(ProFeature *feat, ProError UNUSED(status), ProAppData app_data) /* Get assembly component model */ err = ProAsmcompMdlGet(feat, &model); if (err != PRO_TK_NO_ERROR) { - creo_log(cinfo, MSG_DEBUG, "Failed to get model handle for \"%s\"\n", name); + creo_log(cinfo, MSG_PLAIN, " MODEL: Failed to get handle for \"%s\"\n", name); return PRO_TK_NO_ERROR; } /* Get model type (only a part or assembly should make it here) */ err = ProMdlTypeGet(model, &mtype); if (err != PRO_TK_NO_ERROR) { - creo_log(cinfo, MSG_DEBUG, "Failed to get model type for \"%s\"\n", name); + creo_log(cinfo, MSG_PLAIN, " MODEL: Failed to get type for \"%s\"\n", name); return PRO_TK_NO_ERROR; } /* If this is a skeleton, we're done */ ProMdlIsSkeleton(model, &is_skel); if (is_skel) { - creo_log(cinfo, MSG_DEBUG, "\"%s\" is a \"skeleton\" model, skipping...\n", name); + creo_log(cinfo, MSG_PLAIN, " MODEL: \"%s\" is a \"skeleton\", skipping...\n", name); return PRO_TK_NO_ERROR; } @@ -398,7 +382,7 @@ objects_gather(ProFeature *feat, ProError UNUSED(status), ProAppData app_data) wname_saved = (wchar_t *)bu_calloc(wcslen(wname)+1, sizeof(wchar_t), "ptc_asm_name"); wcsncpy(wname_saved, wname, wcslen(wname)+1); cinfo->assems->insert(wname_saved); - creo_log(cinfo, MSG_DEBUG, "Walking into \"%s\"\n", name); + creo_log(cinfo, MSG_PLAIN, " ASSEM: Walking into \"%s\"\n", name); ProSolidFeatVisit(ProMdlToPart(model), objects_gather, (ProFeatureFilterAction)component_filter, app_data); } break; @@ -410,7 +394,7 @@ objects_gather(ProFeature *feat, ProError UNUSED(status), ProAppData app_data) } break; default: - creo_log(cinfo, MSG_DEBUG, "\"%s\" is not a PART or an ASSEMBLY, skipping...\n", name); + creo_log(cinfo, MSG_PLAIN, " MODEL: \"%s\" is not a PART or an ASSEMBLY, skipping...\n", name); return PRO_TK_NO_ERROR; } @@ -466,7 +450,7 @@ output_top_level_object(struct creo_conv_info *cinfo, ProMdl model, ProMdlType m output_assems(cinfo); break; default: - creo_log(cinfo, MSG_DEBUG, "Top-level object \"%s\" is not a PART or an ASSEMBLY, skipping...", name); + creo_log(cinfo, MSG_PLAIN, " MODEL: Top-level object \"%s\" is not a PART or an ASSEMBLY, skipping...", name); return; } @@ -494,7 +478,7 @@ output_top_level_object(struct creo_conv_info *cinfo, ProMdl model, ProMdlType m (void)mk_addmember(bu_vls_addr(comb_name), &(wcomb.l), xform, WMOP_UNION); /* Guarantee we have a non-colliding top level name */ - bu_vls_sprintf(&top_name, "all.g"); + bu_vls_sprintf(&top_name, "all"); tdp = db_lookup(cinfo->wdbp->dbip, bu_vls_addr(&top_name), LOOKUP_QUIET); if (tdp != RT_DIR_NULL) { bu_vls_sprintf(&top_name, "all-1.g"); @@ -503,7 +487,7 @@ output_top_level_object(struct creo_conv_info *cinfo, ProMdl model, ProMdlType m (void)bu_vls_incr(&top_name, NULL, "0:0:0:0:-", NULL, NULL); count++; if (count >= MAX_UNIQUE_NAMES) { - creo_log(cinfo, MSG_DEBUG, "\"%s\" failed top-level name generation\n", bu_vls_cstr(cinfo->out_fname)); + creo_log(cinfo, MSG_PLAIN, " NAME: \"%s\" failed top-level generation\n", bu_vls_cstr(cinfo->out_fname)); break; } } @@ -536,9 +520,9 @@ doit(char *UNUSED(dialog), char *UNUSED(compnent), ProAppData UNUSED(appdata)) memset(padstr, ' ', 17); padstr[17] = '\0'; - time_t start; - time_t finish; - time_t elapsed; + int64_t start; + int time_hr, time_min; + double elapsed, time_sec; /* This replaces the global variables used in the original Creo converter */ struct creo_conv_info *cinfo = new creo_conv_info; @@ -695,26 +679,26 @@ doit(char *UNUSED(dialog), char *UNUSED(compnent), ProAppData UNUSED(appdata)) (void)ProWstringFree(tmp_str); /* Open material file when name is provided */ - if (strlen(mtl_fname) > 0) { - if (bu_file_exists(mtl_fname, NULL)) { - if ((cinfo->fpmtl=fopen(mtl_fname, "r")) == NULL) { - creo_log(NULL, MSG_STATUS, "FAILURE: Unable to open material file \"%s\" ", mtl_fname); - creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to open material file \"%s\"\n", mtl_fname); - creo_conv_info_free(cinfo); - ProUIDialogDestroy("creo_brl"); - delete cinfo; - return; - } else - cinfo->mtl_rec = get_mtl_input(cinfo->fpmtl, &(cinfo->mtl_str[0][0]) , &(cinfo->mtl_id[0]), &(cinfo->mtl_los[0])); - } else { - cinfo->fpmtl = (FILE *)NULL; - } - } + if (strlen(mtl_fname) > 0) { + if (bu_file_exists(mtl_fname, NULL)) { + if ((cinfo->fpmtl=fopen(mtl_fname, "r")) == NULL) { + creo_log(NULL, MSG_STATUS, "FAILURE: Unable to open material file \"%s\" ", mtl_fname); + creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to open material file \"%s\"\n", mtl_fname); + creo_conv_info_free(cinfo); + ProUIDialogDestroy("creo_brl"); + delete cinfo; + return; + } else + cinfo->mtl_rec = get_mtl_input(cinfo->fpmtl, &(cinfo->mtl_str[0][0]) , &(cinfo->mtl_id[0]), &(cinfo->mtl_los[0])); + } else + cinfo->fpmtl = (FILE *)NULL; + } /* Store the material filename for later use */ sprintf(cinfo->mtl_fname, "%s", mtl_fname); } + /* Begin echoing the input summary */ creo_log(cinfo, MSG_PLAIN, "# Output file name: \"%s\"\n", bu_vls_cstr(cinfo->out_fname)); creo_log(cinfo, MSG_PLAIN, "# Process log criteria: \"%s\"\n", bu_vls_cstr(cinfo->logger_str)); creo_log(cinfo, MSG_PLAIN, "# Process log file name: \"%s\"\n", bu_vls_cstr(cinfo->log_fname)); @@ -729,9 +713,9 @@ doit(char *UNUSED(dialog), char *UNUSED(compnent), ProAppData UNUSED(appdata)) /* Read user-supplied list of model parameters for object names */ { /* Get string from dialog */ - char attr_rename[MAXPATHLEN]; - wchar_t *w_attr_rename; - err = ProUIInputpanelValueGet("creo_brl", "attr_rename", &w_attr_rename); + char param_rename[MAXPATHLEN]; + wchar_t *w_param_rename; + err = ProUIInputpanelValueGet("creo_brl", "param_rename", &w_param_rename); if (err != PRO_TK_NO_ERROR) { creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get value(s): \"Create object names\" "); creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get value(s): \"Create object names\"\n"); @@ -741,77 +725,38 @@ doit(char *UNUSED(dialog), char *UNUSED(compnent), ProAppData UNUSED(appdata)) return; } - ProWstringToString(attr_rename, w_attr_rename); - (void)ProWstringFree(w_attr_rename); - - if (strlen(attr_rename) > 0) { - std::string pfilestr(attr_rename); - std::istringstream ss(pfilestr); - std::string line; - while (std::getline(ss, line)) { - std::string pkey; - std::istringstream ls(line); - while (std::getline(ls, pkey, ',')) { - /* Scrub leading and trailing whitespace */ - size_t startpos = pkey.find_first_not_of(" \t\n\v\f\r"); - if (std::string::npos != startpos) - pkey = pkey.substr(startpos); - size_t endpos = pkey.find_last_not_of(" \t\n\v\f\r"); - if (std::string::npos != endpos) - pkey = pkey.substr(0 ,endpos+1); - if (pkey.length() > 0) { - creo_log(cinfo, MSG_PLAIN, "# Creates object names: \"%s\"\n", pkey.c_str()); - cinfo->model_parameters->push_back(bu_strdup(pkey.c_str())); - } - } - } + ProWstringToString(param_rename, w_param_rename); + (void)ProWstringFree(w_param_rename); + + if (strlen(param_rename) > 0) { + parse_param_list(cinfo, param_rename, NAME_PARAMS); creo_log(cinfo, MSG_PLAIN, "#%s#\n", linestr); } else - creo_log(cinfo, MSG_PLAIN, "# Create object names: \"%s\"\n", attr_rename); + creo_log(cinfo, MSG_PLAIN, "# Creates object names: \"%s\"\n", param_rename); } /* Read user-supplied list of model attributes for conversion */ { /* Get string from dialog */ - char attr_save[MAXPATHLEN]; - wchar_t *w_attr_save; - err = ProUIInputpanelValueGet("creo_brl", "attr_save", &w_attr_save); + char param_save[MAXPATHLEN]; + wchar_t *w_param_save; + err = ProUIInputpanelValueGet("creo_brl", "param_save", &w_param_save); if (err != PRO_TK_NO_ERROR) { - creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get value(s): \"Preserve as attributes\" "); - creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get value(s): \"Preserve as attributes\"\n"); + creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get value(s): \"Preserved attributes\" "); + creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get value(s): \"Preserved attributes\"\n"); creo_conv_info_free(cinfo); ProUIDialogDestroy("creo_brl"); delete cinfo; return; } - ProWstringToString(attr_save, w_attr_save); - (void)ProWstringFree(w_attr_save); - - if (strlen(attr_save) > 0) { - /* Parse attribute list into separate parameter keys */ - std::string afilestr(attr_save); - std::istringstream ss(afilestr); - std::string line; - while (std::getline(ss, line)) { - std::string pkey; - std::istringstream ls(line); - while (std::getline(ls, pkey, ',')) { - /* Scrub leading and trailing whitespace */ - size_t startpos = pkey.find_first_not_of(" \t\n\v\f\r"); - if (std::string::npos != startpos) - pkey = pkey.substr(startpos); - size_t endpos = pkey.find_last_not_of(" \t\n\v\f\r"); - if (std::string::npos != endpos) - pkey = pkey.substr(0 ,endpos+1); - if (pkey.length() > 0) { - creo_log(cinfo, MSG_PLAIN, "# Preserved as attribute: \"%s\"\n", pkey.c_str()); - cinfo->attrs->push_back(bu_strdup(pkey.c_str())); - } - } - } - } else - creo_log(cinfo, MSG_PLAIN, "# Preserve as attributes: \"%s\"\n", attr_save); + ProWstringToString(param_save, w_param_save); + (void)ProWstringFree(w_param_save); + + if (strlen(param_save) > 0) + parse_param_list(cinfo, param_save, ATTR_PARAMS); + else + creo_log(cinfo, MSG_PLAIN, "# Preserved attribute: \"%s\"\n", param_save); } creo_log(cinfo, MSG_PLAIN, "#%s#\n", linestr); @@ -864,7 +809,7 @@ doit(char *UNUSED(dialog), char *UNUSED(compnent), ProAppData UNUSED(appdata)) ProUIDialogDestroy("creo_brl"); return; } else { - cinfo->reg_id = wstr_to_long(cinfo, tmp_str); + cinfo->reg_id = (int)wstr_to_long(cinfo, tmp_str); creo_log(cinfo, MSG_PLAIN, "# Initial region counter: %d\n", cinfo->reg_id); V_MAX(cinfo->reg_id, 1); (void)ProWstringFree(tmp_str); @@ -873,15 +818,15 @@ doit(char *UNUSED(dialog), char *UNUSED(compnent), ProAppData UNUSED(appdata)) /* Get minimum luminance threshold */ err = ProUIInputpanelValueGet("creo_brl", "min_luminance", &tmp_str); if (err != PRO_TK_NO_ERROR) { - creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get value: \"Min luminance threshold\" "); - creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get value: \"Min luminance threshold\"\n"); + creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get value: \"Min luminance\" "); + creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get value: \"Min luminance\"\n"); creo_conv_info_free(cinfo); ProUIDialogDestroy("creo_brl"); return; } else { - cinfo->lmin = wstr_to_long(cinfo, tmp_str); - creo_log(cinfo, MSG_PLAIN, "# Min luminance threshold, %s: %d\n", "%", cinfo->lmin); - cinfo->lmin = std::min(std::max(cinfo->lmin,0),100); + int lmin = (int)wstr_to_long(cinfo, tmp_str); + creo_log(cinfo, MSG_PLAIN, "# Min luminance, %s: %d\n", "%", lmin); + cinfo->lmin = std::min(std::max(lmin,0),100); (void)ProWstringFree(tmp_str); } @@ -891,84 +836,81 @@ doit(char *UNUSED(dialog), char *UNUSED(compnent), ProAppData UNUSED(appdata)) creo_log(cinfo, MSG_PLAIN, "%s#\n", padstr); creo_log(cinfo, MSG_PLAIN, "#%s#\n", linestr); - /* Get max tessellation error */ - err = ProUIInputpanelValueGet("creo_brl", "max_error", &tmp_str); + /* Get max chord height */ + err = ProUIInputpanelValueGet("creo_brl", "max_chord", &tmp_str); if (err != PRO_TK_NO_ERROR) { - creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get value: \"Max chord error\" "); - creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get value: \"Max chord error\"\n"); + creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get value: \"Max chord\" "); + creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get value: \"Max chord\"\n"); creo_conv_info_free(cinfo); ProUIDialogDestroy("creo_brl"); return; } else { - cinfo->max_error = wstr_to_double(cinfo, tmp_str); - creo_log(cinfo, MSG_PLAIN, "# Max chord error, mm: %8.6f\n", cinfo->max_error); + cinfo->max_chord = wstr_to_double(cinfo, tmp_str); + creo_log(cinfo, MSG_PLAIN, "# Max chord height, mm: %8.6f\n", cinfo->max_chord); (void)ProWstringFree(tmp_str); } - /* Get min tessellation error */ - err = ProUIInputpanelValueGet("creo_brl", "min_error", &tmp_str); + /* Get min chord height */ + err = ProUIInputpanelValueGet("creo_brl", "min_chord", &tmp_str); if (err != PRO_TK_NO_ERROR) { - creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get value: \"Min chord error\" "); - creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get value: \"Min chord error\"\n"); + creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get value: \"Min chord\" "); + creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get value: \"Min chord\"\n"); creo_conv_info_free(cinfo); ProUIDialogDestroy("creo_brl"); return; } else { - cinfo->min_error = wstr_to_double(cinfo, tmp_str); - creo_log(cinfo, MSG_PLAIN, "# Min chord error, mm: %8.6f\n", cinfo->min_error); - V_MAX(cinfo->max_error, cinfo->min_error); + cinfo->min_chord = wstr_to_double(cinfo, tmp_str); + creo_log(cinfo, MSG_PLAIN, "# Min chord height, mm: %8.6f\n", cinfo->min_chord); + V_MAX(cinfo->max_chord, cinfo->min_chord); (void)ProWstringFree(tmp_str); } /* Get the max angle control */ - err = ProUIInputpanelValueGet("creo_brl", "max_angle_ctrl", &tmp_str); + err = ProUIInputpanelValueGet("creo_brl", "max_angle", &tmp_str); if (err != PRO_TK_NO_ERROR) { - creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get value: \"Max angle control\" "); - creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get value: \"Max angle control\"\n"); + creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get value: \"Max angle\" "); + creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get value: \"Max angle\"\n"); creo_conv_info_free(cinfo); ProUIDialogDestroy("creo_brl"); return; } else { - cinfo->max_angle_cntrl = wstr_to_double(cinfo, tmp_str); - creo_log(cinfo, MSG_PLAIN, "# Max angle control, deg: %8.6f\n", cinfo->max_angle_cntrl); + cinfo->max_angle = wstr_to_double(cinfo, tmp_str); + creo_log(cinfo, MSG_PLAIN, "# Max angle control: %8.6f\n", cinfo->max_angle); (void)ProWstringFree(tmp_str); } /* Get the min angle control */ - err = ProUIInputpanelValueGet("creo_brl", "min_angle_ctrl", &tmp_str); + err = ProUIInputpanelValueGet("creo_brl", "min_angle", &tmp_str); if (err != PRO_TK_NO_ERROR) { - creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get value: \"Min angle control\" "); - creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get value: \"Min angle control\"\n"); + creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get value: \"Min angle\" "); + creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get value: \"Min angle\"\n"); creo_conv_info_free(cinfo); ProUIDialogDestroy("creo_brl"); return; } else { - cinfo->min_angle_cntrl = wstr_to_double(cinfo, tmp_str); - creo_log(cinfo, MSG_PLAIN, "# Min angle control, deg: %8.6f\n", cinfo->min_angle_cntrl); - V_MAX(cinfo->max_angle_cntrl, cinfo->min_angle_cntrl); + cinfo->min_angle = wstr_to_double(cinfo, tmp_str); + creo_log(cinfo, MSG_PLAIN, "# Min angle control: %8.6f\n", cinfo->min_angle); + V_MAX(cinfo->max_angle, cinfo->min_angle); (void)ProWstringFree(tmp_str); } - /* Get the max to min steps */ - err = ProUIInputpanelValueGet("creo_brl", "isteps", &tmp_str); + /* Get the max number of steps */ + err = ProUIInputpanelValueGet("creo_brl", "max_steps", &tmp_str); if (err != PRO_TK_NO_ERROR) { - creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get value: \"Max to Min control steps\" "); - creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get value: \"Max to Min control steps\"\n"); + creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get value: \"Max steps\" "); + creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get value: \"Max steps\"\n"); creo_conv_info_free(cinfo); ProUIDialogDestroy("creo_brl"); return; } else { - cinfo->max_to_min_steps = wstr_to_long(cinfo, tmp_str); - creo_log(cinfo, MSG_PLAIN, "# Max to Min control steps: %d\n", cinfo->max_to_min_steps); + cinfo->max_steps = (int)wstr_to_long(cinfo, tmp_str); + creo_log(cinfo, MSG_PLAIN, "# Max number of steps: %d\n", cinfo->max_steps); (void)ProWstringFree(tmp_str); - if (cinfo->max_to_min_steps <= 0) - cinfo->max_to_min_steps = 0; - else { - cinfo->error_increment = (ZERO((cinfo->max_error - cinfo->min_error))) ? 0 : (cinfo->max_error - cinfo->min_error) / (double)cinfo->max_to_min_steps; - cinfo->angle_increment = (ZERO((cinfo->max_angle_cntrl - cinfo->min_angle_cntrl))) ? 0 : (cinfo->max_angle_cntrl - cinfo->min_angle_cntrl) / (double)cinfo->max_to_min_steps; - if (ZERO(cinfo->error_increment) && ZERO(cinfo->angle_increment)) - cinfo->max_to_min_steps = 0; - } + + /* Utilize adaptive tessellation settings? */ + cinfo->tess_adapt = (ZERO(cinfo->max_chord) && + ZERO(cinfo->min_chord) && + cinfo->max_steps > 0 ); } creo_log(cinfo, MSG_PLAIN, "#%s#\n", linestr); @@ -978,7 +920,7 @@ doit(char *UNUSED(dialog), char *UNUSED(compnent), ProAppData UNUSED(appdata)) creo_log(cinfo, MSG_PLAIN, "#%s#\n", linestr); /* Check if user wants to eliminate small features */ - err = ProUICheckbuttonGetState("creo_brl", "elim_small", &cinfo->do_elims); + err = ProUICheckbuttonGetState("creo_brl", "elim_small", &cinfo->elim_small); if (err != PRO_TK_NO_ERROR) { creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get check button state: \"ignore minimum sizes\" "); creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get check button state: \"ignore minimum sizes\"\n"); @@ -987,9 +929,9 @@ doit(char *UNUSED(dialog), char *UNUSED(compnent), ProAppData UNUSED(appdata)) delete cinfo; return; } else - creo_log(cinfo, MSG_PLAIN, "# Ignore minimum sizes: %s\n", cinfo->do_elims ? "ON" : "OFF"); + creo_log(cinfo, MSG_PLAIN, "# Ignore minimum sizes: %s\n", cinfo->elim_small ? "ON" : "OFF"); - if (cinfo->do_elims) { + if (cinfo->elim_small) { /* Get the minimum hole diameter */ err = ProUIInputpanelValueGet("creo_brl", "min_hole", &tmp_str); if (err != PRO_TK_NO_ERROR) { @@ -1051,7 +993,7 @@ doit(char *UNUSED(dialog), char *UNUSED(compnent), ProAppData UNUSED(appdata)) creo_log(cinfo, MSG_PLAIN, "#%s#\n", linestr); /* Check if user wants to do any CSG */ - err = ProUICheckbuttonGetState("creo_brl", "facets_only", &cinfo->do_facets_only); + err = ProUICheckbuttonGetState("creo_brl", "facets_only", &cinfo->facets_only); if (err != PRO_TK_NO_ERROR) { creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get check button state: \"facets only\" "); creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get check button state: \"facets only\"\n"); @@ -1060,19 +1002,7 @@ doit(char *UNUSED(dialog), char *UNUSED(compnent), ProAppData UNUSED(appdata)) delete cinfo; return; } else - creo_log(cinfo, MSG_PLAIN, "# Facetize everything, (no CSG): %s\n", cinfo->do_facets_only ? "ON" : "OFF"); - - /* Check if user wants surface normals in the BOT's */ - err = ProUICheckbuttonGetState("creo_brl", "get_normals", &cinfo->get_normals); - if (err != PRO_TK_NO_ERROR) { - creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get check button state: \"write surface normals\" "); - creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get check button state: \"write surface normals\"\n"); - creo_conv_info_free(cinfo); - ProUIDialogDestroy("creo_brl"); - delete cinfo; - return; - } else - creo_log(cinfo, MSG_PLAIN, "# Write surface normals: %s\n", cinfo->get_normals ? "ON" : "OFF"); + creo_log(cinfo, MSG_PLAIN, "# Facetize everything, (no CSG): %s\n", cinfo->facets_only ? "ON" : "OFF"); /* Check if user wants to test solidity */ err = ProUICheckbuttonGetState("creo_brl", "check_solidity", &cinfo->check_solidity); @@ -1087,7 +1017,7 @@ doit(char *UNUSED(dialog), char *UNUSED(compnent), ProAppData UNUSED(appdata)) creo_log(cinfo, MSG_PLAIN, "# Reject BoTs that fail solidity: %s\n", cinfo->check_solidity ? "ON" : "OFF"); /* Check if user wants to use bounding boxes */ - err = ProUICheckbuttonGetState("creo_brl", "debug_bboxes", &cinfo->debug_bboxes); + err = ProUICheckbuttonGetState("creo_brl", "create_boxes", &cinfo->create_boxes); if (err != PRO_TK_NO_ERROR) { creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get check button state: \"bounding box for failed part\" "); creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get check button state: \"bounding box for failed part\"\n"); @@ -1096,31 +1026,50 @@ doit(char *UNUSED(dialog), char *UNUSED(compnent), ProAppData UNUSED(appdata)) delete cinfo; return; } else - creo_log(cinfo, MSG_PLAIN, "# Bounding box replaces failed part: %s\n", cinfo->debug_bboxes ? "ON" : "OFF"); + creo_log(cinfo, MSG_PLAIN, "# Bounding box replaces failed part: %s\n", cinfo->create_boxes ? "ON" : "OFF"); - creo_log(cinfo, MSG_PLAIN, "#%s#\n", linestr); + /* Check if user wants surface normals in the BOT's */ + err = ProUICheckbuttonGetState("creo_brl", "get_normals", &cinfo->get_normals); + if (err != PRO_TK_NO_ERROR) { + creo_log(NULL, MSG_STATUS, "FAILURE: Unable to get check button state: \"write surface normals\" "); + creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get check button state: \"write surface normals\"\n"); + creo_conv_info_free(cinfo); + ProUIDialogDestroy("creo_brl"); + delete cinfo; + return; + } else + creo_log(cinfo, MSG_PLAIN, "# Write surface normals: %s\n", cinfo->get_normals ? "ON" : "OFF"); - /* Input summary now complete, restore user-specified logger type */ - cinfo->logger_type = user_logger_type; + creo_log(cinfo, MSG_PLAIN, "#%s#\n", linestr); /* Report status of material file */ if (int(strlen(cinfo->mtl_fname)) > 0) { if (cinfo->fpmtl == NULL) - creo_log(cinfo, MSG_DEBUG, "Unknown material translation file \"%s\"\n", + creo_log(cinfo, MSG_PLAIN, " MATL: Unknown material translation file \"%s\"\n", cinfo->mtl_fname); else if (cinfo->mtl_rec > 0) { - creo_log(cinfo, MSG_DEBUG, "Found material translation file \"%s\"\n", + creo_log(cinfo, MSG_PLAIN, " MATL: Found material translation file \"%s\"\n", cinfo->mtl_fname); - creo_log(cinfo, MSG_DEBUG, "Found %d valid material translation entries\n", + creo_log(cinfo, MSG_PLAIN, " MATL: Found %d valid material translation entries\n", cinfo->mtl_rec); + creo_log(cinfo, MSG_PLAIN, " MATL: ==========================================================\n"); + creo_log(cinfo, MSG_PLAIN, " MATL: n ptc_material_name material_id los\n"); + creo_log(cinfo, MSG_PLAIN , " MATL: ----------------------------------------------------------\n"); + for (int n = 0; n < cinfo->mtl_rec; n++) + creo_log(cinfo, MSG_PLAIN, " MATL: %3d %-32s %3d %3d\n", + n+1, cinfo->mtl_str[n], cinfo->mtl_id[n], cinfo->mtl_los[n]); + creo_log(cinfo, MSG_PLAIN, " MATL: ----------------------------------------------------------\n"); } else creo_log(cinfo, MSG_FAIL, "File \"%s\" has no valid material translation entries\n", cinfo->mtl_fname); } else { - creo_log(cinfo, MSG_DEBUG, "No material translation file was specified\n"); + creo_log(cinfo, MSG_PLAIN, " MATL: No translation file was specified\n"); cinfo->mtl_rec = -1; } + /* Input summary now complete, restore user-specified logger type */ + cinfo->logger_type = user_logger_type; + /* Get currently displayed model in Creo */ err = ProMdlCurrentGet(&model); if (err == PRO_TK_BAD_CONTEXT) { @@ -1160,7 +1109,7 @@ doit(char *UNUSED(dialog), char *UNUSED(compnent), ProAppData UNUSED(appdata)) cinfo->local_tol = cinfo->tol_dist / cinfo->creo_to_brl_conv; cinfo->local_tol_sq = cinfo->local_tol * cinfo->local_tol; - (void)time(&start); + start = bu_gettime(); /* * Output the top-level object @@ -1232,14 +1181,16 @@ doit(char *UNUSED(dialog), char *UNUSED(compnent), ProAppData UNUSED(appdata)) } else creo_log(cinfo, MSG_PLAIN, "# Conversion ratio: 100%s\n", "%"); - (void)time(&finish); - elapsed = finish - start; - creo_log(cinfo, MSG_PLAIN, "#%s#\n", linestr); - creo_log(cinfo, MSG_PLAIN, "# Elapsed time: %02d:%02d:%02d\n", - (int)elapsed/3600, - (int)elapsed%3600/60, - (int)elapsed%60); + + /* Bin the elapsed run time for display as: hh:mm:ss.sss */ + elapsed = (double)(bu_gettime() - start)/1000000.0; + time_hr = (int)(elapsed)/3600; + time_min = ((int)(elapsed)-3600*time_hr)/60; + time_sec = elapsed - 3600*time_hr - 60*time_min; + + creo_log(cinfo, MSG_PLAIN, "# Elapsed time: %02d:%02d:%06.3f\n", + time_hr, time_min, time_sec); creo_log(cinfo, MSG_PLAIN, "#%s#\n", linestr); creo_log(cinfo, MSG_PLAIN, "#%s", padstr); @@ -1259,7 +1210,6 @@ doit(char *UNUSED(dialog), char *UNUSED(compnent), ProAppData UNUSED(appdata)) cinfo->asm_total - cinfo->asm_count); else creo_log(cinfo, MSG_STATUS, "No Assembly failures found"); - creo_log(cinfo, MSG_STATUS, "---------------------------------"); creo_conv_info_free(cinfo); delete cinfo; @@ -1292,7 +1242,7 @@ elim_small_activate(char *dialog_name, char *button_name, ProAppData UNUSED(data } } else { if (ProUIInputpanelReadOnly(dialog_name, "min_hole") != PRO_TK_NO_ERROR) { - creo_log(NULL, MSG_STATUS, "FAILURE: Unable to de-activate: \"Hole diameter\"vv"); + creo_log(NULL, MSG_STATUS, "FAILURE: Unable to de-activate: \"Hole diameter\" "); return; } if (ProUIInputpanelReadOnly(dialog_name, "min_chamfer") != PRO_TK_NO_ERROR) { @@ -1387,15 +1337,15 @@ creo_brl(uiCmdCmdId UNUSED(command), uiCmdValue *UNUSED(p_value), void *UNUSED(p * users to input lists directly... to do so, need to increase char * limit */ - ProUIInputpanelMaxlenSet("creo_brl", "attr_rename", MAXPATHLEN - 1); - ProUIInputpanelMaxlenSet("creo_brl", "attr_save", MAXPATHLEN - 1); + ProUIInputpanelMaxlenSet("creo_brl", "param_rename", MAXPATHLEN - 1); + ProUIInputpanelMaxlenSet("creo_brl", "param_save", MAXPATHLEN - 1); if (ProUIDialogActivate("creo_brl", &err) != PRO_TK_NO_ERROR) bu_vls_printf(&vls, "FAILURE: Unexpected error in creo-brl dialog returned %d\n", err); print_msg: if (bu_vls_strlen(&vls) > 0) { - creo_log(NULL, MSG_DEBUG, bu_vls_addr(&vls)); + creo_log(NULL, MSG_PLAIN, bu_vls_addr(&vls)); bu_vls_free(&vls); } if (destroy_dialog) diff --git a/src/external/Creo/part.cpp b/src/external/Creo/part.cpp index eddca0e7f2..20d1c69a65 100644 --- a/src/external/Creo/part.cpp +++ b/src/external/Creo/part.cpp @@ -217,7 +217,7 @@ check_dimension(ProDimension *dim, ProError UNUSED(status), ProAppData data) extern "C" ProError -do_feature_visit(ProFeature *feat, ProError UNUSED(status), ProAppData data) +feature_visit(ProFeature *feat, ProError UNUSED(status), ProAppData data) { ProError err = PRO_TK_GENERAL_ERROR; ProFeattype feat_type; @@ -242,7 +242,7 @@ do_feature_visit(ProFeature *feat, ProError UNUSED(status), ProAppData data) case PRO_FEAT_HOLE: if (pinfo->diameter < pinfo->cinfo->min_hole_diameter) pinfo->suppressed_features->push_back(feat->id); /* Suppress small holes */ - else if (pinfo->cinfo->do_facets_only) + else if (pinfo->cinfo->facets_only) goto skip; /* Skip hole when Facetizing */ else if (subtract_hole(pinfo)) pinfo->suppressed_features->push_back(feat->id); /* Suppress hole before tessellating */ @@ -294,7 +294,7 @@ unsuppress_features(struct part_conv_info *pinfo) continue; /* Resume suppressed feature */ - creo_log(pinfo->cinfo, MSG_DEBUG, "\"%s\" unsuppressing feature \"%d\"\n", + creo_log(pinfo->cinfo, MSG_PLAIN, " FEAT: \"%s\" unsuppressing feature \"%d\"\n", pname, pinfo->suppressed_features->at(i)); err = ProFeatureWithoptionsResume(ProMdlToSolid(pinfo->model), @@ -305,15 +305,15 @@ unsuppress_features(struct part_conv_info *pinfo) /* Report the outcome */ switch (err) { case PRO_TK_NO_ERROR: - creo_log(pinfo->cinfo, MSG_DEBUG, "Part \"%s\" feature \"%d\" unsuppressed\n", + creo_log(pinfo->cinfo, MSG_PLAIN, " FEAT: Part \"%s\" feature \"%d\" unsuppressed\n", pname, pinfo->suppressed_features->at(i)); break; case PRO_TK_SUPP_PARENTS: - creo_log(pinfo->cinfo, MSG_DEBUG, "Part \"%s\" suppressed parents for feature \"%d\" not found\n", + creo_log(pinfo->cinfo, MSG_PLAIN, " FEAT: Part \"%s\" suppressed parents for feature \"%d\" not found\n", pname, pinfo->suppressed_features->at(i)); break; default: - creo_log(pinfo->cinfo, MSG_FAIL, "Part \"%s\" feature id \"%d\" failed to resume\n", + creo_log(pinfo->cinfo, MSG_FAIL, "Part \"%s\" feature id \"%d\" failed to resume\n", pname, pinfo->suppressed_features->at(i)); } @@ -528,28 +528,22 @@ opennurbs_part(struct creo_conv_info *cinfo, ProMdl model, struct bu_vls **sname err = ProSolidBodiesCollect(psol, &pbdy); if (err != PRO_TK_NO_ERROR) { - return err; + return err; } - // Getting to the point where we will use bdata - allocate + /* Allocate the brep data */ bdata.cs_to_onf = new std::map; bdata.ce_to_one = new std::map; bdata.cc3d_to_on3dc = new std::map; bdata.cc2d_to_on2dc = new std::map; err = ProSolidBodySurfaceVisit(pbdy, surface_process, (ProAppData)&bdata); - if (err != PRO_TK_NO_ERROR) { - delete bdata.cs_to_onf; - delete bdata.ce_to_one; - delete bdata.cc3d_to_on3dc; - delete bdata.cc2d_to_on2dc; - return err; + if (err == PRO_TK_NO_ERROR) { + /* Output the solid */ + *sname = get_brlcad_name(cinfo, wname, "brep", N_SOLID); + mk_brep(cinfo->wdbp, bu_vls_addr(*sname), nbrep); } - /* Output the solid */ - *sname = get_brlcad_name(cinfo, wname, "brep", N_SOLID); - mk_brep(cinfo->wdbp, bu_vls_addr(*sname), nbrep); - /* * Things to investigate: * @@ -571,6 +565,7 @@ opennurbs_part(struct creo_conv_info *cinfo, ProMdl model, struct bu_vls **sname * ProCurveToNURBS() */ + /* Clean-up before returning */ delete bdata.cs_to_onf; delete bdata.ce_to_one; delete bdata.cc3d_to_on3dc; @@ -586,8 +581,6 @@ tessellate_part(struct creo_conv_info *cinfo, ProMdl model, struct bu_vls **snam ProSurfaceTessellationData *tess = NULL; ProError err = PRO_TK_GENERAL_ERROR; - int success = 0; - wchar_t wname[CREO_NAME_MAX]; char pname[CREO_NAME_MAX]; @@ -596,89 +589,125 @@ tessellate_part(struct creo_conv_info *cinfo, ProMdl model, struct bu_vls **snam std::vector faces; std::vector face_normals; + /* tessellation settings */ + int max_steps; + double max_angle; + double min_angle; + double max_chord; + double min_chord; + double angle_incr; + double chord_incr; + + /* tessellation values */ + double curr_chord; + double curr_angle; + + /* tessellation results */ + int success = 0; + int facet_count = 0; + int surf_count = 0; size_t v1, v2, v3; size_t n1, n2, n3; size_t vert_no; - int surface_count = 0; - double curr_error; - double curr_angle; - double factor = cinfo->creo_to_brl_conv; + double conv_scale = cinfo->creo_to_brl_conv; /* * Note: The below code works, but we can't use model units - Creo * "corrects" object sizes with matricies in the parent hierarchies * and correcting it here results in problems with those matricies. * - * ProError ustatus = creo_model_units(&factor, model); + * ProError ustatus = creo_model_units(&conv_scale, model); */ (void)ProMdlMdlnameGet(model, wname); ProWstringToString(pname, wname); lower_case(pname); - creo_log(cinfo, MSG_DEBUG, "Tessellating part \"%s\"...\n", pname); + if (cinfo->max_steps < 1) { + creo_log(cinfo, MSG_PLAIN, " TESS: \"%s\" has invalid settings with max_steps = %d\n", + pname, cinfo->max_steps); + return err; + } else + max_steps = (cinfo->max_steps); + + if (cinfo->tess_adapt) { + /* Apply adaptive tessellation settings */ + max_angle = 1.0; + min_angle = 1.0/double(cinfo->max_steps); + max_chord = (cinfo->bbox_diag)/double(cinfo->max_steps); + min_chord = (cinfo->bbox_diag)/pow(double(cinfo->max_steps), 2); + creo_log(cinfo, MSG_PLAIN, " TESS: ========== \"%s\" ==========\n", pname); + creo_log(cinfo, MSG_PLAIN, " TESS: Max angle control = %g\n" , max_angle); + creo_log(cinfo, MSG_PLAIN, " TESS: Min angle control = %g\n" , min_angle); + creo_log(cinfo, MSG_PLAIN, " TESS: Max chord height = %g\n" , max_chord); + creo_log(cinfo, MSG_PLAIN, " TESS Min chord height = %g\n" , min_chord); + creo_log(cinfo, MSG_PLAIN, " TESS: Max steps = %d\n" , max_steps); + creo_log(cinfo, MSG_PLAIN, " TESS: ---------- \"%s\" ----------\n", pname); + } else { + /* Adopt existing tessellation settings */ + max_angle = (cinfo->max_angle); + min_angle = (cinfo->min_angle); + max_chord = (cinfo->max_chord)/conv_scale; /* mm to in */ + min_chord = (cinfo->min_chord)/conv_scale; /* mm to in */ + } + + if (max_steps > 1) { + angle_incr = (ZERO(max_angle - min_angle)) ? 0.0 : (max_angle - min_angle) / (double)(max_steps - 1); + chord_incr = (ZERO(max_chord - min_chord)) ? 0.0 : (max_chord - min_chord) / (double)(max_steps - 1); + } else { + angle_incr = (ZERO(max_angle - min_angle)) ? 0.0 : (max_angle - min_angle); + chord_incr = (ZERO(max_chord - min_chord)) ? 0.0 : (max_chord - min_chord); + } + + if (ZERO(angle_incr) && ZERO(chord_incr)) + max_steps = 0; + + creo_log(cinfo, MSG_PLAIN, " TESS: Processing part \"%s\"...\n", pname); /* Tessellate part, going from coarse to fine tessellation */ - for (int i = 0; i <= cinfo->max_to_min_steps; ++i) { - curr_error = cinfo->max_error - (i * cinfo->error_increment); - curr_angle = cinfo->min_angle_cntrl + (i * cinfo->angle_increment); + for (int i = 0; i < max_steps; i++) { + curr_chord = max_chord - (i * chord_incr); + curr_angle = min_angle + (i * angle_incr); vert_tree = bg_vert_tree_create(); norm_tree = bg_vert_tree_create(); - /* - * Used for diagnostic output: - * - * creo_log(cinfo, MSG_SUCCESS, "Tessellating \"%s\" with %g mm and %g deg\n", - * pname, curr_error, curr_angle); - * - */ + err = ProPartTessellate(ProMdlToPart(model), curr_chord, curr_angle, + PRO_B_TRUE, &tess); - err = ProPartTessellate(ProMdlToPart(model), curr_error/cinfo->creo_to_brl_conv, - curr_angle, PRO_B_TRUE, &tess); if (err != PRO_TK_NO_ERROR) { - creo_log(cinfo, MSG_DEBUG, "Tessellation of \"%s\" failed with %g mm and %g deg\n", - pname, curr_error, curr_angle); - /* - * Used for diagnostic output: - * - * creo_log(cinfo, MSG_DEBUG, "max_error = %g, min_error - %g, error_increment - %g\n", - * cinfo->max_error, cinfo->min_error, cinfo->error_increment); - * creo_log(cinfo, MSG_DEBUG, "max_angle_cntrl = %g, min_angle_cntrl - %g, angle_increment - %g\n", - cinfo->max_angle_cntrl, cinfo->min_angle_cntrl, cinfo->angle_increment); - * creo_log(cinfo, MSG_DEBUG, "curr_error = %g, curr_angle - %g\n", - * curr_error, curr_angle); - * - */ + creo_log(cinfo, MSG_PLAIN, " TESS: \"%s\" failed with %g and %g\n", + pname, curr_chord, curr_angle); continue; } /* We got through the initial tests - how many surfaces do we have? */ - err = ProArraySizeGet((ProArray)tess, &surface_count); + err = ProArraySizeGet((ProArray)tess, &surf_count); if (err != PRO_TK_NO_ERROR) goto tess_cleanup; - else if (surface_count < 1) { + else if (surf_count < 3) { err = PRO_TK_NOT_EXIST; goto tess_cleanup; } - for (int surfno = 0; surfno < surface_count; surfno++) - for (int j = 0; j < tess[surfno].n_facets; j++) { + facet_count = 0; + for (int surfno = 0; surfno < surf_count; surfno++) + for (int k = 0; k < tess[surfno].n_facets; k++) { /* Grab the triangle */ - vert_no = (size_t)tess[surfno].facets[j][0]; + vert_no = (size_t)tess[surfno].facets[k][0]; v1 = bg_vert_tree_add(vert_tree, tess[surfno].vertices[vert_no][0], tess[surfno].vertices[vert_no][1], tess[surfno].vertices[vert_no][2], cinfo->local_tol_sq); - vert_no = (size_t)tess[surfno].facets[j][1]; + vert_no = (size_t)tess[surfno].facets[k][1]; v2 = bg_vert_tree_add(vert_tree, tess[surfno].vertices[vert_no][0], tess[surfno].vertices[vert_no][1], tess[surfno].vertices[vert_no][2], cinfo->local_tol_sq); - vert_no = (size_t)tess[surfno].facets[j][2]; + vert_no = (size_t)tess[surfno].facets[k][2]; v3 = bg_vert_tree_add(vert_tree, tess[surfno].vertices[vert_no][0], tess[surfno].vertices[vert_no][1], @@ -694,21 +723,21 @@ tessellate_part(struct creo_conv_info *cinfo, ProMdl model, struct bu_vls **snam /* Grab the surface normals */ if (cinfo->get_normals) { - vert_no = (size_t)tess[surfno].facets[j][0]; + vert_no = (size_t)tess[surfno].facets[k][0]; VUNITIZE(tess[surfno].normals[vert_no]); n1 = bg_vert_tree_add(norm_tree, tess[surfno].normals[vert_no][0], tess[surfno].normals[vert_no][1], tess[surfno].normals[vert_no][2], cinfo->local_tol_sq); - vert_no = (size_t)tess[surfno].facets[j][1]; + vert_no = (size_t)tess[surfno].facets[k][1]; VUNITIZE(tess[surfno].normals[vert_no]); n2 = bg_vert_tree_add(norm_tree, tess[surfno].normals[vert_no][0], tess[surfno].normals[vert_no][1], tess[surfno].normals[vert_no][2], cinfo->local_tol_sq); - vert_no = (size_t)tess[surfno].facets[j][2]; + vert_no = (size_t)tess[surfno].facets[k][2]; VUNITIZE(tess[surfno].normals[vert_no]); n3 = bg_vert_tree_add(norm_tree, tess[surfno].normals[vert_no][0], @@ -719,6 +748,7 @@ tessellate_part(struct creo_conv_info *cinfo, ProMdl model, struct bu_vls **snam face_normals.push_back((int)n3); face_normals.push_back((int)n2); } + facet_count++; } /* Check solidity */ @@ -726,7 +756,7 @@ tessellate_part(struct creo_conv_info *cinfo, ProMdl model, struct bu_vls **snam vert_tree->the_array, &faces[0], NULL); /* If it's not solid and we're testing solidity, keep trying... */ - if (!success) + if (!success) { if (cinfo->check_solidity) { /* Free the tessellation memory */ ProPartTessellationFree(&tess); @@ -736,29 +766,29 @@ tessellate_part(struct creo_conv_info *cinfo, ProMdl model, struct bu_vls **snam bg_vert_tree_clean(vert_tree); bg_vert_tree_clean(norm_tree); - creo_log(cinfo, MSG_DEBUG, "Tessellation of \"%s\" failed solidity test " - "with %g mm and %g deg, trying next level\n", - pname, curr_error, curr_angle); + creo_log(cinfo, MSG_PLAIN, " TESS: \"%s\" failed solidity test " + "with %g and %g, trying next level\n", + pname, curr_chord, curr_angle); /* failed bot, solidity enforced, so keep trying */ continue; + } else - creo_log(cinfo, MSG_DEBUG, "Tessellation of \"%s\" failed solidity test, " + creo_log(cinfo, MSG_PLAIN, " TESS: \"%s\" failed solidity test, " "but solidity requirement is disabled\n", pname); - else + } else break; } - if (!success) { - cinfo->tess_chord = -1.0; - cinfo->tess_angle = -1.0; - err = PRO_TK_NOT_EXIST; - goto tess_cleanup; - } else { - cinfo->tess_chord = curr_error; + if (success) { + cinfo->tess_count = facet_count; + cinfo->tess_chord = curr_chord; cinfo->tess_angle = curr_angle; err = PRO_TK_NO_ERROR; + } else { + err = PRO_TK_NOT_EXIST; + goto tess_cleanup; } /* Make sure we have non-zero faces (and if needed, face_normals) vectors */ @@ -771,11 +801,13 @@ tessellate_part(struct creo_conv_info *cinfo, ProMdl model, struct bu_vls **snam goto tess_cleanup; } - creo_log(cinfo, MSG_SUCCESS, "Tessellation of \"%s\" successful with %g mm and %g deg\n", - pname, curr_error, curr_angle); + creo_log(cinfo, MSG_PLAIN, " TESS: Tessellation of \"%s\" successful with %g and %g\n", + pname, curr_chord, curr_angle); + creo_log(cinfo, MSG_PLAIN, " TESS: Tessellation of \"%s\" produced %d facets\n", + pname, facet_count); for (unsigned int i = 0; i < vert_tree->curr_vert * 3; i++) - vert_tree->the_array[i] = vert_tree->the_array[i] * factor; + vert_tree->the_array[i] = vert_tree->the_array[i] * conv_scale; /* Output the solid - TODO - what is the correct ordering??? does CCW always work? */ *sname = get_brlcad_name(cinfo, wname, "s", N_SOLID); @@ -831,20 +863,20 @@ output_part(struct creo_conv_info *cinfo, ProMdl model) ProFeatureResumeOptions *resume_opts; ProSurfaceAppearanceProps aprops; - char mname[MAX_MATL_NAME]; + char mname[MAX_MATL_NAME + 1]; char pname[CREO_NAME_MAX]; wchar_t wname[CREO_NAME_MAX]; char *verstr; - double prtdens = 1.0; - double bbox_vol = 0.0; - double bbox_area = 0.0; + double prtdens = 1.0; + + /* bounding box flags */ + int have_bbox = 0; + int have_rpp = 0; fastf_t rgbflts[3]; - int bbox_created = 0; - int have_bbox = 0; int surface_side = 0; /* 0 = surface normal; 1 = other side */ int rgb_mode = -1; @@ -852,8 +884,6 @@ output_part(struct creo_conv_info *cinfo, ProMdl model) struct directory *rdp; struct directory *sdp; - struct bu_attribute_value_set r_avs; - struct bu_attribute_value_set s_avs; struct bu_vls vstr = BU_VLS_INIT_ZERO; struct bu_color color; struct wmember wcomb; @@ -879,7 +909,7 @@ output_part(struct creo_conv_info *cinfo, ProMdl model) ProWstringToString(pname, wname); lower_case(pname); - creo_log(cinfo, MSG_SUCCESS, "Processing \"%s\"\n", pname); + creo_log(cinfo, MSG_PLAIN, " PART: Processing \"%s\"\n", pname); /* * TODO - add some up-front logic to detect parts with no @@ -887,12 +917,12 @@ output_part(struct creo_conv_info *cinfo, ProMdl model) */ /* Collect info about things that might be eliminated */ - if (cinfo->do_elims) { + if (cinfo->elim_small) { /* * Apply user supplied criteria to see if we have anything * to suppress */ - ProSolidFeatVisit(ProMdlToSolid(model), do_feature_visit, feature_filter, (ProAppData)pinfo); + ProSolidFeatVisit(ProMdlToSolid(model), feature_visit, feature_filter, (ProAppData)pinfo); /* If we've got anything to suppress, go ahead and do it. */ if (!pinfo->suppressed_features->empty()) { @@ -902,10 +932,10 @@ output_part(struct creo_conv_info *cinfo, ProMdl model) PRO_REGEN_NO_FLAGS); /* If something went wrong, need to undo just the suppressions we added */ if (supp_err != PRO_TK_NO_ERROR) { - creo_log(cinfo, MSG_DEBUG, "\"%s\" failed to suppress features\n", pname); + creo_log(cinfo, MSG_PLAIN, " FEAT: \"%s\" failed to suppress features\n", pname); unsuppress_features(pinfo); } else - creo_log(cinfo, MSG_DEBUG, "\"%s\" features suppressed, continuing conversion\n", pname); + creo_log(cinfo, MSG_PLAIN, " FEAT: \"%s\" features suppressed, continuing conversion\n", pname); } } @@ -915,6 +945,31 @@ output_part(struct creo_conv_info *cinfo, ProMdl model) */ have_bbox = (ProSolidOutlineGet(ProMdlToSolid(model), bboxpnts) == PRO_TK_NO_ERROR); + /* Retain bounding box results */ + if (have_bbox) { + double dx, dy, dz; + dx = abs(bboxpnts[1][0] - bboxpnts[0][0]); + dy = abs(bboxpnts[1][1] - bboxpnts[0][1]); + dz = abs(bboxpnts[1][2] - bboxpnts[0][2]); + cinfo->bbox_area = 2.0*(dx*dy + dx*dz + dy*dz); + cinfo->bbox_diag = sqrt(pow(dx,2) + pow(dy,2) + pow(dz,2)); + cinfo->bbox_vol = dx*dy*dz; + creo_log(cinfo, MSG_PLAIN, " PART: ==============================\n"); + creo_log(cinfo, MSG_PLAIN, " PART: Bounding Box \n"); + creo_log(cinfo, MSG_PLAIN, " PART: ------------------------------\n"); + creo_log(cinfo, MSG_PLAIN, " PART: dx = %g\n", dx); + creo_log(cinfo, MSG_PLAIN, " PART: dy = %g\n", dy); + creo_log(cinfo, MSG_PLAIN, " PART: dz = %g\n", dy); + creo_log(cinfo, MSG_PLAIN, " PART: Diagonal = %g\n", cinfo->bbox_diag); + creo_log(cinfo, MSG_PLAIN, " PART: Surface area = %g\n", cinfo->bbox_area); + creo_log(cinfo, MSG_PLAIN, " PART: Volume = %g\n", cinfo->bbox_vol); + creo_log(cinfo, MSG_PLAIN, " PART: ------------------------------\n"); + } else { + creo_log(cinfo, MSG_FAIL, "Part \"%s\" has no bounding box\n", pname); + tess_err = PRO_TK_NOT_EXIST; + goto cleanup; + } + /* * TODO - support an option to convert to ON_Brep * @@ -927,23 +982,15 @@ output_part(struct creo_conv_info *cinfo, ProMdl model) /* Deal with the solid conversion results */ if (tess_err == PRO_TK_NOT_EXIST) { /* Failed!!! */ - creo_log(cinfo, MSG_DEBUG, "Tessellation of \"%s\" failed\n", pname); - if (cinfo->debug_bboxes && have_bbox) { + creo_log(cinfo, MSG_PLAIN, "Tessellation for \"%s\" failed\n", pname); + if (cinfo->create_boxes && have_bbox) { /* * A failed solid conversion with a bounding box indicates a * problem. Rather than ignore it, put the bbox in the .g file * as a placeholder. */ - double dx, dy, dz; point_t rmin, rmax; - dx = abs(bboxpnts[1][0] - bboxpnts[0][0]); - dy = abs(bboxpnts[1][1] - bboxpnts[0][1]); - dz = abs(bboxpnts[1][2] - bboxpnts[0][2]); - - bbox_vol = dx*dy*dz; - bbox_area = 2.0*(dx*dy + dx*dz + dy*dz); - rmin[0] = bboxpnts[0][0]; rmin[1] = bboxpnts[0][1]; rmin[2] = bboxpnts[0][2]; @@ -953,18 +1000,13 @@ output_part(struct creo_conv_info *cinfo, ProMdl model) sname = get_brlcad_name(cinfo, wname, "rpp", N_SOLID); mk_rpp(cinfo->wdbp, bu_vls_addr(sname), rmin, rmax); - creo_log(cinfo, MSG_DEBUG, "Part \"%s\" replaced with bounding box\n", pname); - - /* Retain bounding box results */ - bbox_created = 1; - cinfo->bbox_vol = bbox_vol; - cinfo->bbox_area = bbox_area; - + creo_log(cinfo, MSG_PLAIN, " PART: \"%s\" replaced with bounding box\n", pname); + have_rpp = 1; goto have_part; } else { wchar_t *stable = stable_wchar(cinfo, wname); if (!stable) - creo_log(cinfo, MSG_DEBUG, "Part \"%s\" no stable version of name found\n", pname); + creo_log(cinfo, MSG_PLAIN, " NAME: Part \"%s\" no stable version of name found\n", pname); else cinfo->empty->insert(stable); creo_log(cinfo, MSG_FAIL, "Part \"%s\" not converted\n", pname); @@ -978,10 +1020,6 @@ output_part(struct creo_conv_info *cinfo, ProMdl model) */ have_part: - // If we got here without a name, it's a no-go - if (!sname) - goto cleanup; - BU_LIST_INIT(&wcomb.l); rname = get_brlcad_name(cinfo, wname, "r", N_REGION); @@ -996,7 +1034,7 @@ output_part(struct creo_conv_info *cinfo, ProMdl model) * Get the surface properties from the part, * output the region comb */ - ProMdlToModelitem(model, &mitm); + (void)ProMdlToModelitem(model, &mitm); if (ProSurfaceSideAppearancepropsGet(&mitm, surface_side, &aprops) == PRO_TK_NO_ERROR) { /* * Shader args @@ -1026,24 +1064,23 @@ output_part(struct creo_conv_info *cinfo, ProMdl model) bu_color_from_rgb_floats(&color, rgbflts); bu_color_to_rgb_chars(&color, rgb); - creo_log(cinfo, MSG_DEBUG, "Part \"%s\" has rgb = %u/%u/%u\n", - pname, rgb[0], rgb[1], rgb[2]); + creo_log(cinfo, MSG_PLAIN, " COLOR: Part \"%s\" has rgb = %u/%u/%u\n", + pname, rgb[0], rgb[1], rgb[2]); /* Adjust rgb values for minimum luminance thresold */ if (cinfo->lmin > 0) { rgb_mode = rgb4lmin(rgbflts, cinfo->lmin); if (rgb_mode < 0) - creo_log(cinfo, MSG_DEBUG, "Part \"%s\" has unknown color error\n", pname); + creo_log(cinfo, MSG_PLAIN, " COLOR: Part \"%s\" has unknown color error\n", pname); else if (rgb_mode == 0) - creo_log(cinfo, MSG_DEBUG, "Part \"%s\" luminance exceeds the %d%s minimum\n", + creo_log(cinfo, MSG_PLAIN, " COLOR: Part \"%s\" luminance exceeds the %d%s minimum\n", pname, cinfo->lmin, "%"); else { bu_color_to_rgb_chars(&color, creo_rgb); /* Preserve existing Creo rgb values */ bu_color_from_rgb_floats(&color, rgbflts); /* Adopt the enhanced rgb values */ - bu_color_to_rgb_chars(&color, rgb); - creo_log(cinfo, MSG_DEBUG, "Part \"%s\" luminance has increased to %d%s\n", + creo_log(cinfo, MSG_PLAIN, " COLOR: Part \"%s\" luminance has increased to %d%s\n", pname, cinfo->lmin, "%"); - creo_log(cinfo, MSG_DEBUG, "Part \"%s\" color changed to rgb = %u/%u/%u\n", + creo_log(cinfo, MSG_PLAIN, " COLOR: Part \"%s\" color changed to rgb = %u/%u/%u\n", pname, rgb[0], rgb[1], rgb[2]); } } @@ -1056,7 +1093,7 @@ output_part(struct creo_conv_info *cinfo, ProMdl model) } else { /* Substitute a default color */ rgb[0] = 255; rgb[1] = 255; rgb[2] = 0; - creo_log(cinfo, MSG_DEBUG, "Surface properties unavailable for \"%s\", default rgb = %u/%u/%u\n", + creo_log(cinfo, MSG_PLAIN, " COLOR: Surface properties unavailable for \"%s\", default rgb = %u/%u/%u\n", pname, rgb[0], rgb[1], rgb[2]); mk_comb(cinfo->wdbp, bu_vls_addr(rname), &wcomb.l, 1, NULL, NULL, (const unsigned char *)rgb, @@ -1066,180 +1103,172 @@ output_part(struct creo_conv_info *cinfo, ProMdl model) /* Set the attributes for the solid/primitive */ ptc_name = get_brlcad_name(cinfo, wname, NULL, N_CREO); sdp = db_lookup(cinfo->wdbp->dbip, bu_vls_addr(sname), LOOKUP_QUIET); - db5_get_attributes(cinfo->wdbp->dbip, &s_avs, sdp); - bu_avs_add(&s_avs, "importer", "creo-g"); - bu_avs_add(&s_avs, "ptc_name", bu_vls_addr(ptc_name)); - if (bbox_created) { - bu_avs_add(&s_avs, "solid_status", "failed"); - bu_vls_sprintf(&vstr, "%g", cinfo->bbox_vol); - bu_avs_add(&s_avs, "rpp_vol" , bu_vls_addr(&vstr)); + db5_get_attributes(cinfo->wdbp->dbip, &cinfo->avs, sdp); + bu_avs_add(&cinfo->avs, "importer", "creo-g"); + bu_avs_add(&cinfo->avs, "ptc_name", bu_vls_addr(ptc_name)); + if (have_rpp) { bu_vls_sprintf(&vstr, "%g", cinfo->bbox_area); - bu_avs_add(&s_avs, "rpp_area" , bu_vls_addr(&vstr)); + bu_avs_add(&cinfo->avs, "rpp_area", bu_vls_addr(&vstr)); + bu_vls_sprintf(&vstr, "%g", cinfo->bbox_diag); + bu_avs_add(&cinfo->avs, "rpp_diag", bu_vls_addr(&vstr)); + bu_vls_sprintf(&vstr, "%g", cinfo->bbox_vol); + bu_avs_add(&cinfo->avs, "rpp_vol", bu_vls_addr(&vstr)); + bu_avs_add(&cinfo->avs, "tess_fail", bu_vls_addr(ptc_name)); bu_vls_free(&vstr); } else { + bu_vls_sprintf(&vstr, "%d", cinfo->tess_count); + bu_avs_add(&cinfo->avs, "tess_count" , bu_vls_addr(&vstr)); bu_vls_sprintf(&vstr, "%g", cinfo->tess_chord); - bu_avs_add(&s_avs, "tess_chord" , bu_vls_addr(&vstr)); + bu_avs_add(&cinfo->avs, "tess_chord" , bu_vls_addr(&vstr)); bu_vls_sprintf(&vstr, "%g", cinfo->tess_angle); - bu_avs_add(&s_avs, "tess_angle" , bu_vls_addr(&vstr)); + bu_avs_add(&cinfo->avs, "tess_angle" , bu_vls_addr(&vstr)); bu_vls_free(&vstr); } - db5_standardize_avs(&s_avs); - db5_update_attributes(sdp, &s_avs, cinfo->wdbp->dbip); + db5_standardize_avs(&cinfo->avs); + db5_update_attributes(sdp, &cinfo->avs, cinfo->wdbp->dbip); /* Set the Creo attributes for the region */ rdp = db_lookup(cinfo->wdbp->dbip, bu_vls_addr(rname), LOOKUP_QUIET); - db5_get_attributes(cinfo->wdbp->dbip, &r_avs, rdp); - bu_avs_add(&r_avs, "ptc_name", bu_vls_addr(ptc_name)); + db5_get_attributes(cinfo->wdbp->dbip, &cinfo->avs, rdp); + + bu_avs_add(&cinfo->avs, "ptc_name", bu_vls_addr(ptc_name)); if (ProMdlVerstampGet(model, &cstamp) == PRO_TK_NO_ERROR) { if (ProVerstampStringGet(cstamp, &verstr) == PRO_TK_NO_ERROR) - bu_avs_add(&r_avs, "ptc_version_stamp", verstr); + bu_avs_add(&cinfo->avs, "ptc_version_stamp", verstr); ProVerstampStringFree(&verstr); } /* If the part has a material, extract the name, otherwise use a default */ if (ProMaterialCurrentGet(ProMdlToSolid(model), &material) == PRO_TK_NO_ERROR) { ProWstringToString(mname, material.matl_name); - for (int n = 0; n < MAX_LINE_SIZE; n++) /* Enforce lowercase */ - if (n <= int(strlen(mname))) - mname[n] = tolower(mname[n]); - else { - mname[n++] = '\0'; - break; - } + for (int n = 0; mname[n]; n++) + mname[n] = tolower(mname[n]); } else - bu_strlcpy(mname,"undefined", MAX_MATL_NAME); + strcpy(mname,"undefined"); - bu_strlcpy(cinfo->mtl_key, mname, MAX_MATL_NAME); - creo_log(cinfo, MSG_SUCCESS, "Part \"%s\" has ptc_material_name = \"%s\"\n", + strcpy(cinfo->mtl_key, mname); + creo_log(cinfo, MSG_PLAIN, " MATL: Part \"%s\" has ptc_material_name = \"%s\"\n", pname, cinfo->mtl_key); + /* Enforce material name attribute */ + bu_avs_add(&cinfo->avs, "ptc_material_name", mname); + /* If a translation table exists, attempt to find the material */ if (cinfo->mtl_rec > 0) { if (find_matl(cinfo)) { int p = cinfo->mtl_ptr; - creo_log(cinfo, MSG_SUCCESS, "======== \"%s\" ========\n", cinfo->mtl_str[p]); - creo_log(cinfo, MSG_SUCCESS, " item = %d\n" , p + 1); - creo_log(cinfo, MSG_SUCCESS, " material_id = %d\n" , cinfo->mtl_id[p]); - creo_log(cinfo, MSG_SUCCESS, " los = %d%s\n" , cinfo->mtl_los[p], "%"); - creo_log(cinfo, MSG_SUCCESS, "-------- \"%s\" --------\n", cinfo->mtl_str[p]); + creo_log(cinfo, MSG_PLAIN, " MATL: ========== \"%s\" ==========\n", cinfo->mtl_str[p]); + creo_log(cinfo, MSG_PLAIN, " MATL: item = %d\n" , p + 1); + creo_log(cinfo, MSG_PLAIN, " MATL: material_id = %d\n" , cinfo->mtl_id[p]); + creo_log(cinfo, MSG_PLAIN, " MATL: los = %d%s\n" , cinfo->mtl_los[p], "%"); + creo_log(cinfo, MSG_PLAIN, " MATL: ---------- \"%s\" ----------\n", cinfo->mtl_str[p]); /* Add material attributes when material_id is positive */ if (cinfo->mtl_id[p] >= 0) { - bu_avs_add(&r_avs, "ptc_material_name", mname); bu_vls_sprintf(&vstr, "%d", cinfo->mtl_id[p]); - bu_avs_add(&r_avs, "material_id" , bu_vls_addr(&vstr)); + bu_avs_add(&cinfo->avs, "material_id" , bu_vls_addr(&vstr)); bu_vls_sprintf(&vstr, "%d", cinfo->mtl_los[p]); - bu_avs_add(&r_avs, "los" , bu_vls_addr(&vstr)); + bu_avs_add(&cinfo->avs, "los" , bu_vls_addr(&vstr)); bu_vls_free(&vstr); } else { - creo_log(cinfo, MSG_SUCCESS, "Material attributes for material \"%s\" are suppressed\n", + creo_log(cinfo, MSG_PLAIN, " MATL: Attributes for \"%s\" are suppressed\n", mname); - } + } } else { - creo_log(cinfo, MSG_FAIL, "Unable to find \"%s\" in the material table\n", + creo_log(cinfo, MSG_PLAIN, " MATL: Unable to find \"%s\" in the material table\n", cinfo->mtl_key); - } + } } /* When luminance increases, add the "ptc_rgb" attribute */ if (rgb_mode > 0) { bu_vls_sprintf(&vstr, "%u/%u/%u", creo_rgb[0], creo_rgb[1], creo_rgb[2]); - bu_avs_add(&r_avs, "ptc_rgb", bu_vls_addr(&vstr)); + bu_avs_add(&cinfo->avs, "ptc_rgb" , bu_vls_addr(&vstr)); bu_vls_free(&vstr); } /* Extract mass properties */ if (ProSolidMassPropertyGet(ProMdlToSolid(model), NULL, &massprops) == PRO_TK_NO_ERROR) { - creo_log(cinfo, MSG_SUCCESS, "======== \"%s\" ========\n", pname); + creo_log(cinfo, MSG_PLAIN, " SOLID: ========== \"%s\" ==========\n", pname); if (massprops.volume > 0.0) - creo_log(cinfo, MSG_SUCCESS, " volume = %g\n", + creo_log(cinfo, MSG_PLAIN, " SOLID: volume = %g\n", massprops.volume); else - creo_log(cinfo, MSG_SUCCESS, " volume = \"%g\" %s\n", + creo_log(cinfo, MSG_PLAIN, " SOLID: volume = \"%g\" %s\n", massprops.volume, "(invalid, using 0.0)"); if (massprops.surface_area > 0.0) - creo_log(cinfo, MSG_SUCCESS, " surface area = %g\n", + creo_log(cinfo, MSG_PLAIN, " SOLID: surface area = %g\n", massprops.surface_area); else - creo_log(cinfo, MSG_SUCCESS, " surface area = \"%g\" %s\n", + creo_log(cinfo, MSG_PLAIN, " SOLID: surface area = \"%g\" %s\n", massprops.surface_area, "(invalid, using 0.0)"); if (NEAR_EQUAL(massprops.density, 1.0, SMALL_FASTF)) { - creo_log(cinfo, MSG_SUCCESS, " density = \"%g\" %s\n", - massprops.density, "(unassigned, using 1.0)"); + creo_log(cinfo, MSG_PLAIN, " SOLID: density = \"%g\" %s\n", + massprops.density,"(unassigned, using 1.0)"); prtdens = 1.0; } else if (massprops.density < 0.0 ) { - creo_log(cinfo, MSG_SUCCESS, " density = \"%g\" %s\n", - massprops.density, "(invalid, using 1.0)"); + creo_log(cinfo, MSG_PLAIN, " SOLID: density = \"%g\" %s\n", + massprops.density,"(invalid, using 1.0)"); prtdens = 1.0; } else { - creo_log(cinfo, MSG_SUCCESS, " density = %g\n", + creo_log(cinfo, MSG_PLAIN, " SOLID: density = %g\n", massprops.density); prtdens = massprops.density; } if (massprops.mass > 0.0) - creo_log(cinfo, MSG_SUCCESS, " mass = %g\n", + creo_log(cinfo, MSG_PLAIN, " SOLID: mass = %g\n", massprops.mass); else - creo_log(cinfo, MSG_SUCCESS, " mass = %g %s\n", - massprops.mass, "(invalid, using 0.0)"); - creo_log(cinfo, MSG_SUCCESS, "-------- \"%s\" --------\n", pname); + creo_log(cinfo, MSG_PLAIN, " SOLID: mass = %g %s\n", + massprops.mass, "(invalid, using 0.0)"); + creo_log(cinfo, MSG_PLAIN, " SOLID: ---------- \"%s\" ----------\n", pname); /* Create volume attribute */ - bu_vls_sprintf(&vstr, "%g", std::max(massprops.volume,0.0)); - bu_avs_add(&r_avs, "volume" , bu_vls_addr(&vstr)); + bu_vls_sprintf(&vstr, "%g", max(massprops.volume,0.0)); + bu_avs_add(&cinfo->avs, "volume" , bu_vls_addr(&vstr)); /* Create surface area attribute */ - bu_vls_sprintf(&vstr, "%g", std::max(massprops.surface_area,0.0)); - bu_avs_add(&r_avs, "surface_area", bu_vls_addr(&vstr)); + bu_vls_sprintf(&vstr, "%g", max(massprops.surface_area,0.0)); + bu_avs_add(&cinfo->avs, "surface_area", bu_vls_addr(&vstr)); /* Create mass attribute */ - bu_vls_sprintf(&vstr, "%g", std::max(massprops.mass,0.0)); - bu_avs_add(&r_avs, "mass" , bu_vls_addr(&vstr)); + bu_vls_sprintf(&vstr, "%g", max(massprops.mass,0.0)); + bu_avs_add(&cinfo->avs, "mass" , bu_vls_addr(&vstr)); bu_vls_free(&vstr); } else if (ProPartDensityGet(ProMdlToPart(model), &prtdens) == PRO_TK_NO_ERROR) { - creo_log(cinfo, MSG_DEBUG, "Part \"%s\" has no mass property values\n", pname); + creo_log(cinfo, MSG_PLAIN, " SOLID: \"%s\" has no mass property values\n", pname); /* If the part has a density, extract the value, otherwise use a default */ if (NEAR_EQUAL(prtdens, 1.0, SMALL_FASTF)) { - creo_log(cinfo, MSG_DEBUG, "Part \"%s\" has no material assigned, density = %g\n", + creo_log(cinfo, MSG_PLAIN, " MASS: Part \"%s\" has no material assigned, density = %g\n", pname, prtdens); prtdens = 1.0; } else if (prtdens < 0.0 ) { - creo_log(cinfo, MSG_DEBUG, "Part \"%s\" has a negative density, value \"%g\" ignored\n", + creo_log(cinfo, MSG_PLAIN, " MASS: Part \"%s\" has a negative density, value \"%g\" ignored\n", pname, prtdens); prtdens = 1.0; } else - creo_log(cinfo, MSG_DEBUG, "Part \"%s\" has density = %g\n", + creo_log(cinfo, MSG_PLAIN, " MASS: Part \"%s\" has density = %g\n", pname, prtdens); } else prtdens = 1.0; if (NEAR_EQUAL(prtdens, 1.0, SMALL_FASTF)) - creo_log(cinfo, MSG_DEBUG, "Part \"%s\" has been assigned a default value, density = %g\n", + creo_log(cinfo, MSG_PLAIN, " MASS: Part \"%s\" has been assigned a default value, density = %g\n", pname, prtdens); /* Create density attribute */ bu_vls_sprintf(&vstr, "%g", prtdens); - bu_avs_add(&r_avs, "density", bu_vls_addr(&vstr)); /* Add density attribute */ + bu_avs_add(&cinfo->avs, "density", bu_vls_addr(&vstr)); /* Add density attribute */ bu_vls_free(&vstr); - /* If we have a user supplied list of attributes to save, do it */ - if (cinfo->attrs->size() > 0) { - for (unsigned int i = 0; i < cinfo->attrs->size(); i++) { - char *attr_val = NULL; - const char *arg = cinfo->attrs->at(i); - creo_attribute_val(&attr_val, arg, model); - if (attr_val) { - bu_avs_add(&r_avs, arg, attr_val); - bu_free(attr_val, "value string"); - } - } - } + /* Export user-supplied list of parameters */ + param_export(cinfo, model, pname); /* Update attributes stored on disk */ - db5_standardize_avs(&r_avs); - db5_update_attributes(rdp, &r_avs, cinfo->wdbp->dbip); + db5_standardize_avs(&cinfo->avs); + db5_update_attributes(rdp, &cinfo->avs, cinfo->wdbp->dbip); /* Increment the region id - this is a concern if we move to multithreaded generation... */ cinfo->reg_id++; @@ -1247,24 +1276,27 @@ output_part(struct creo_conv_info *cinfo, ProMdl model) cleanup: /* Unsuppress anything we suppressed */ - if (cinfo->do_elims && !pinfo->suppressed_features->empty()) { - creo_log(cinfo, MSG_SUCCESS, "Unsuppressing %zu features\n", pinfo->suppressed_features->size()); + if (cinfo->elim_small && !pinfo->suppressed_features->empty()) { + creo_log(cinfo, MSG_PLAIN, " FEAT: Unsuppressing %zu features\n", pinfo->suppressed_features->size()); supp_err = ProFeatureWithoptionsResume(ProMdlToSolid(model), &pinfo->suppressed_features->at(0), resume_opts, PRO_REGEN_NO_FLAGS); if (supp_err != PRO_TK_NO_ERROR) { - creo_log(cinfo, MSG_DEBUG, "Failed to unsuppress feature(s) for \"%s\"\n", pname); + creo_log(cinfo, MSG_PLAIN, " FEAT: Failed to unsuppress feature(s) for \"%s\"\n", pname); cinfo->warn_feature_unsuppress = 1; } else - creo_log(cinfo, MSG_DEBUG, "Successfully unsuppressed feature(s) for \"%s\"\n", pname); + creo_log(cinfo, MSG_PLAIN, " FEAT: Successfully unsuppressed feature(s) for \"%s\"\n", pname); } delete pinfo->suppressed_features; delete pinfo->subtractions; BU_GET(pinfo, struct part_conv_info); - /* No tessellation error for bounding boxes */ - if (bbox_created) - return PRO_TK_NO_ERROR; + /* Identify when bounding box replaces failed tessellation */ + cinfo->tess_bbox = (have_bbox & have_rpp); + + /* Log bounding box as a part failure */ + if (cinfo->tess_bbox) + creo_log(cinfo, MSG_FAIL, "Part \"%s\" replaced with bounding box\n", pname); return tess_err; } diff --git a/src/external/Creo/resources/creo_brl.res b/src/external/Creo/resources/creo_brl.res index c809b865d6..0964d1083a 100644 --- a/src/external/Creo/resources/creo_brl.res +++ b/src/external/Creo/resources/creo_brl.res @@ -2,7 +2,7 @@ !* Title: creo_brl.res !* Purpose: Dialog box resource file for Creo to BRL-CAD Converter !* Version: Created for use with Creo version 7.0.9.0 -!* Date: 10/21/2022 +!* Date: 3/22/2023 !* !* Notes: !* 1) Refer to: ..\src\external\Creo\main.cpp for more information @@ -111,10 +111,10 @@ (InputPanel mtl_fname) (Label empty_label) (Label parameter_label) - (Label attr_rename_l) - (InputPanel attr_rename) - (Label attr_save_l) - (InputPanel attr_save) + (Label param_rename_l) + (InputPanel param_rename) + (Label param_save_l) + (InputPanel param_save) ) (Resources (out_fname_l.AttachRight True) @@ -168,24 +168,24 @@ (parameter_label.AttachLeft True) (parameter_label.Label "Creo Parameters") (parameter_label.LeftOffset 150) - (attr_rename_l.AttachRight True) - (attr_rename_l.Label "Create object names:") - (attr_rename_l.LeftOffset 4) - (attr_rename_l.RightOffset 0) - (attr_rename.AttachLeft True) - (attr_rename.HelpText "Enter a comma-separated list of Creo parameters which create BRL-CAD object names (optional)") - (attr_rename.LeftOffset 0) - (attr_rename.RightOffset 4) - (attr_rename.Value "") - (attr_save_l.AttachRight True) - (attr_save_l.Label "Preserve as attributes:") - (attr_save_l.LeftOffset 4) - (attr_save_l.RightOffset 0) - (attr_save.AttachLeft True) - (attr_save.HelpText "Enter a comma-separated list of Creo parameters to preserve in the BRL-CAD .g file (optional)") - (attr_save.LeftOffset 0) - (attr_save.RightOffset 4) - (attr_save.Value "") + (param_rename_l.AttachRight True) + (param_rename_l.Label "Create object names:") + (param_rename_l.LeftOffset 4) + (param_rename_l.RightOffset 0) + (param_rename.AttachLeft True) + (param_rename.HelpText "Enter a comma-separated list of Creo parameters which create BRL-CAD object names (optional)") + (param_rename.LeftOffset 0) + (param_rename.RightOffset 4) + (param_rename.Value "nomenclature") + (param_save_l.AttachRight True) + (param_save_l.Label "Preserve as attributes:") + (param_save_l.LeftOffset 4) + (param_save_l.RightOffset 0) + (param_save.AttachLeft True) + (param_save.HelpText "Enter a comma-separated list of Creo parameters to preserve in the BRL-CAD .g file (optional)") + (param_save.LeftOffset 0) + (param_save.RightOffset 4) + (param_save.Value "nomenclature,part_name") (.AttachTop True) (.BottomOffset 4) (.Decorated False) @@ -202,10 +202,10 @@ mtl_fname empty_label parameter_label - attr_rename_l - attr_rename - attr_save_l - attr_save + param_rename_l + param_rename + param_save_l + param_save ) ) ) @@ -294,68 +294,68 @@ (Layout tessellation_controls (Components - (Label max_error_l) - (InputPanel max_error) - (Label min_error_l) - (InputPanel min_error) - (Label max_angle_ctrl_l) - (InputPanel max_angle_ctrl) - (Label min_angle_ctrl_l) - (InputPanel min_angle_ctrl) - (Label isteps_l) - (InputPanel isteps) + (Label max_chord_l) + (InputPanel max_chord) + (Label min_chord_l) + (InputPanel min_chord) + (Label max_angle_l) + (InputPanel max_angle) + (Label min_angle_l) + (InputPanel min_angle) + (Label max_steps_l) + (InputPanel max_steps) ) (Resources - (max_error_l.AttachRight True) - (max_error_l.Label "Max chord error, mm:") - (max_error_l.LeftOffset 2) - (max_error_l.RightOffset 0) - (max_error.AttachLeft True) - (max_error.HelpText "Enter maximum chord error for tessellation of curved surfaces") - (max_error.InputType 3) - (max_error.LeftOffset 0) - (max_error.RightOffset 2) - (max_error.Value "1.0") - (min_error_l.AttachRight True) - (min_error_l.Label "Min chord error, mm:") - (min_error_l.LeftOffset 2) - (min_error_l.RightOffset 0) - (min_error.AttachLeft True) - (min_error.HelpText "Enter minimum chord error for tessellation of curved surfaces") - (min_error.InputType 3) - (min_error.LeftOffset 0) - (min_error.RightOffset 2) - (min_error.Value "0.1") - (max_angle_ctrl_l.AttachRight True) - (max_angle_ctrl_l.Label "Max angle control, deg:") - (max_angle_ctrl_l.LeftOffset 2) - (max_angle_ctrl_l.RightOffset 0) - (max_angle_ctrl.AttachLeft True) - (max_angle_ctrl.HelpText "Larger values here produce finer tessellations [0.0 to 1.0]") - (max_angle_ctrl.InputType 3) - (max_angle_ctrl.LeftOffset 0) - (max_angle_ctrl.RightOffset 2) - (max_angle_ctrl.Value "1.0") - (min_angle_ctrl_l.AttachRight True) - (min_angle_ctrl_l.Label "Min angle control, deg:") - (min_angle_ctrl_l.LeftOffset 2) - (min_angle_ctrl_l.RightOffset 0) - (min_angle_ctrl.AttachLeft True) - (min_angle_ctrl.HelpText "Larger values here produce finer tessellations [0.0 to 1.0]") - (min_angle_ctrl.InputType 3) - (min_angle_ctrl.LeftOffset 0) - (min_angle_ctrl.RightOffset 2) - (min_angle_ctrl.Value "1.0") - (isteps_l.AttachRight True) - (isteps_l.Label "Max to Min control steps:") - (isteps_l.LeftOffset 2) - (isteps_l.RightOffset 0) - (isteps.AttachLeft True) - (isteps.HelpText "Enter number of steps between the min to max angle control value") - (isteps.InputType 2) - (isteps.LeftOffset 0) - (isteps.RightOffset 2) - (isteps.Value "20") + (max_chord_l.AttachRight True) + (max_chord_l.Label "Max chord height, mm:") + (max_chord_l.LeftOffset 2) + (max_chord_l.RightOffset 0) + (max_chord.AttachLeft True) + (max_chord.HelpText "Enter maximum chord height for tessellation of curved surfaces") + (max_chord.InputType 3) + (max_chord.LeftOffset 0) + (max_chord.RightOffset 2) + (max_chord.Value "0.0") + (min_chord_l.AttachRight True) + (min_chord_l.Label "Min chord height, mm:") + (min_chord_l.LeftOffset 2) + (min_chord_l.RightOffset 0) + (min_chord.AttachLeft True) + (min_chord.HelpText "Enter minimum chord height for tessellation of curved surfaces") + (min_chord.InputType 3) + (min_chord.LeftOffset 0) + (min_chord.RightOffset 2) + (min_chord.Value "0.0") + (max_angle_l.AttachRight True) + (max_angle_l.Label "Max angle control:") + (max_angle_l.LeftOffset 2) + (max_angle_l.RightOffset 0) + (max_angle.AttachLeft True) + (max_angle.HelpText "Larger values here produce finer tessellations [0.0 to 1.0]") + (max_angle.InputType 3) + (max_angle.LeftOffset 0) + (max_angle.RightOffset 2) + (max_angle.Value "1.0") + (min_angle_l.AttachRight True) + (min_angle_l.Label "Min angle control:") + (min_angle_l.LeftOffset 2) + (min_angle_l.RightOffset 0) + (min_angle.AttachLeft True) + (min_angle.HelpText "Larger values here produce finer tessellations [0.0 to 1.0]") + (min_angle.InputType 3) + (min_angle.LeftOffset 0) + (min_angle.RightOffset 2) + (min_angle.Value "0.1") + (max_steps_l.AttachRight True) + (max_steps_l.Label "Maximum number of steps:") + (max_steps_l.LeftOffset 2) + (max_steps_l.RightOffset 0) + (max_steps.AttachLeft True) + (max_steps.HelpText "Enter maximum number of tessellation attempts") + (max_steps.InputType 2) + (max_steps.LeftOffset 0) + (max_steps.RightOffset 2) + (max_steps.Value "50") (.Alignment 0) (.AttachLeft True) (.AttachTop True) @@ -366,16 +366,16 @@ (.TopOffset 1) (.Layout (Grid (Rows 1 1 1 1 1) (Cols 1 1) - max_error_l - max_error - min_error_l - min_error - max_angle_ctrl_l - max_angle_ctrl - min_angle_ctrl_l - min_angle_ctrl - isteps_l - isteps + max_chord_l + max_chord + min_chord_l + min_chord + max_angle_l + max_angle + min_angle_l + min_angle + max_steps_l + max_steps ) ) ) @@ -478,9 +478,9 @@ (Layout surface_controls (Components (CheckButton facets_only) - (CheckButton get_normals) (CheckButton check_solidity) - (CheckButton debug_bboxes) + (CheckButton create_boxes) + (CheckButton get_normals) ) (Resources (facets_only.AttachLeft True) @@ -492,6 +492,24 @@ (facets_only.RightOffset 88) (facets_only.Set True) (facets_only.TopOffset 0) + (check_solidity.AttachLeft True) + (check_solidity.AttachTop True) + (check_solidity.BottomOffset 0) + (check_solidity.HelpText "Select this to reject BoTs that fail the solidity test (no unmated edges)") + (check_solidity.Label "Reject BoTs that fail solidity") + (check_solidity.LeftOffset 0) + (check_solidity.RightOffset 88) + (check_solidity.Set True) + (check_solidity.TopOffset 1) + (create_boxes.AttachLeft True) + (create_boxes.AttachTop True) + (create_boxes.BottomOffset 0) + (create_boxes.HelpText "Select this to create a bounding box solid from the Creo part upon part tessellation failure") + (create_boxes.Label "Bounding box replaces failed part") + (create_boxes.LeftOffset 0) + (create_boxes.RightOffset 88) + (create_boxes.Set True) + (create_boxes.TopOffset 1) (get_normals.AttachLeft True) (get_normals.AttachTop True) (get_normals.BottomOffset 0) @@ -501,24 +519,6 @@ (get_normals.RightOffset 88) (get_normals.Set False) (get_normals.TopOffset 1) - (check_solidity.AttachLeft True) - (check_solidity.AttachTop True) - (check_solidity.BottomOffset 0) - (check_solidity.HelpText "Select this to reject BoTs that fail the solidity test (no unmated edges)") - (check_solidity.Label "Reject BoTs that fail solidity") - (check_solidity.LeftOffset 0) - (check_solidity.RightOffset 88) - (check_solidity.Set False) - (check_solidity.TopOffset 1) - (debug_bboxes.AttachLeft True) - (debug_bboxes.AttachTop True) - (debug_bboxes.BottomOffset 0) - (debug_bboxes.HelpText "Select this to create a bounding box solid from the Creo part upon part tessellation failure") - (debug_bboxes.Label "Bounding box replaces failed part") - (debug_bboxes.LeftOffset 0) - (debug_bboxes.RightOffset 88) - (debug_bboxes.Set False) - (debug_bboxes.TopOffset 1) (.Alignment 0) (.AttachLeft True) (.AttachTop True) @@ -530,9 +530,9 @@ (.Layout (Grid (Rows 1 1 1 1) (Cols 1) facets_only - get_normals check_solidity - debug_bboxes + create_boxes + get_normals ) ) ) diff --git a/src/external/Creo/shim.cpp b/src/external/Creo/shim.cpp index c8a7711047..7c93a4329a 100644 --- a/src/external/Creo/shim.cpp +++ b/src/external/Creo/shim.cpp @@ -2,7 +2,7 @@ * S H I M . C P P * BRL-CAD * - * Published in 2022 by the United States Government. + * Published in 2023 by the United States Government. * This work is in the public domain. * */ @@ -90,6 +90,7 @@ extern "C" int ProUIRadiogroupSelectednamesGet(const char*,const char*,int*,char extern "C" int ProUITextareaValueSet(const char *,const char *,wchar_t*) {return 0;} extern "C" int ProUnitConversionCalculate(void**,void**,ProUnitConversion*) {return 0;} extern "C" int ProUnitsystemUnitGet(void**,int,void**) {return 0;} +extern "C" int ProUtilCollectParameters(void**,void**) {return 0;} extern "C" int ProValueDataGet(void*,ProValueData*) {return 0;} extern "C" int ProVerstampEqual(void*, void*) {return 0;} extern "C" int ProVerstampStringFree(char**) {return 0;} diff --git a/src/external/Creo/shim.h b/src/external/Creo/shim.h index 08ff6dbb77..e69b359ea0 100644 --- a/src/external/Creo/shim.h +++ b/src/external/Creo/shim.h @@ -2,7 +2,7 @@ * S H I M . H * BRL-CAD * - * Published in 2022 by the United States Government. + * Published in 2023 by the United States Government. * This work is in the public domain. * */ @@ -68,7 +68,6 @@ #define PRO_FEAT_PIPE 46 #define PRO_FEAT_PROTRUSION 47 #define PRO_FEAT_REPLACE_SURF 48 - #define PRO_FEAT_RIB 49 #define PRO_FEAT_ROUND 50 #define PRO_FEAT_SHAFT 51 @@ -264,6 +263,7 @@ extern "C" int ProUIRadiogroupSelectednamesGet(const char*,const char*,int*,char extern "C" int ProUITextareaValueSet(const char *,const char *,wchar_t*); extern "C" int ProUnitConversionCalculate(void**,void**,ProUnitConversion*); extern "C" int ProUnitsystemUnitGet(void**,int,void**); +extern "C" int ProUtilCollectParameters(void**,void**); extern "C" int ProValueDataGet(void*,ProValueData*); extern "C" int ProVerstampEqual(void*, void*); extern "C" int ProVerstampStringFree(char**); @@ -279,9 +279,9 @@ extern "C" void ProMessageClear(); extern "C" void ProPartTessellationFree(ProSurfaceTessellationData**); extern "C" void ProStringToWstring(wchar_t*,const char*); extern "C" void ProSurfaceContourVisit(void*,int(*)(void*,int,void*),int(*)(void*,void*), void*); -extern "C" void ProSurfacedataGet(void*,int*,double*,double*,int*,void**,int*); extern "C" void ProSurfaceIdGet(void*,int*); extern "C" void ProSurfaceToNURBS(void*,void***); +extern "C" void ProSurfacedataGet(void*,int*,double*,double*,int*,void**,int*); extern "C" void ProUIInputpanelMaxlenSet(const char*,const char*,int); extern "C" void ProUIMessageDialogDisplay(int,const wchar_t *,const wchar_t *,ProUIMessageButton*,int,ProUIMessageButton*); extern "C" void ProUnitInit(void*,const wchar_t *,void**); diff --git a/src/external/Creo/util.cpp b/src/external/Creo/util.cpp index 1f171a6d8d..ca39ef98be 100644 --- a/src/external/Creo/util.cpp +++ b/src/external/Creo/util.cpp @@ -1,5 +1,5 @@ /** - * U T I L . C P P + * U T I L . C P P * BRL-CAD * * Copyright (c) 2017-2023 United States Government as represented by @@ -22,6 +22,36 @@ * @file util.cpp */ + +/* */ +/* Synopsis of Utiliity Routines: */ +/* */ +/* component_filter /* Component item filter for the feature visit routine */ +/* creo_log /* Report conversion status and log file messages */ +/* creo_model_units /* Extracts Creo model units and conversion factor */ +/* creo_param_name /* Returns first valid alpha-numeric parameter name string */ +/* creo_param_val /* Extract parameter value from specified Creo model */ +/* find_matl /* Determine if specified material is on the material list */ +/* get_brlcad_name /* Returns a unique BRL-CAD object name */ +/* get_mtl_input /* Process input from specified material translation file */ +/* lower_case /* Converts string to lower case */ +/* param_append /* Append parameter to the array */ +/* param_collect /* Collect available parameters from the specified model */ +/* param_export /* Export list of model parameters */ +/* param_preserve /* Preserve available model parameters */ +/* params_to_attrs /* Preserve a list of model-specific parameters as attributes */ +/* parse_param_list /* Parse list of user-supplied parameters */ +/* PopupMsg /* Display a message in a Creo dialog box */ +/* regex_key /* Utilize regular expression match for Creo parameter name */ +/* rgb4lmin /* Modify RGB values to achieve minimum luminance threshold */ +/* scrub_vls /* Removes unwanted characters from a variable-length string */ +/* stable_wchar /* Map a string to the "stable" version found in parts/assems */ +/* trim /* Purge string of leading and trailing whitespace */ +/* wstr_to_double /* Convert wide string to double precision value */ +/* wstr_to_long /* Convert wide string to long int value */ + + + #include "common.h" #include #include @@ -29,7 +59,7 @@ /* - * Filter for the feature visit routine that selects only "component" items + * Component item filter for the feature visit routine * (should be only parts and assemblies) */ extern "C" ProError @@ -47,67 +77,7 @@ component_filter(ProFeature *feat, ProAppData *UNUSED(data)) } -extern "C" ProError -creo_attribute_val(char **val, const char *key, ProMdl m) -{ - struct bu_vls cpval = BU_VLS_INIT_ZERO; - wchar_t wkey[CREO_NAME_MAX]; - wchar_t w_val[CREO_NAME_MAX]; - char cval[CREO_NAME_MAX]; - char *fval = NULL; - - ProError err = PRO_TK_GENERAL_ERROR; - ProModelitem mitm; - ProParameter param; - ProParamvalueType ptype; - ProParamvalue pval; - ProUnititem punits; - - short b_val; - int i_val; - double d_val; - - ProStringToWstring(wkey, (char *)key); - ProMdlToModelitem(m, &mitm); - err = ProParameterInit(&mitm, wkey, ¶m); - - /* if param not found, return */ - if (err != PRO_TK_NO_ERROR) - return PRO_TK_CONTINUE; - - ProParameterValueWithUnitsGet(¶m, &pval, &punits); - ProParamvalueTypeGet(&pval, &ptype); - switch (ptype) { - case PRO_PARAM_STRING: - ProParamvalueValueGet(&pval, ptype, (void *)w_val); - ProWstringToString(cval, w_val); - if (strlen(cval) > 0) - fval = bu_strdup(cval); - break; - case PRO_PARAM_INTEGER: - ProParamvalueValueGet(&pval, ptype, (void *)&i_val); - bu_vls_sprintf(&cpval, "%d", i_val); - if (bu_vls_strlen(&cpval) > 0) - fval = bu_strdup(bu_vls_cstr(&cpval)); - break; - case PRO_PARAM_DOUBLE: - ProParamvalueValueGet(&pval, ptype, (void *)&d_val); - bu_vls_sprintf(&cpval, "%g", d_val); - if (bu_vls_strlen(&cpval) > 0) - fval = bu_strdup(bu_vls_cstr(&cpval)); - break; - case PRO_PARAM_BOOLEAN: - ProParamvalueValueGet(&pval, ptype, (void *)&b_val); - fval = (b_val) ? bu_strdup("YES") : bu_strdup("NO"); - break; - } - - *val = fval; - bu_vls_free(&cpval); - return PRO_TK_NO_ERROR; -} - - +/* Report conversion status and log file messages */ extern "C" void creo_log(struct creo_conv_info *cinfo, int msg_type, const char *fmt, ...) { /* @@ -169,6 +139,7 @@ creo_log(struct creo_conv_info *cinfo, int msg_type, const char *fmt, ...) { } +/* Extracts Creo model units and conversion factor */ extern "C" ProError creo_model_units(double *scale, ProMdl mdl) { @@ -206,76 +177,34 @@ struct pparam_data { }; -extern "C" ProError -regex_key(ProParameter *param, ProError UNUSED(status), ProAppData app_data) -{ - char pname[CREO_NAME_MAX]; - char val[CREO_NAME_MAX]; - wchar_t wval[CREO_NAME_MAX]; - - regex_t reg; - - ProParamvalue pval; - ProParamvalueType ptype; - ProUnititem punits; - - struct pparam_data *pdata = (struct pparam_data *)app_data; - if (pdata->val) - return PRO_TK_NO_ERROR; - - ProWstringToString(pname, param->id); - (void)regcomp(®, pdata->key, REG_NOSUB|REG_EXTENDED); - if (!(regexec(®, pname, 0, NULL, 0))) { - regfree(®); - return PRO_TK_CONTINUE; - } - regfree(®); - - if (ProParameterValueWithUnitsGet(param, &pval, &punits) != PRO_TK_NO_ERROR) - return PRO_TK_CONTINUE; - - if (ProParamvalueTypeGet(&pval, &ptype) != PRO_TK_NO_ERROR) - return PRO_TK_CONTINUE; - - if (ptype == PRO_PARAM_STRING) { - if (ProParamvalueValueGet(&pval, ptype, wval) != PRO_TK_NO_ERROR) - return PRO_TK_CONTINUE; - ProWstringToString(val, wval); - if (strlen(val) > 0) - pdata->val = bu_strdup(val); - } - - return PRO_TK_NO_ERROR; -} - - +/* Returns first valid alpha-numeric parameter name string */ extern "C" char * -creo_param_name(struct creo_conv_info *cinfo, wchar_t *creo_name, int flags) +creo_param_name(struct creo_conv_info *cinfo, wchar_t *creo_name, int flag) { struct pparam_data pdata; pdata.cinfo = cinfo; pdata.val = NULL; char *val = NULL; - ProModelitem itm; + ProModelitem mitm; ProMdl model; - if (flags == N_REGION || flags == N_SOLID) { + if (flag == N_REGION || flag == N_SOLID) { if (ProMdlnameInit(creo_name, PRO_MDLFILE_PART, &model) != PRO_TK_NO_ERROR) return NULL; - } else if (flags == N_ASSEM) { + } else if (flag == N_ASSEM) { if (ProMdlnameInit(creo_name, PRO_MDLFILE_ASSEMBLY, &model) != PRO_TK_NO_ERROR) return NULL; } else return NULL; - if (ProMdlToModelitem(model, &itm) != PRO_TK_NO_ERROR) + if (ProMdlToModelitem(model, &mitm) != PRO_TK_NO_ERROR) return NULL; - for (unsigned int i = 0; i < cinfo->model_parameters->size(); i++) { - pdata.key = cinfo->model_parameters->at(i); + for (unsigned int i = 0; i < cinfo->obj_name_params->size(); i++) { + pdata.key = cinfo->obj_name_params->at(i); /* First, try a direct lookup */ - creo_attribute_val(&pdata.val, pdata.key, model); + creo_param_val(&pdata.val, pdata.key, model); /* If that didn't work, and it looks like we have regex characters, * try a regex match */ if (!pdata.val) { @@ -283,7 +212,7 @@ creo_param_name(struct creo_conv_info *cinfo, wchar_t *creo_name, int flags) for (unsigned int j = 0; j < strlen(pdata.key); j++) non_alnum += !isalnum(pdata.key[j]); if (non_alnum) - ProParameterVisit(&itm, NULL, regex_key, (ProAppData)&pdata); + ProParameterVisit(&mitm, NULL, regex_key, (ProAppData)&pdata); } if (pdata.val && strlen(pdata.val) > 0) { int is_al = 0; @@ -304,7 +233,72 @@ creo_param_name(struct creo_conv_info *cinfo, wchar_t *creo_name, int flags) } -/* determine if specified material is on the material list */ +/* Extract parameter value from specified Creo model */ +extern "C" ProError +creo_param_val(char **val, const char *key, ProMdl model) +{ + struct bu_vls cpval = BU_VLS_INIT_ZERO; + wchar_t wkey[CREO_NAME_MAX]; + wchar_t w_val[CREO_NAME_MAX]; + char c_val[CREO_NAME_MAX]; + char *fval = NULL; + + ProError err = PRO_TK_GENERAL_ERROR; + ProModelitem mitm; + ProParameter param; + ProParamvalueType ptype; + ProParamvalue pval; + ProUnititem punits; + + short b_val; + int i_val; + double d_val; + + ProStringToWstring(wkey, (char *)key); + (void)ProMdlToModelitem(model, &mitm); + err = ProParameterInit(&mitm, wkey, ¶m); + + /* if param not found, return */ + if (err != PRO_TK_NO_ERROR) + return PRO_TK_CONTINUE; + + ProParameterValueWithUnitsGet(¶m, &pval, &punits); + ProParamvalueTypeGet(&pval, &ptype); + switch (ptype) { + case PRO_PARAM_STRING: + ProParamvalueValueGet(&pval, ptype, (void *)w_val); + ProWstringToString(c_val, w_val); + lower_case(c_val); + bu_vls_sprintf(&cpval, "%s", c_val); + scrub_vls(&cpval); + if (bu_vls_strlen(&cpval) > 0) + fval = bu_strdup(bu_vls_cstr(&cpval)); + break; + case PRO_PARAM_INTEGER: + ProParamvalueValueGet(&pval, ptype, (void *)&i_val); + bu_vls_sprintf(&cpval, "%d", i_val); + if (bu_vls_strlen(&cpval) > 0) + fval = bu_strdup(bu_vls_cstr(&cpval)); + break; + case PRO_PARAM_DOUBLE: + ProParamvalueValueGet(&pval, ptype, (void *)&d_val); + bu_vls_sprintf(&cpval, "%g", d_val); + if (bu_vls_strlen(&cpval) > 0) + fval = bu_strdup(bu_vls_cstr(&cpval)); + break; + case PRO_PARAM_BOOLEAN: + ProParamvalueValueGet(&pval, ptype, (void *)&b_val); + fval = (b_val) ? bu_strdup("yes") : bu_strdup("no"); + break; + } + + *val = fval; + bu_vls_free(&cpval); + return PRO_TK_NO_ERROR; +} + + +/* Determine if specified material is on the material list */ extern "C" int find_matl(struct creo_conv_info *cinfo) { @@ -326,7 +320,7 @@ find_matl(struct creo_conv_info *cinfo) } -/* Create a unique BRL-CAD object name from a possibly illegal name */ +/* Returns a unique BRL-CAD object name */ extern "C" struct bu_vls * get_brlcad_name(struct creo_conv_info *cinfo, wchar_t *name, const char *suffix, int flag) { @@ -347,29 +341,29 @@ get_brlcad_name(struct creo_conv_info *cinfo, wchar_t *name, const char *suffix, lower_case(astr); if (!stable) { - creo_log(cinfo, MSG_DEBUG, "\"%s\" unable to find stable version of name\n", astr); + creo_log(cinfo, MSG_PLAIN, " NAME: \"%s\" unable to find stable version of name\n", astr); return NULL; } - creo_log(cinfo, MSG_DEBUG, "Generating name for \"%s\"...\n", astr); + creo_log(cinfo, MSG_PLAIN, " NAME: Generating name for \"%s\"...\n", astr); switch (flag) { case N_REGION: nmap = cinfo->region_name_map; - creo_log(cinfo, MSG_DEBUG, "Name type: region\n"); + creo_log(cinfo, MSG_PLAIN, " NAME: Name type: region\n"); break; case N_ASSEM: nmap = cinfo->assem_name_map; - creo_log(cinfo, MSG_DEBUG, "Name type: assembly\n"); + creo_log(cinfo, MSG_PLAIN, " NAME: Name type: assembly\n"); break; case N_SOLID: nmap = cinfo->solid_name_map; - creo_log(cinfo, MSG_DEBUG, "Name type: solid\n"); + creo_log(cinfo, MSG_PLAIN, " NAME: Name type: solid\n"); break; case N_CREO: nmap = cinfo->creo_name_map; nset = cinfo->creo_names; - creo_log(cinfo, MSG_DEBUG, "Name type: Creo name\n"); + creo_log(cinfo, MSG_PLAIN, " NAME: Name type: Creo name\n"); break; default: return NULL; /* Ignore unknown name type */ @@ -383,7 +377,7 @@ get_brlcad_name(struct creo_conv_info *cinfo, wchar_t *name, const char *suffix, n_it = nmap->find(name); if (n_it != nmap->end()) { gname = n_it->second; - creo_log(cinfo, MSG_DEBUG, "Name \"%s\" already exists\n", bu_vls_addr(gname)); + creo_log(cinfo, MSG_PLAIN, " NAME: \"%s\" already exists\n", bu_vls_addr(gname)); return gname; } @@ -425,11 +419,11 @@ get_brlcad_name(struct creo_conv_info *cinfo, wchar_t *name, const char *suffix, for (count = 0; nset->find(gname) != nset->end(); count++) { (void)bu_vls_incr(gname, NULL, NULL, NULL, NULL); if (count == 2) - creo_log(cinfo, MSG_DEBUG, "Seeking unique name for object \"%s\"\n", bu_vls_addr(&gname_root)); + creo_log(cinfo, MSG_PLAIN, " NAME: Seeking unique object name \"%s\"\n", bu_vls_addr(&gname_root)); else if (count >= MAX_UNIQUE_NAMES) { bu_vls_free(gname); BU_PUT(gname, struct bu_vls); - creo_log(cinfo, MSG_DEBUG, "Failed name generation for \"%s\"\n", astr); + creo_log(cinfo, MSG_PLAIN, " NAME: Failed name generation for \"%s\"\n", astr); return NULL; } } @@ -442,41 +436,37 @@ get_brlcad_name(struct creo_conv_info *cinfo, wchar_t *name, const char *suffix, nset->insert(gname); nmap->insert(std::pair(stable, gname)); - creo_log(cinfo, MSG_DEBUG, "Name \"%s\" succeeded\n", bu_vls_addr(gname)); + creo_log(cinfo, MSG_PLAIN, " NAME: \"%s\" succeeded\n", bu_vls_addr(gname)); return gname; } -/* process input from specified material translation file */ +/* Process input from specified material translation file */ extern "C" int get_mtl_input(FILE *fpmtl, char *mtl_str, int *mtl_id, int *mtl_los) { - const int cols = MAX_LINE_SIZE + 1; + const int cols = MAX_MATL_NAME + 1; + const int mbuf = MAX_LINE_BUFFER; const char comments[] = "!@#$%^&*/<>?"; - char buf[MAX_LINE_SIZE + 1]; - char mtl[sizeof(buf) - 4]; + char buf[MAX_LINE_BUFFER]; + char mtl[MAX_LINE_BUFFER]; char firstc; int id, los; int recs; /* Initialize counter */ recs = 0; - while (bu_fgets(buf, cols, fpmtl) != NULL) { + while (fgets(buf, mbuf, fpmtl) != NULL) { trim(buf); firstc = buf[0]; if(strchr(comments, firstc)) /* skip comments */ continue; - else if (sscanf(buf, "%s%d%d", mtl, &id, &los) != 3) + else if (sscanf(buf, "%s%d%d", &mtl, &id, &los) != 3) continue; /* skip invalid input */ else if (recs < MAX_FILE_RECS) { - for (int n = 0; n < cols; n++) - if (n <= int(strlen(mtl))) - mtl_str[recs*cols + n] = tolower(mtl[n]); - else { - mtl_str[recs*cols + n] = '\0'; - break; - } + for (int n = 0; mtl[n]; n++) + mtl_str[recs*cols + n] = tolower(mtl[n]); mtl_id[recs] = id; mtl_los[recs] = los; recs++; @@ -489,6 +479,7 @@ get_mtl_input(FILE *fpmtl, char *mtl_str, int *mtl_id, int *mtl_los) } +/* Converts string to lower case */ extern "C" void lower_case( char *name ) { @@ -502,7 +493,197 @@ lower_case( char *name ) } -/* Throw a message up in a dialog */ +/* Append parameter to the array */ +extern "C" ProError +param_append(void *p_object, ProError filt_err, ProAppData app_data) +{ + ProError err = PRO_TK_GENERAL_ERROR; + ProArray *p_array; + + p_array = (ProArray*)((void**)app_data)[0]; + + err = ProArrayObjectAdd(p_array, PRO_VALUE_UNUSED, 1, p_object ); + + return err; +} + + +/* Collect available parameters from the specified model */ +extern "C" ProError +param_collect(ProModelitem *p_modelitem, ProParameter **p_parameters) +{ + ProError err = PRO_TK_GENERAL_ERROR; + + if (p_parameters != NULL) { + err = ProArrayAlloc(0, sizeof(ProParameter), 1, (ProArray*)p_parameters); + if (err == PRO_TK_NO_ERROR ) { + err = ProParameterVisit(p_modelitem, + NULL, + (ProParameterAction)param_append, + (ProAppData)&p_parameters); + if (err != PRO_TK_NO_ERROR) { + (void)ProArrayFree((ProArray*)p_parameters); + *p_parameters = NULL; + } + } + } + else + err = PRO_TK_BAD_INPUTS; + + return err; +} + + +/* Export list of model parameters */ +extern "C" void +param_export(struct creo_conv_info *cinfo, ProMdl model, const char *name) +{ + + if (cinfo->obj_attr_params->size() > 0) + for (unsigned int i = 0; i < cinfo->obj_attr_params->size(); i++) { + char *attr_val = NULL; + const char *arg = cinfo->obj_attr_params->at(i); + creo_param_val(&attr_val, arg, model); + if (attr_val) { + bu_avs_add(&cinfo->avs, arg, attr_val); + bu_free(attr_val, "value string"); + } + } + else + (void) param_preserve(cinfo, model, name); + +} + + +/* Preserve available model parameters */ +extern "C" ProError +param_preserve(struct creo_conv_info *cinfo, ProMdl model, const char *name) +{ + ProError err = PRO_TK_GENERAL_ERROR; + ProModelitem mitm; + ProParameter *pars; + + err = ProMdlToModelitem(model, &mitm); + if (err != PRO_TK_NO_ERROR) { + creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to get \"%s\" model item identifier\n", name); + return err; + } + + err = param_collect(&mitm, &pars); + if (err == PRO_TK_BAD_INPUTS) + creo_log(cinfo, MSG_PLAIN, "FAILURE: Invalid inputs for \"%s\" parameter collection\n", name); + else if (err != PRO_TK_NO_ERROR) + creo_log(cinfo, MSG_PLAIN, "FAILURE: Unable to collect \"%s\" model parameters\n", name); + else { + err = params_to_attrs(cinfo, model, pars); + if (err == PRO_TK_BAD_INPUTS) + creo_log(cinfo, MSG_PLAIN, "FAILURE: Invalid inputs for \"%s\" attribute creation\n", name); + else if (err == PRO_TK_NOT_EXIST) + creo_log(cinfo, MSG_PLAIN, " PARAM: No parameters for \"%s\" are available\n", name); + } + + (void)ProArrayFree((ProArray*)&pars); + return err; +} + + +/* Preserve a list of model-specific parameters as attributes */ +extern "C" ProError +params_to_attrs(struct creo_conv_info *cinfo, ProMdl model, ProParameter* pars) +{ + ProError err = PRO_TK_GENERAL_ERROR; + int count = 0; + int found = 0; + + err = ProArraySizeGet((ProArray)pars, &count); + if (err != PRO_TK_NO_ERROR) + return err; + else if (count < 1) + return PRO_TK_NOT_EXIST; + + /* Add every available parameter that has a value to the list */ + for (int i = 0; i < count; i++) { + char *attr_val = NULL; + char attr_nam[CREO_NAME_MAX]; + + ProWstringToString(attr_nam, pars[i].id); + lower_case(attr_nam); + creo_param_val(&attr_val, attr_nam, model); + + if (attr_val) { + found++; + if (found == 1) { + creo_log(cinfo, MSG_PLAIN, " PARAM: ==========================================================\n"); + creo_log(cinfo, MSG_PLAIN, " PARAM: n ptc_parameter_name value\n"); + /* xxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxx */ + creo_log(cinfo, MSG_PLAIN, " PARAM: ----------------------------------------------------------\n"); + } + creo_log(cinfo, MSG_PLAIN, " PARAM: %3d %-32s %-s\n", found, attr_nam, attr_val); + bu_avs_add(&cinfo->avs, attr_nam, attr_val); + bu_free(attr_val, "value string"); + } + } + + if (found > 0) { + creo_log(cinfo, MSG_PLAIN, " PARAM: ----------------------------------------------------------\n"); + creo_log(cinfo, MSG_PLAIN, " PARAM: Processed %d model parameters\n", count); + if (found == 1) + creo_log(cinfo, MSG_PLAIN, " PARAM: Extracted a single non-empty parameter\n"); + else + creo_log(cinfo, MSG_PLAIN, " PARAM: Extracted %d non-empty parameters \n", found); + if (count > found) + creo_log(cinfo, MSG_PLAIN, " PARAM: Extraction ratio: %.1f%s\n", + double(found)/double(count)*100.0, "%"); + else + creo_log(cinfo, MSG_PLAIN, " PARAM: Extraction ratio: 100%s\n", "%"); + } else + creo_log(cinfo, MSG_PLAIN, " PARAM: No model parameters were found\n"); + + return PRO_TK_NO_ERROR; +} + + +/* Parse list of user-supplied parameters */ +extern "C" void +parse_param_list(struct creo_conv_info *cinfo, const char *param_list, int flag) +{ + if (strlen(param_list) > 0) { + struct bu_vls msg = BU_VLS_INIT_ZERO; + if (flag == NAME_PARAMS) + bu_vls_printf(&msg, "# Creates object names:"); + else if (flag == ATTR_PARAMS) + bu_vls_printf(&msg, "# Preserved attribute:"); + else + bu_vls_printf(&msg, " FAILURE: Unknown parameter type:"); + std::string filestr(param_list); + std::istringstream ss(filestr); + std::string line; + while (std::getline(ss, line)) { + std::string key; + std::istringstream ls(line); + while (std::getline(ls, key, ',')) { + /* Scrub leading and trailing whitespace */ + size_t startpos = key.find_first_not_of(" \t\n\v\f\r"); + if (std::string::npos != startpos) + key = key.substr(startpos); + size_t endpos = key.find_last_not_of(" \t\n\v\f\r"); + if (std::string::npos != endpos) + key = key.substr(0 ,endpos+1); + if (key.length() > 0) { + if (flag == NAME_PARAMS) + cinfo->obj_name_params->push_back(bu_strdup(key.c_str())); + else if (flag == ATTR_PARAMS) + cinfo->obj_attr_params->push_back(bu_strdup(key.c_str())); + creo_log(cinfo, MSG_PLAIN, "%s \"%s\"\n", bu_vls_addr(&msg), key.c_str()); + } + } + } + bu_vls_free(&msg); + } +} + + +/* Display a message in a Creo dialog box */ extern "C" ProError PopupMsg(const char *title, const char *msg) { @@ -522,7 +703,51 @@ PopupMsg(const char *title, const char *msg) } -/* modify RGB values to achieve minimum luminance threshold */ +/* Utilize regular expression match for Creo parameter name */ +extern "C" ProError +regex_key(ProParameter *param, ProError UNUSED(status), ProAppData app_data) +{ + char pname[CREO_NAME_MAX]; + char val[CREO_NAME_MAX]; + wchar_t wval[CREO_NAME_MAX]; + + regex_t reg; + + ProParamvalue pval; + ProParamvalueType ptype; + ProUnititem punits; + + struct pparam_data *pdata = (struct pparam_data *)app_data; + if (pdata->val) + return PRO_TK_NO_ERROR; + + ProWstringToString(pname, param->id); + (void)regcomp(®, pdata->key, REG_NOSUB|REG_EXTENDED); + if (!(regexec(®, pname, 0, NULL, 0))) { + regfree(®); + return PRO_TK_CONTINUE; + } + regfree(®); + + if (ProParameterValueWithUnitsGet(param, &pval, &punits) != PRO_TK_NO_ERROR) + return PRO_TK_CONTINUE; + + if (ProParamvalueTypeGet(&pval, &ptype) != PRO_TK_NO_ERROR) + return PRO_TK_CONTINUE; + + if (ptype == PRO_PARAM_STRING) { + if (ProParamvalueValueGet(&pval, ptype, wval) != PRO_TK_NO_ERROR) + return PRO_TK_CONTINUE; + ProWstringToString(val, wval); + if (strlen(val) > 0) + pdata->val = bu_strdup(val); + } + + return PRO_TK_NO_ERROR; +} + + +/* Modify RGB values to achieve minimum luminance threshold */ extern "C" int rgb4lmin(fastf_t *rgb, int lmin) { @@ -541,13 +766,15 @@ rgb4lmin(fastf_t *rgb, int lmin) if (UNLIKELY(!rgb)) /* bad input? */ return -1; - rp = std::min(std::max(lrint(rgb[0]*255.0),(long int)0),(long int)255); /* control input range */ + /* Restrict input range for: rgb, lmin */ + rp = std::min(std::max(lrint(rgb[0]*255.0),(long int)0),(long int)255); gp = std::min(std::max(lrint(rgb[1]*255.0),(long int)0),(long int)255); bp = std::min(std::max(lrint(rgb[2]*255.0),(long int)0),(long int)255); lp = std::min(std::max(lmin,0),100); cmax = std::max(std::max(rp,gp),bp); cmin = std::min(std::min(rp,gp),bp); + del = cmax-cmin; lum = (cmax+cmin)/510.0; @@ -594,7 +821,8 @@ rgb4lmin(fastf_t *rgb, int lmin) rf = cp; gf = 0.0; bf = xp; } - rgb[0] = std::min(std::max((rf + mp),0.0),1.0); /* control output range */ + /* Restrict rgb output range */ + rgb[0] = std::min(std::max((rf + mp),0.0),1.0); rgb[1] = std::min(std::max((gf + mp),0.0),1.0); rgb[2] = std::min(std::max((bf + mp),0.0),1.0); @@ -602,7 +830,28 @@ rgb4lmin(fastf_t *rgb, int lmin) } -/* Map a given string to the "stable" version of that string generated by objects_gather */ +/* Removes unwanted characters from a variable-length string */ +extern "C" void +scrub_vls(struct bu_vls *vls) +{ + struct bu_vls tmp_str = BU_VLS_INIT_ZERO; + + const char *keep_chars = "+-.=_"; + const char *collapse_chars = "_"; + + if (bu_vls_strlen(vls) > 0) { + bu_vls_sprintf(&tmp_str, "%s", bu_vls_cstr(vls)); + bu_vls_trimspace(&tmp_str); + bu_vls_simplify(&tmp_str, keep_chars, collapse_chars, collapse_chars); + bu_vls_sprintf(vls, "%s", bu_vls_addr(&tmp_str)); + } + + bu_vls_free(&tmp_str); + return; +} + + +/* Map a string to the "stable" version found in parts/assems */ extern "C" wchar_t * stable_wchar(struct creo_conv_info *cinfo, wchar_t *wc) { @@ -618,7 +867,7 @@ stable_wchar(struct creo_conv_info *cinfo, wchar_t *wc) } -/* left-shift string to suppress leading and trailing whitespace */ +/* Purge string of leading and trailing whitespace */ extern "C" void trim(char *str) { @@ -649,36 +898,40 @@ trim(char *str) } +/* Convert wide string to double precision value */ extern "C" double wstr_to_double(struct creo_conv_info *cinfo, wchar_t *tmp_str) { - double ret; + double ret = 0.0; char *endptr = NULL; char astr[CREO_MSG_MAX]; + ProWstringToString(astr, tmp_str); - errno = 0; + ret = strtod(astr, &endptr); if (endptr != NULL && strlen(endptr) > 0) { /* Had some invalid character in the input, fail */ - creo_log(cinfo, MSG_PLAIN, "ERROR: Invalid string \"%s\" specified for type double\n", astr); + creo_log(cinfo, MSG_PLAIN, " STRING: Invalid data \"%s\" specified for type double\n", astr); return -1.0; } return ret; } +/* Convert wide string to long int value */ extern "C" long int wstr_to_long(struct creo_conv_info *cinfo, wchar_t *tmp_str) { - long int ret; + long int ret = 0; char *endptr = NULL; char astr[CREO_MSG_MAX]; + ProWstringToString(astr, tmp_str); - errno = 0; + ret = strtol(astr, &endptr, 0); if (endptr != NULL && strlen(endptr) > 0) { /* Had some invalid character in the input, fail */ - creo_log(cinfo, MSG_PLAIN, "ERROR: Invalid string \"%s\" specified for integer type\n", astr); + creo_log(cinfo, MSG_PLAIN, " STRING: Invalid data \"%s\" specified for integer type\n", astr); return -1; } return ret;