Home > User Guide > Model Import
Sample Code to Demonstrate How to Execute Healing Workflow
This section contains snippets of C++ code to illustrate how to execute healing workflow. These snippets are designed to be very simple starting points for developing your own code - they are not complete, compiling, and runtime programs.
The code snippet demonstrates the following:
- Tolerant stitch of bodies by calling api_stitch
- Geometry simplification of bodies by calling api_simplify_entity
- Tightening gaps in the bodies to the user's desired tightness value by calling api_tighten_gaps
Sample Code
// ************************************************************
// Sample customer function to execute Healing Workflow.
//
// Input:
// Input to this function is ENTITY_LIST bodies_imported_into_ACIS which
// should be a list of non-wire bodies translated into ACIS from external
// file formats. This list should only contain BODYs.
//
// Output:
// The function will return back the output bodies in ENTITY_LIST output_bodies
// which will belong to the caller. The entities inside
// bodies_imported_into_ACIS may be invalid after this function.
// ************************************************************
void user_function_for_healing_workflow(ENTITY_LIST& bodies_imported_into_ACIS,
ENTITY_LIST& output_bodies)
{
// **************************************************************
// Step 1 : Tolerant Stitching
// (call api_stitch with tolerant_stitch_options)
// **************************************************************
if (/* stitching is needed*/)
{
// Create a default tolerant_stitch_options object.
tolerant_stitch_options sopts;
// Set the stitcher coincident face identification routine
// to SPASTITCH_COIN_SKIP to skip stitching coincident faces.
STITCH_COIN_MODES mode = SPASTITCH_COIN_SKIP;
sopts.set_stch_coincident_face_handling_mode(mode);
// Determine and set max-stitch-tol for stitching.
const double max_stitch_tol = user_function_to_determine_max_stitch_tol();
sopts.set_max_stitch_tol(max_stitch_tol);
// Call User's function to stitch list of entities
user_function_to_stitch_entities(bodies_imported_into_ACIS, output_bodies, sopts);
}
else
{
output_bodies = bodies_imported_into_ACIS;
}
// **************************************************************
// Step 2 : Simplification
// (call api_simplify_entity)
// **************************************************************
// Determine the desired gap tightness ("desired_gap_tightness")
// of the user's downstream application (like manufacturing).
const double desired_gap_tightness = user_function_to_determine_desired_gap_tightness();
if (/* simplification is needed*/)
{
// A user may want to simplify each stitched BODY in the "output_bodies" list.
// Create default simplify_options object. A default simplify_options object
// will do both curve and surface simplification based on the default value of
// simplification tolerance(SPAresabs).
simplify_options simp_opts;
// Choose a simplification tolerance. If the user desires the gaps in the model
// to be within a certain value, then that value could be the best value
// to use as simplification tolerance. So user may want to use the desired
// gap tightness as simplification tolerance. Set the simplification tolerance
// equal to the desired_gap_tightness value of the downstream application.
simp_opts.set_simplification_tol(desired_gap_tightness);
// Call User's function to simplify each stitched body
ENTITY* entity_to_simplify = NULL;
output_bodies.init();
while (NULL != (entity_to_simplify = output_bodies.next()))
{
user_function_to_simplify_entity(entity_to_simplify, simp_opts);
}
}
// **************************************************************
// Step 3 : Tighten Gaps to desired tightness
// (call api_tighten_gaps)
// **************************************************************
if (/* gap tightening is needed*/)
{
// A user may want to tighten gaps in each of the stitched and simplified
// BODY so that the gaps in TEDGEs and TVERTEXs in
// the BODYs are within a "desired_gap_tightness" of the user's downstream
// application (like manufacturing).
BODY* body = NULL;
output_bodies.init();
while (NULL != (body = (BODY *)output_bodies.next()))
{
user_function_to_tighten_gaps_in_body(body, desired_gap_tightness);
}
}
}
// ************************************************************
// User function to get max-stitch-tol
// ************************************************************
double user_function_to_determine_max_stitch_tol(/*const ENTITY_LIST& to_be_stitched*/)
{
// Initialize max_stitch_tol to -1.0
double max_stitch_tol = -1.0;
// A user is recommended to set max-stitch-tol such that it is
// bigger than the size of expected maximum gap between incoming faces.
// Further it should be smaller than the minimum feature size in the model.
// This is important because api_stitch might remove edges smaller than
// the supplied max-stitch-tol.
return max_stitch_tol;
}
// ************************************************************
// User function to stitch a list of entities
// ************************************************************
void user_function_to_stitch_entities(
ENTITY_LIST& to_be_stitched,
ENTITY_LIST& output_bodies,
tolerant_stitch_options& sopts)
{
// ENTITY_LIST& new_bodies will contain all the new bodies resulting
// from the API api_stitch. This list will be a subset of
// ENTITY_LIST& output_bodies. This list is provided so that it is
// convenient to the caller to find out the new bodies that the caller
// will have to take ownership of (for example, the users may have to register
// new bodies in their application and/or do memory management for those bodies).
ENTITY_LIST new_bodies;
// Make the careful option OFF to enable failsafe behavior.
// Note: By default the "careful" option is already OFF
option_header *careful_opt = find_option("careful");
if (NULL != careful_opt)
{
careful_opt->push(FALSE);
}
// Note: To disable the failsafe behavior, set the "careful" option ON (push TRUE)
// Make a call to api_stitch to stitch the entities in "to be stitched" list
outcome result_stch = api_stitch(to_be_stitched,
output_bodies,
new_bodies,
&sopts);
// Restore the original value of careful_opt
if (NULL != careful_opt)
{
careful_opt->pop();
}
// Check and handle fatal problems reported by api_stitch
// User code to handle failure and exit.
if ( TRUE == user_function_to_handle_fatal_problem_reported_by_outcome(result_stch) )
{
// User code to handle failure and exit
...
return;
}
// Handle all new bodies returned by api_stitch
BODY *new_body = NULL;
new_bodies.init();
while (NULL != (new_body = (BODY *)new_bodies.next()))
{
// User code to handle new bodies created by api_stitch. For example,
// the user may want to register new bodies into their application.
...
}
// User may want to know of the non fatal problems the API encoutered,
// and take corrective actions if any, before before proceeding to the next step.
user_function_to_handle_problems_reported_by_outcome(result_stch);
// Pointer to an array of ENTITY_LIST pointers to store the coincident face
// cluster lists to allow list processing.
ENTITY_LIST* coin_face_list = NULL;
// Get the number of coincident faces clusters
int num_clusters = sopts.get_number_of_coincident_face_clusters();
// Check if coincident faces were detected
if ( num_clusters > 0 )
{
// Allocate memory based on the size of coincident face cluster list
coin_face_list = ACIS_NEW ENTITY_LIST[num_clusters];
// Now to go in a loop to collect each coincident face cluster
ENTITY_LIST* cluster = NULL;
int cluster_index = 0;
sopts.init_coincident_face_cluster_list();
while (NULL != (cluster = sopts.get_next_coincident_face_cluster()))
{
// deep copy list
coin_face_list[cluster_index] = *cluster;
cluster_index ++;
}
// Process each cluster (as an example, just print the size of each cluster).
// In practice, customers will probably want to exit to a handling routine
// which deletes items from the to_be_stitched list and recall api_stitch
// again. The user may need to keep retrying this step until no coincident
// faces are detected anymore.
int i=0;
for (i = 0; i < num_clusters; i++)
{
int num_faces = coin_face_list[i].count();
printf("Number of faces in cluster %d = %d", i, num_faces);
}
// Delete the coincident faces cluster list.
if ( coin_face_list != NULL )
{
ACIS_DELETE [] coin_face_list;
coin_face_list = NULL;
}
} // end braces for "num_clusters > 0"
}
// ************************************************************
// User function to get max-stitch-tol
// ************************************************************
double user_function_to_determine_desired_gap_tightness()
{
// Initialize to -1.0;
double desired_gap_tightness = -1.0;
// Determine the desired gap tightness
// ("desired_gap_tightness") of the user's downstream
// application (like manufacturing).
return desired_gap_tightness;
}
// ************************************************************
// User function to simplify an ENTITY
// ************************************************************
void user_function_to_simplify_entity(ENTITY*& entity_to_simplify,
simplify_options& simp_opts)
{
// Make the careful option OFF to enable failsafe behavior.
// Note: By default the "careful" option is already OFF
option_header *careful_opt = find_option("careful");
if (NULL != careful_opt)
{
careful_opt->push(FALSE);
}
// Call api_simplify_entity to simplify body.
outcome result_of_simplify = api_simplify_entity(
entity_to_simplify,
&simp_opts);
// Restore the original value of careful_opt
if (NULL != careful_opt)
{
careful_opt->pop();
}
// Check and handle fatal problems reported by api_simplify_entity
// User code to handle failure and exit.
if ( TRUE == user_function_to_handle_fatal_problem_reported_by_outcome(result_of_simplify) )
{
// User code to handle failure and exit
...
return;
}
// User may want to know of the non fatal problems the
// api encoutered, and take corrective actions if any,
// before before proceeding to the next step.
user_function_to_handle_problems_reported_by_outcome(result_of_simplify);
return;
}
// ************************************************************
// User function to tighten gaps in BODY
// ************************************************************
void user_function_to_tighten_gaps_in_body(BODY*& body,
const double& desired_gap_tightness)
{
// Make the careful option OFF to enable failsafe behavior.
// Note: By default the "careful" option is already OFF
option_header *careful_opt = find_option("careful");
if (NULL != careful_opt)
{
careful_opt->push(FALSE);
}
// Call api_tighten_gaps on body with desired_gap_tightness.
outcome result_of_gap_tightening = api_tighten_gaps(
body,
desired_gap_tightness);
// Restore the original value of careful_opt
if (NULL != careful_opt)
{
careful_opt->pop();
}
// Check and handle fatal problems reported by api_tighten_gaps
// User code to handle failure and exit.
if ( TRUE == user_function_to_handle_fatal_problem_reported_by_outcome(result_of_gap_tightening) )
{
// User code to handle failure and exit
...
return;
}
// User may want to know of the non fatal problems the
// api encoutered, and take corrective actions if any,
// before before proceeding to the next step.
user_function_to_handle_problems_reported_by_outcome(result_of_gap_tightening);
return;
}
logical user_function_to_handle_fatal_problem_reported_by_outcome(const outcome& api_outcome)
{
logical fatal = FALSE;
// Handle fatal errors of api
if ( !api_outcome.ok() )
{
// User may want to know about the fatal error due to
// which the API failed
error_info* einf = api_outcome.get_error_info();
// User code to report information on errors. A sample
// function "display_problems_encountered" for such
// reporting is given at the bottom of the code
// snippet
display_problems_encountered(einf);
// Reasons for error
if (einf->has_reasons())
{
// User code to mention that the following are
// reasons for the error, the user may print it as
// printf("Following are the reasons for the error:\n");
// error_info_list owns all the error_info
// objects inside it and cleans them up on
// destruction. User need not worry about memory
// cleanup of the error_info objects.
error_info_list reasons_eil;
einf->reasons(reasons_eil);
const error_info* reason_einf = NULL;
for (reasons_eil.init(); NULL != (reason_einf =
reasons_eil.next());)
{
display_problems_encountered(reason_einf);
}
}
fatal = TRUE;
}
return fatal;
}
void user_function_to_handle_problems_reported_by_outcome(const outcome& api_outcome)
{
if ( api_outcome.ok() )
{
// Problem reporting by API.
// API succeeded (either partially or fully) if this point
// is reached
error_info_list eil;
api_outcome.get_error_info_list(eil);
const error_info* einf = NULL;
for (eil.init(); NULL != (einf = eil.next());)
{
// User code to report information on problems. A
// sample function "display_problems_encountered" for
// such reporting is given at the bottom of the code
// snippet.
display_problems_encountered(einf);
// Reasons for the problem
if (einf->has_reasons())
{
// User code to mention that the following are
// reasons for the problem, the user may print it as
printf("Following are the reasons for the error:\n");
// error_info_list owns all the error_info
// objects inside it and cleans them up on
// destruction. User need not worry about memory
// cleanup of the error_info objects.
error_info_list reasons_eil;
einf->reasons(reasons_eil);
const error_info* reason_einf = NULL;
for (reasons_eil.init(); NULL != (reason_einf =
reasons_eil.next());)
{
display_problems_encountered(reason_einf);
}
}
}
}
}
// ************************************************************
// User function to report information on problems
// ************************************************************
void display_problems_encountered(const error_info *einf)
{
if ( NULL == einf )
{ return; }
char const *err_message = einf->error_message();
spa_outcome_severity_type err_severity = einf->severity();
// User code to display message and severity
// for example, the user might do the following
printf("Problem encountered: %s\n", err_message);
if (SPA_OUTCOME_FATAL == err_severity)
// Represents a fatal error
{ printf("Severity: FATAL \n"); }
else if (SPA_OUTCOME_ERROR == err_severity)
// Represents an error encountered by a failsafe routine
// during an atomic operation
{ printf("Severity: ERROR \n"); }
else if (SPA_OUTCOME_PROBLEM == err_severity)
// Represents a problem encountered during an operation
{ printf("Severity: PROBLEM \n"); }
else if (SPA_OUTCOME_INSANITY == err_severity)
// Represents an insanity in the model
{ printf("Severity: INSANITY \n"); }
int ent_id_cnt = get_error_info_entity_id_count(einf);
// If ent_id_cnt returns positive count,
// then einf has atleast one entity, dead or live
if ( 0 < ent_id_cnt && einf->type() == entity_error_info::id() )
{
const entity_error_info* ent_einf = (const entity_error_info *)einf;
if ( 0 ) /* the user wants to report problems on dead entities too ) */
// LIVE and DEAD entities
{
for (int i = 0; i < ent_id_cnt; i++)
{
tag_id_type ent_id = ent_einf->get_entity_id(i);
ENTITY *err_entity = NULL;
outcome res_get_ent = api_get_entity_from_id(ent_id, err_entity);
if ( !res_get_ent.ok() )
{
// Handle API failure and continue or exit as caller thinks suitable
...
}
if (NULL != err_entity) // err_entity is LIVE
{
// User code to report a live entity associated with a problem,
// for example the user may want to highlight the entity
}
else
{
// Report problem for a dead entity
}
}
}
else // Only LIVE entities
{
ENTITY_LIST live_entities;
ent_einf->get_entities_alive(live_entities);
ENTITY *live_err_entity = NULL;
for (live_entities.init(); NULL != (live_err_entity = live_entities.next()); )
{
// User code to report a live entity associated with a problem,
// for example the user may want to highlight the entity
}
}
}
}
}[Top]
© 1989-2007 Spatial Corp., a Dassault Systèmes company. All rights reserved.