/***************************************************************************** udo_occ_sample_udo.c ========================================================================= Copyright (c) 2004 UGS PLM Solutions and EDS Company Unpublished - All rights reserved ========================================================================= File Description Contains Unigraphics entry points for registering the UDO Occ Sample Class and the UDO Non Occ Sample Class used by udo_occ_sample_application.c Please see the uf_udobj chapter of the Open API Reference Guide for a detailed description of this example. *** PLEASE NOTE *** The shared library created from this program should be placed in the udo directory specified by the UGII_SITE_DIR or the UGII_USER_DIR environment variable. *****************************************************************************/ /* Include files */ #include #include #include #include #include #include #include #include #include #include #include /* The class id's for associating UDO's with two perpendicular/adjacent edges */ static unsigned int UDO_occ_sample_class; static unsigned int UDO_non_occ_sample_class; /* structure used to hold the data that defines the placement of the circle */ typedef struct edge_data_s{ tag_t horiz_edge; /* linear edge selected by the user */ double horiz_point1[3]; /* end point of the horiz_edge, this should be the same point as vert_point1*/ double horiz_point2[3]; /* other end point of the horiz_edge */ tag_t vert_edge; /* linear edge selected by the user, must be adjacent and perpendicular to the horiz_edge */ double vert_point1[3]; /* end point of the vert_edge, this should be the same point as horiz_point1 */ double vert_point2[3]; /* other end point of the vert_edge */ }edge_data_t,*edge_data_p_t; /* UF_CALL is the standard User Function error handling mechanism that is recommended to anyone calling a user function. */ #define UF_CALL(X)(report_error( __FILE__, __LINE__, #X, (X))) /* report_error works in conjunction with the UF_CALL macro */ static int report_error( char *file, int line, char *call, int irc ) { if(irc) { char err[133], msg[133]; sprintf( msg, "*** ERROR code %d at line %d in %s:\n+++", irc, line, file ); UF_get_fail_message( irc, err ); UF_print_syslog( msg, FALSE ); UF_print_syslog( err, FALSE ); UF_print_syslog( "\n", FALSE ); UF_print_syslog( call, FALSE ); UF_print_syslog( ";\n", FALSE ); if( !UF_UI_open_listing_window() ) { UF_UI_write_listing_window( msg ); UF_UI_write_listing_window( err ); UF_UI_write_listing_window( "\n" ); UF_UI_write_listing_window( call ); UF_UI_write_listing_window( ";\n" ); } } return( irc ); } /**************************************************************************** * create_sample_classes * * DESCRIPTION * Creates the occurenceable and nonoccurrenceable sample classes, * and registers the callback functions for display, selection, update, * info, delete, and is_occurenceable. * ****************************************************************************/ static void create_sample_classes( void ); /******************************************************************** * is_occurrenceable_func * * DESCRIPTION * Given the tag of a UDO determine if it should be occurrenceable. * * INPUT * udo_tag * Tag of the UDO to determine occurrenceablity of. * * OUPUT * is_occurrenceable * TRUE - The UDO will be displayed in an assembly. * FALSE - The UDO will only be displayed in an assembly if * the UDO was created in the current displayed part. ********************************************************************/ static void is_occurrenceable_func( tag_t udo_tag, logical *is_occurrenceable ); /******************************************************************** * update_sample_cb * * DESCRIPTION * Given the tag of a UDO and the link that caused the UDO to * go through update, define what it means to update this UDO. * * This function is called when one of the edges linked to * a UDO go through update. * * INPUT * udo_tag * Tag of the UDO to update * link * The link containing the edge that has just gone through update. * * OUPUT * The UDO is updated if necessary. ********************************************************************/ static void update_sample_cb( tag_t udo_tag, UF_UDOBJ_link_p_t link ); /******************************************************************** * display_sample_cb * * DESCRIPTION * The display callback makes calls to the display primitives * which are used for attention point, fit, display, and selection. * Therefore this same callback can be used in place of all * 4 callbacks. * * This UDO is displayed as a circle centered on the rectangle * defined by two linear, adjacent, and parpendicular edges. * The center point of the circle is also displayed. * * Assume you have a face that looks like the following: * * V E * e d * r g +-----------------------. * t e | / * i | | / * c '->| / * a +-------------------+ * l ^ * /|\ * Horizontal Edge--' * * To construct the center of the circle, construct a line from * the midpoint of the horizontal edge that runs parallel to the * vertical edge. Next construct a line through the midpoint of * the vertical edge that runs parallel to the horizontal edge. * The center of the circle is defined by the intersection of * the two lines. The diameter of the circle is the length * of the shorter edge. In this example the diameter is the * length of the vertical edge. * * midpoint line 1 * V E : * e d : * r g +--------.-.------------. * t e | / : \ / * i | +.....|...+...|......./....... midpoint line 2 * c '->| \ : / / * a +--------'-'--------+ * l : ^ * /|\ * Horizontal Edge--' * * * The finished UDO should look like: * * V E * e d * r g +--------.-.------------. * t e | / \ / * i | | | + | / * c '->| \ / / * a +--------'-'--------+ * l ^ * /|\ * Horizontal Edge--' * * INPUT * udo_tag * Tag of the udo to display. * context * Used as input for display primitive functions. * ********************************************************************/ static void display_sample_cb( tag_t udo_tag, void *context ); /******************************************************************** * info_sample_cb * * DESCRIPTION * This function is called interactively when selecting * Information->Object from the UG Menubar and then selecting a * UDO. * * This function displays the following information to the * UI Listing window (Text shown in []'s are replaced by real values * in the actual listing window): * * UDO Sample [Tag of UDO] is defined by edge [Tag of H.Edge] and edge [Tag of V.Edge] * The radius is [Radisu] and the origin in absolute coordinates is ([X-Coord], [Y-Coord], [Z-Coord]) * The circle transform matrix is: * ([X1], [Y1], [Z1]) * ([X2], [Y2], [Z2]) * ([X3], [Y3], [Z3]) * The circle origin in circle space coordinates is ([X-Coord], [Y-Coord], [Z-Coord]) * * INPUT * udo_tag * Tag of UDO you wish to inquire. This tag is used to get * the linked edges, which in turn is used to generate the * rest of the data. ********************************************************************/ static void info_sample_cb( tag_t udo_tag ); /******************************************************************** * find_arc_csys_and_origin * * DESCRIPTION * Find the csys matrix, origin, and radius that define a circle * centered on the rectangle defined by two * linear/adjacent/perpendicular edges. * * INPUT * edge_data * horiz_edge * The tag of the horizontal linear edge * horiz_point1 * The common endpoint between the horizontal * and vertical edges. * horiz_point2 * The other horizontal endpoint. * vert_edge * The tag of the vertical linear edge * vert_point1 * The common endpoint between the horizontal * and vertical edges. * vert_point2 * The other vertical endpoint. * * OUTPUT * matrix * Matrix that defines the coordinate system of the circle. * origin * The center of the circle in absolute coordinates. * radius * The radius of the circle. ********************************************************************/ static void find_arc_csys_and_origin( edge_data_p_t edge_data, double matrix[9], double origin[3], double *radius ); /******************************************************************** * find_common_point * * DESCRIPTION * Given the edge data, check to see if the two edges have a * common endpoint. If the two edges have a common * endpoint, return TRUE and set horiz_point1 and vert_point1 * to the common endpoint. Set horiz_point2 to the other * endpoint of the horizontal edge, and vert_point2 to the * other endpoint of the vertical edge. * * INPUT * data * horiz_edge * The horizontal linear edge. * horiz_point1 * One of the endpoints of the horizontal edge. * horiz_point2 * The other endpoint of the horizontal edge. * vert_edge * The potential adjacent linear edge to the horizontal edge. * vert_point1 * One of the endpoints of the vertical edge. * vert_point2 * The other endpoint of the vertical edge. * * OUTPUT * data * horiz_edge * The horizontal linear edge. * horiz_point1 * The common endpoint, if one exists, of the horizontal * and vertical edges, otherwise this is unchanged. * horiz_point2 * The other endpoint of the horizontal edge. * vert_edge * The potential adjacent linear edge to the horizontal edge. * vert_point1 * The common endpoint, if one exists, of the horizontal * and vertical edges, otherwise this is unchanged. * vert_point2 * The other endpoint of the vertical edge. * * RETURNS * TRUE - There was a common endpoint. * FALSE - The edges do not have a common endpoint. ********************************************************************/ static logical find_common_point( edge_data_p_t data ); /******************************************************************** * swap_edge_data_points * * DESCRIPTION * Given the edge data, if swap_horiz_pts is true, swap * the two horizontal points, and if swap_vert_pts is true, * swap the two vertical points. * * INPUT * data * horiz_edge * The horizontal linear edge. * horiz_point1 * One of the endpoints of the horizontal edge. * horiz_point2 * The other endpoint of the horizontal edge. * vert_edge * The vertical linear edge. * vert_point1 * One of the endpoints of the vertical edge. * vert_point2 * The other endpoint of the vertical edge. * * OUTPUT * data * horiz_edge * The horizontal linear edge. * horiz_point1 * If swap_horiz_pts was true, then (input)horiz_point2 * otherwise this variable is unchanged. * horiz_point2 * If swap_horiz_pts was true, then (input)horiz_point1 * otherwise this variable is unchanged. * vert_edge * The vertical linear edge. * vert_point1 * If swap_vert_pts was true, then (input)horiz_point2 * otherwise this variable is unchanged. * vert_point2 * If swap_vert_pts was true, then (input)horiz_point1 * otherwise this variable is unchanged. * ********************************************************************/ static void swap_edge_data_points( edge_data_p_t data, logical swap_horiz_pts, logical swap_vert_pts ); /***************************************************************************** ** Activation Methods *****************************************************************************/ /* Unigraphics Startup ** This entry point activates the application at Unigraphics startup */ extern DllExport void ufsta( char *param, int *returnCode, int rlen ) { /* Initialize the API environment */ UF_CALL( UF_initialize() ); UDO_occ_sample_class = 0; UDO_non_occ_sample_class = 0; create_sample_classes(); UF_CALL( UF_terminate() ); } /**************************************************************************** * create_sample_class * * DESCRIPTION * Creates the sample class, and registers the callback functions for * display, selection, update, info and delete. * ****************************************************************************/ static void create_sample_classes( void ) { /* create a UDO class */ if( !UF_CALL( UF_UDOBJ_create_class( "udo_occ_sample", "UDO Occ Sample", &UDO_occ_sample_class) )); { /* Register the display callbacks */ UF_CALL( UF_UDOBJ_register_attn_pt_cb( UDO_occ_sample_class, display_sample_cb ) ); UF_CALL( UF_UDOBJ_register_fit_cb( UDO_occ_sample_class, display_sample_cb ) ); UF_CALL( UF_UDOBJ_register_display_cb( UDO_occ_sample_class, display_sample_cb ) ); /* Make the class selectable */ UF_CALL( UF_UI_add_to_class_sel( UDO_occ_sample_class ) ); UF_CALL( UF_UDOBJ_set_query_class_id( UDO_occ_sample_class, UF_UDOBJ_ALLOW_QUERY_CLASS_ID ) ); /* Register the selection callback */ UF_CALL( UF_UDOBJ_register_select_cb( UDO_occ_sample_class, display_sample_cb ) ); /* Register the update callback */ UF_CALL( UF_UDOBJ_register_update_cb( UDO_occ_sample_class, update_sample_cb) ); /* Register the info callback */ UF_CALL( UF_UDOBJ_register_info_obj_cb( UDO_occ_sample_class, info_sample_cb) ); UF_CALL( UF_UDOBJ_register_is_occurrenceable_cb ( UDO_occ_sample_class, is_occurrenceable_func )); } if( !UF_CALL( UF_UDOBJ_create_class( "udo_non_occ_sample", "UDO Non-Occ Sample", &UDO_non_occ_sample_class) )); { /* Register the display callbacks */ UF_CALL( UF_UDOBJ_register_attn_pt_cb( UDO_non_occ_sample_class, display_sample_cb ) ); UF_CALL( UF_UDOBJ_register_fit_cb( UDO_non_occ_sample_class, display_sample_cb ) ); UF_CALL( UF_UDOBJ_register_display_cb( UDO_non_occ_sample_class, display_sample_cb ) ); /* Make the class selectable */ UF_CALL( UF_UI_add_to_class_sel( UDO_non_occ_sample_class ) ); UF_CALL( UF_UDOBJ_set_query_class_id( UDO_non_occ_sample_class, UF_UDOBJ_ALLOW_QUERY_CLASS_ID ) ); /* Register the selection callback */ UF_CALL( UF_UDOBJ_register_select_cb( UDO_non_occ_sample_class, display_sample_cb ) ); /* Register the update callback */ UF_CALL( UF_UDOBJ_register_update_cb( UDO_non_occ_sample_class, update_sample_cb) ); /* Register the info callback */ UF_CALL( UF_UDOBJ_register_info_obj_cb( UDO_non_occ_sample_class, info_sample_cb) ); /* to make a class non-occurrenceable, you can register an is_occurrenceable_cb that always returns false, or you can register a NULL function as the is_occurrenceable_cb, or you can avoid registering the is_occurrenceable_cb altogether */ UF_CALL( UF_UDOBJ_register_is_occurrenceable_cb ( UDO_non_occ_sample_class, NULL )); } } /******************************************************************** * is_occurrenceable_func * * DESCRIPTION * Given the tag of a UDO determine if it should be occurrenceable. * * INPUT * udo_tag * Tag of the UDO to determine occurrenceablity of. * * OUPUT * is_occurrenceable * TRUE - The UDO will be displayed in an assembly. * FALSE - The UDO will only be displayed in an assembly if * the UDO was created in the current displayed part. ********************************************************************/ static void is_occurrenceable_func( tag_t udo_tag, logical *is_occurrenceable ) { *is_occurrenceable = TRUE; } /******************************************************************** * update_sample_cb * * DESCRIPTION * Given the tag of a UDO and the link that caused the UDO to * go through update, define what it means to update this UDO. * * This function is called when one of the edges linked to * a UDO go through update. * * INPUT * udo_tag * Tag of the UDO to update * link * The link containing the edge that has just gone through update. * * OUPUT * The UDO is updated if necessary. ********************************************************************/ static void update_sample_cb( tag_t udo_tag, UF_UDOBJ_link_p_t link ) { tag_t assoc_tag = NULL_TAG; /* If the link is null, there is nothing to do */ if( link == NULL) { return; } UF_CALL( UF_initialize() ); assoc_tag = link->assoc_ug_tag; /* Make sure that the associated tag still exists */ if( assoc_tag == NULL_TAG ) { UF_CALL( UF_terminate() ); return; } /* Make sure that the associated tag is still alive */ if( UF_OBJ_ask_status( assoc_tag ) != UF_OBJ_ALIVE ) { /* The object is no longer alive, this can happen when an edge is blended away, the edge still exists, but is not an active part of the model */ UF_CALL( UF_terminate() ); return; } /* Redisplay the item with the updated edge */ UF_CALL( UF_DISP_add_item_to_display( udo_tag )); UF_CALL( UF_terminate() ); } /******************************************************************** * display_sample_cb * * DESCRIPTION * The display callback makes calls to the display primitives * which are used for attention point, fit, display, and selection. * Therefore this same callback can be used in place of all * 4 callbacks. * * This UDO is displayed as a circle centered on the rectangle * defined by two linear, adjacent, and parpendicular edges. * The center point of the circle is also displayed. * * Assume you have a face that looks like the following: * * V E * e d * r g +-----------------------. * t e | / * i | | / * c '->| / * a +-------------------+ * l ^ * /|\ * Horizontal Edge--' * * To construct the center of the circle, construct a line from * the midpoint of the horizontal edge that runs parallel to the * vertical edge. Next construct a line through the midpoint of * the vertical edge that runs parallel to the horizontal edge. * The center of the circle is defined by the intersection of * the two lines. The diameter of the circle is the length * of the shorter edge. In this example the diameter is the * length of the vertical edge. * * midpoint line 1 * V E : * e d : * r g +--------.-.------------. * t e | / : \ / * i | +.....|...+...|......./....... midpoint line 2 * c '->| \ : / / * a +--------'-'--------+ * l : ^ * /|\ * Horizontal Edge--' * * * The finished UDO should look like: * * V E * e d * r g +--------.-.------------. * t e | / \ / * i | | | + | / * c '->| \ / / * a +--------'-'--------+ * l ^ * /|\ * Horizontal Edge--' * * INPUT * udo_tag * Tag of the udo to display. * context * Used as input for display primitive functions. * ********************************************************************/ static void display_sample_cb( tag_t udo_tag, void *context ) { UF_UDOBJ_all_data_t all_data; edge_data_t edge_data; tag_t edge_1 = NULL_TAG; tag_t edge_2 = NULL_TAG; int vertex_count = 0; double origin[3] = {0.0, 0.0, 0.0}; double matrix[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; double radius = 0.0; char *class_name = NULL; UF_CALL( UF_initialize() ); /* find the data that defines this udo */ UF_CALL( UF_UDOBJ_ask_udo_data ( udo_tag, &all_data ) ); /* note that the links are returned in random order, but for this example, the order of the two edges is irrelevant. */ edge_data.horiz_edge = all_data.link_defs[0].assoc_ug_tag; edge_data.vert_edge = all_data.link_defs[1].assoc_ug_tag; /* If either edge is not alive, do not display this udo */ if( (UF_OBJ_ask_status( edge_data.horiz_edge ) != UF_OBJ_ALIVE) || (UF_OBJ_ask_status( edge_data.vert_edge ) != UF_OBJ_ALIVE)) { UF_CALL( UF_terminate() ); return; } /* fill in the edge_data structure */ UF_CALL( UF_MODL_ask_edge_verts( edge_data.horiz_edge, edge_data.horiz_point1, edge_data.horiz_point2, &vertex_count ) ); UF_CALL( UF_MODL_ask_edge_verts( edge_data.vert_edge, edge_data.vert_point1, edge_data.vert_point2, &vertex_count ) ); find_common_point( &edge_data ); /* find the csys matrix, origin and radius that define the circle */ find_arc_csys_and_origin( &edge_data, matrix, origin, &radius); /* display a point at the origin of the circle in absolute coordinates */ UF_CALL( UF_DISP_display_points( origin, 1, UF_DISP_POINT, context )); /* display text next to the point that tells the user the class name of this udo */ UF_CALL( UF_UDOBJ_ask_udo_class_name( udo_tag, &class_name ) ); UF_CALL( UF_DISP_display_text( class_name, origin, UF_DISP_TOPLEFT, context ) ); UF_free( class_name ); /* find the origin of the circle in terms of the arc space defined by matrix */ UF_MTX3_vec_multiply( origin, matrix, origin ); /* display a circle centered with respect to the two edges */ UF_CALL( UF_DISP_display_circle( matrix, origin, radius, FALSE, context )); /* free the udo data */ UF_CALL( UF_UDOBJ_free_udo_data( &all_data ) ); UF_CALL( UF_terminate() ); } /******************************************************************** * info_sample_cb * * DESCRIPTION * This function is called interactively when selecting * Information->Object from the UG Menubar and then selecting a * UDO. * * This function displays the following information to the * UI Listing window (Text shown in []'s are replaced by real values * in the actual listing window): * * UDO Sample [Tag of UDO] is defined by edge [Tag of H.Edge] and edge [Tag of V.Edge] * The radius is [Radisu] and the origin in absolute coordinates is ([X-Coord], [Y-Coord], [Z-Coord]) * The circle transform matrix is: * ([X1], [Y1], [Z1]) * ([X2], [Y2], [Z2]) * ([X3], [Y3], [Z3]) * The circle origin in circle space coordinates is ([X-Coord], [Y-Coord], [Z-Coord]) * * INPUT * udo_tag * Tag of UDO you wish to inquire. This tag is used to get * the linked edges, which in turn is used to generate the * rest of the data. ********************************************************************/ static void info_sample_cb( tag_t udo_tag ) { UF_UDOBJ_all_data_t all_data; edge_data_t edge_data; logical alive = TRUE; tag_t edge_1 = NULL_TAG; tag_t edge_2 = NULL_TAG; int vertex_count = 0; double origin[3] = {0.0, 0.0, 0.0}; double matrix[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; double radius = 0.0; char info_msg[133]; UF_CALL( UF_initialize() ); if( !UF_UI_open_listing_window() ) { UF_CALL( UF_UDOBJ_ask_udo_data ( udo_tag, &all_data ) ); /* note that the links are returned in random order, but for this example, the two edges are interchangeable. */ edge_data.horiz_edge = all_data.link_defs[0].assoc_ug_tag; edge_data.vert_edge = all_data.link_defs[1].assoc_ug_tag; /* output the tags of the edges */ sprintf( info_msg, "UDO Sample %u is defined by edge %u and edge %u\n", udo_tag, edge_data.horiz_edge, edge_data.vert_edge ); UF_UI_write_listing_window( info_msg ); /* If either, or both, edges are not alive, inform the user */ if( UF_OBJ_ask_status( edge_data.horiz_edge ) != UF_OBJ_ALIVE ) { alive = FALSE; sprintf( info_msg, "The edge %u is not alive, therefore this UDO is not displayed.\n", edge_data.horiz_edge ); UF_UI_write_listing_window( info_msg ); } if( UF_OBJ_ask_status( edge_data.vert_edge ) != UF_OBJ_ALIVE ) { alive = FALSE; sprintf( info_msg, "The edge %u is not alive, therefore this UDO is not displayed.\n", edge_data.vert_edge ); UF_UI_write_listing_window( info_msg ); } /* if an edge is not alive, you can't ask for its endpoints, so we should return */ if( alive == FALSE ) { UF_CALL( UF_terminate() ); return; } /* fill in the edge data structure */ UF_CALL( UF_MODL_ask_edge_verts( edge_data.horiz_edge, edge_data.horiz_point1, edge_data.horiz_point2, &vertex_count ) ); UF_CALL( UF_MODL_ask_edge_verts( edge_data.vert_edge, edge_data.vert_point1, edge_data.vert_point2, &vertex_count ) ); find_common_point( &edge_data ); /* find the csys matrix, origin and radius that define the circle */ find_arc_csys_and_origin( &edge_data, matrix, origin, &radius); /* output the radius and origin of the circle */ sprintf( info_msg, "The radius is %lf and the origin in absolute coordinates is (%lf, %lf, %lf)\n", radius, origin[0], origin[1], origin[2] ); UF_UI_write_listing_window( info_msg ); /* output the matrix that defined the csys of the circle */ sprintf( info_msg, "The circle transform matrix is:\n" ); UF_UI_write_listing_window( info_msg ); sprintf( info_msg, "(%lf, %lf, %lf)\n", matrix[0], matrix[3], matrix[6] ); UF_UI_write_listing_window( info_msg ); sprintf( info_msg, "(%lf, %lf, %lf)\n", matrix[1], matrix[4], matrix[7] ); UF_UI_write_listing_window( info_msg ); sprintf( info_msg, "(%lf, %lf, %lf)\n", matrix[2], matrix[5], matrix[8] ); UF_UI_write_listing_window( info_msg ); /* find the origin of the circle in terms of the arc space defined by matrix */ UF_MTX3_vec_multiply( origin, matrix, origin ); /* output the origin of the circle in circle space coordinates */ sprintf( info_msg, "The circle origin in circle space cooridnates is(%lf, %lf, %lf)\n", origin[0], origin[1], origin[2] ); UF_UI_write_listing_window( info_msg ); /* free the UDO data */ UF_CALL( UF_UDOBJ_free_udo_data( &all_data ) ); } UF_CALL( UF_terminate() ); } /******************************************************************** * find_arc_csys_and_origin * * DESCRIPTION * Find the csys matrix, origin, and radius that define a circle * centered on the rectangle defined by two * linear/adjacent/perpendicular edges. * * INPUT * edge_data * horiz_edge * The tag of the horizontal linear edge * horiz_point1 * The common endpoint between the horizontal * and vertical edges. * horiz_point2 * The other horizontal endpoint. * vert_edge * The tag of the vertical linear edge * vert_point1 * The common endpoint between the horizontal * and vertical edges. * vert_point2 * The other vertical endpoint. * * OUTPUT * matrix * Matrix that defines the coordinate system of the circle. * origin * The center of the circle in absolute coordinates. * radius * The radius of the circle. ********************************************************************/ static void find_arc_csys_and_origin( edge_data_p_t edge_data, double matrix[9], double origin[3], double *radius ) { double diagonal_vec[3] = {0.0, 0.0, 0.0}; double x_vec[3] = {0.0, 0.0, 0.0}; double y_vec[3] = {0.0, 0.0, 0.0}; double x_length = 0.0; double y_length = 0.0; /* Assume you have a face that looks like the following: vert_point2 \ *-----------------------. | / | / | / *-------------------+ / | \ / | horiz_point2 horiz_point1 & vert_point1 Find the diagonal vector from vert_point2 to horiz_point2, then find the midpoint(M) of the line by scaling the vector by 50% and adding the scaled vector to vert_point2. The midpoint defines the origin of the circle vert_point2 \ *-----------------------. | ` . / | ` M. / | ` . / *-------------------+ / | \ / | horiz_point2 horiz_point1 & vert_point1 */ UF_VEC3_sub( edge_data->horiz_point2, edge_data->vert_point2, diagonal_vec ); UF_VEC3_scale( .5, diagonal_vec, diagonal_vec ); UF_VEC3_add( edge_data->vert_point2, diagonal_vec, origin ); /* Find the x and y vectors for the circle csys, and then get the csys matrix ^ Y-Vector /|\ | *-----------------------. | ` . / | ` M. / | ` . / *-------------------+-----> X-Vector */ UF_VEC3_sub( edge_data->horiz_point2, edge_data->horiz_point1, x_vec ); UF_VEC3_sub( edge_data->vert_point2, edge_data->vert_point1, y_vec ); UF_CALL( UF_MTX3_initialize( x_vec, y_vec, matrix ) ); /* set the raidus to half the length of the shortest edge */ UF_VEC3_mag( x_vec, &x_length ); UF_VEC3_mag( y_vec, &y_length ); if( x_length < y_length ) { *radius = x_length/2; } else { *radius = y_length/2; } } /******************************************************************** * find_common_point * * DESCRIPTION * Given the edge data, check to see if the two edges have a * common endpoint. If the two edges have a common * endpoint, return TRUE and set horiz_point1 and vert_point1 * to the common endpoint. Set horiz_point2 to the other * endpoint of the horizontal edge, and vert_point2 to the * other endpoint of the vertical edge. * * INPUT * data * horiz_edge * The horizontal linear edge. * horiz_point1 * One of the endpoints of the horizontal edge. * horiz_point2 * The other endpoint of the horizontal edge. * vert_edge * The potential adjacent linear edge to the horizontal edge. * vert_point1 * One of the endpoints of the vertical edge. * vert_point2 * The other endpoint of the vertical edge. * * OUTPUT * data * horiz_edge * The horizontal linear edge. * horiz_point1 * The common endpoint, if one exists, of the horizontal * and vertical edges, otherwise this is unchanged. * horiz_point2 * The other endpoint of the horizontal edge. * vert_edge * The potential adjacent linear edge to the horizontal edge. * vert_point1 * The common endpoint, if one exists, of the horizontal * and vertical edges, otherwise this is unchanged. * vert_point2 * The other endpoint of the vertical edge. * * RETURNS * TRUE - There was a common endpoint. * FALSE - The edges do not have a common endpoint. ********************************************************************/ static logical find_common_point( edge_data_p_t data ) { double tol = 0.00001; double distance = 0.0; /* check the distance between the the first horizontal endpoint and the first vertical endpoint. */ UF_VEC3_distance( data->horiz_point1, data->vert_point1, &distance ); if( distance > tol ) { /* now check the distance between the first horizontal endpoint and the second vertical endpoint */ UF_VEC3_distance( data->horiz_point1, data->vert_point2, &distance ); if( distance <= tol ) { /* If the first horizontal point is equal to the second vertical point, swap the two vertical endpoints. */ swap_edge_data_points( data, FALSE, TRUE ); } } if( distance > tol ) { /* now check the distance between the second horizontal endpoint and the first vertical endpoint */ UF_VEC3_distance( data->horiz_point2, data->vert_point1, &distance ); if( distance <= tol ) { /* If the first horizontal point is equal to the second vertical point, swap the two horizontal endpoints. */ swap_edge_data_points( data, TRUE, FALSE ); } } if( distance > tol ) { /* now check the distance between the second horizontal endpoint and the second vertical endpoint */ UF_VEC3_distance( data->horiz_point2, data->vert_point2, &distance ); if( distance <= tol ) { /* If the second horizontal point is equal to the second vertical point, swap the two horizontal endpoints and swap the two vertical endpoints. */ swap_edge_data_points( data, TRUE, TRUE ); } } if( distance <= tol ) { /* a common endpoint was found */ return( TRUE ); } /* there were no common endpoints */ return( FALSE ); } /******************************************************************** * swap_edge_data_points * * DESCRIPTION * Given the edge data, if swap_horiz_pts is true, swap * the two horizontal points, and if swap_vert_pts is true, * swap the two vertical points. * * INPUT * data * horiz_edge * The horizontal linear edge. * horiz_point1 * One of the endpoints of the horizontal edge. * horiz_point2 * The other endpoint of the horizontal edge. * vert_edge * The vertical linear edge. * vert_point1 * One of the endpoints of the vertical edge. * vert_point2 * The other endpoint of the vertical edge. * * OUTPUT * data * horiz_edge * The horizontal linear edge. * horiz_point1 * If swap_horiz_pts was true, then (input)horiz_point2 * otherwise this variable is unchanged. * horiz_point2 * If swap_horiz_pts was true, then (input)horiz_point1 * otherwise this variable is unchanged. * vert_edge * The vertical linear edge. * vert_point1 * If swap_vert_pts was true, then (input)horiz_point2 * otherwise this variable is unchanged. * vert_point2 * If swap_vert_pts was true, then (input)horiz_point1 * otherwise this variable is unchanged. * ********************************************************************/ static void swap_edge_data_points( edge_data_p_t data, logical swap_horiz_pts, logical swap_vert_pts ) { double temp_point[3] = {0.0, 0.0, 0.0}; if( swap_horiz_pts ) { temp_point[0] = data->horiz_point1[0]; temp_point[1] = data->horiz_point1[1]; temp_point[2] = data->horiz_point1[2]; data->horiz_point1[0] = data->horiz_point2[0]; data->horiz_point1[1] = data->horiz_point2[1]; data->horiz_point1[2] = data->horiz_point2[2]; data->horiz_point2[0] = temp_point[0]; data->horiz_point2[1] = temp_point[1]; data->horiz_point2[2] = temp_point[2]; } if( swap_vert_pts ) { temp_point[0] = data->vert_point1[0]; temp_point[1] = data->vert_point1[1]; temp_point[2] = data->vert_point1[2]; data->vert_point1[0] = data->vert_point2[0]; data->vert_point1[1] = data->vert_point2[1]; data->vert_point1[2] = data->vert_point2[2]; data->vert_point2[0] = temp_point[0]; data->vert_point2[1] = temp_point[1]; data->vert_point2[2] = temp_point[2]; } } /***************************************************************************** ** Utilities *****************************************************************************/ /* Unload Handler ** This function specifies when to unload your application from Unigraphics. ** If your application registers a callback (from a MenuScript item or a ** User Defined Object for example), this function MUST return ** "UF_UNLOAD_UG_TERMINATE". */ extern int ufusr_ask_unload( void ) { return( UF_UNLOAD_UG_TERMINATE ); }