/* Copyright (c) 2024 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved. */ /*--------------------------------------------------------------------*\ Pro/Toolkit includes \*--------------------------------------------------------------------*/ #include <ProToolkit.h> #include <ProMdl.h> #include <ProMenuBar.h> #include <ProArray.h> #include <ProObjects.h> #include <ProSurfacedata.h> #include <ProSurface.h> #include <ProAxis.h> #include <ProDtmAxis.h> #include <ProElemId.h> #include <ProValue.h> #include <ProElement.h> #include <ProFeature.h> #include <ProFeatType.h> #include <ProFeatType.h> #include <ProSelection.h> #include <ProElempath.h> #include <ProAsmcomp.h> #include <ProGroup.h> #include <math.h> #include <ProTKRunTime.h> #include <ProSolidBody.h> typedef struct auto_srf_data { ProSurface rev_srf; int axis_id; double diameter; } Auto_srf_data; typedef struct auto_axis_pnts { Pro3dPnt p1; Pro3dPnt p2; } Axis_p12; typedef struct auto_srfs_data { int total_srfs; int num_rev_srfs; Auto_srf_data *srfs_array; int num_axes; Axis_p12 *axes_pnts; int axes_created; ProMdl owner; } Auto_srfs_data; /* Signals that a representative axis was already found for this "hole" */ #define AXIS_ALT_FOUND -5 /*--------------------------------------------------------------------*\ PROTOTYPES OF LOCAL FUNCTIONS \*--------------------------------------------------------------------*/ ProError AutoaxisMain( ProMdl imported_model ); ProError AutoaxisCollectAxes ( ProAxis axis, ProError status, ProAppData app_data ); ProError AutoaxisCollectRevSurfaces ( ProSurface p_surface, ProError status, ProAppData app_data ); ProError AutoaxisSurfaceFilter( ProSurface p_surface, ProAppData app_data ); ProError AutoaxisElementAdd( ProElemId id, ProElement *parent, ProValueData *elem_data, ProElement *elem ); ProError AutoaxisSurfaceAxisCreate( Auto_srfs_data *srfs, ProSurface surface, int* axis_id); ProError AutoaxisSurfaceCheckAxis( ProSurface p_surface, Axis_p12 *p12 ); ProError AutoaxisGeomVisitAction ( ProGeomitem *p_geomitem, ProError err, ProAppData app_data) ; ProError AutoaxisCheckAxis( ProSurface surface , Auto_srfs_data *srfs ); /*--------------------------------------------------------------------*\ USER INTRFACE \*--------------------------------------------------------------------*/ static uiCmdAccessState TestAccessDefault(uiCmdAccessMode access_mode) { return (ACCESS_AVAILABLE); } /*====================================================================*\ FUNCTION : user_initialize() PURPOSE : \*====================================================================*/ int user_initialize( int argc, char *argv[], char *version, char *build, wchar_t errbuf[80]) { uiCmdCmdId cmd_id; ProError status; int RunAutoAxis( ); status = ProCmdActionAdd("AutoAxis", (uiCmdCmdActFn)RunAutoAxis, uiProe2ndImmediate, TestAccessDefault, PRO_B_TRUE, PRO_B_TRUE, &cmd_id); status = ProMenubarmenuPushbuttonAdd( "Applications", "AutoAxis", "AutoAxis", "Creates axes in the model", NULL, PRO_B_FALSE, cmd_id, L"usrmsg.txt"); return (0); } /*====================================================================*\ FUNCTION : user_terminate() PURPOSE : To handle any termination actions \*====================================================================*/ void user_terminate() { } int RunAutoAxis( ) { ProMdl cur_mdl; ProError status; status = ProMdlCurrentGet( &cur_mdl); if ( status == PRO_TK_NO_ERROR ) { status = AutoaxisMain(cur_mdl); } return 0; } /*--------------------------------------------------------------------*\ -------------------------------------------------------------------- FUNCTION DEFINITIONS -------------------------------------------------------------------- \*--------------------------------------------------------------------*/ /*====================================================*\ Function : AutoaxisSurfaceCheckAxis() Purpose : To check if any axis exists which can be related to given surface. \*====================================================*/ ProError AutoaxisSurfaceCheckAxis( ProSurface p_surface, Axis_p12 *p12) { ProError status; ProGeomitemdata *gitem_data; ProSrftype srftype; ProUvParam uv_min, uv_max; ProSurfaceOrient s_orient; ProSurfaceshapedata s_shapedata; ProVector e1, e2, e3; Pro3dPnt origin; ProCurvedata cur1; double rad1, alpha; int s_id; double epsilan; double a,b,c; double x01,y01,z01; double det1,det2,det3; double cp,dist,abc; ProVector a_v; ProError axis_stat; if ( p_surface == NULL || p12 == NULL ) return PRO_TK_BAD_INPUTS; gitem_data = NULL; epsilan = 0.00000001; /* Value is enough ? */ axis_stat = PRO_TK_E_NOT_FOUND; status = ProSurfaceDataGet(p_surface, &gitem_data); if ( status == PRO_TK_NO_ERROR ) { status = ProSurfacedataGet( gitem_data->data.p_surface_data, &srftype, uv_min, uv_max, &s_orient, &s_shapedata, &s_id); if ( status == PRO_TK_NO_ERROR ) { switch(srftype) { case PRO_SRF_CYL: status = ProCylinderdataGet( &s_shapedata, e1, e2, e3, origin, &rad1); break; case PRO_SRF_CONE: status = ProConedataGet( &s_shapedata, e1, e2, e3, origin, &alpha); break; case PRO_SRF_REV: status = ProSrfrevdataGet( &s_shapedata, e1, e2, e3, origin, &cur1); break; default : ProTKPrintf("Not a Rev. Type surface..\n"); } } } if ( status == PRO_TK_NO_ERROR ) { /* To find collinearity between exsting axis with axis to be created using the given surface. 1. Data available from axis ( p1,p2 ) 2. Data available from surface Origin(x0,y0,z0) and Vectors(X,Y,Z) Assumption is made that the axis will be always coincident/parallel with Z vector of the surface. In this scenario, the condition for being parallel and coincident vectors, a) Cross product must be zero, ( Axis x Z = 0 ) b) The distance between the Axis and O(origin) of the surface must be zero If above two conditions are true, no axis will be created because one already exists. */ /* Axis from p1,p2 */ /* In vector form (a,b,c) */ a = p12->p1[0] - p12->p2[0] ; b = p12->p1[1] - p12->p2[1] ; c = p12->p1[2] - p12->p2[2] ; abc = sqrt ( a*a + b*b + c*c ); /* Unit vector along axis */ a_v[0] = a/abc ; a_v[1] = b/abc ; a_v[2] = c/abc ; /* Cross Product ( Axis x Z_vec ) */ cp = a_v[1]*e3[2] - a_v[2]*e3[1] ; cp += a_v[2]*e3[0] - a_v[0]*e3[2] ; cp += a_v[0]*e3[1] - a_v[1]*e3[0] ; if ( cp <= epsilan ) { /* Distance between origin an Axis */ x01 = origin[0] - p12->p1[0] ; y01 = origin[1] - p12->p1[1] ; z01 = origin[2] - p12->p1[2] ; det1 = c*y01 - b*z01 ; det2 = a*z01 - c*x01 ; det3 = b*x01 - a*y01 ; /* Actual formula for Shortest Distace to a line( Localized vector) from a point. dist = sqrt (( det1*det1 + det2*det2 + det3*det3 ) / ( a*a + b*b + c*c ) ) ; But denominator can be ignored . */ dist = det1*det1 + det2*det2 + det3*det3 ; if ( dist <= epsilan ) { axis_stat = PRO_TK_E_FOUND; } else { axis_stat = PRO_TK_E_NOT_FOUND; } } } if( gitem_data != NULL ) { ProGeomitemdataFree( &gitem_data ); } return axis_stat; } /*====================================================*\ Function : AutoaxisSurfaceIsHole() Purpose : Determine if the surface is likely a part of a "hole" that needs an axis. \*====================================================*/ ProBoolean AutoaxisSurfaceIsHole (ProSolid solid, ProSurface surface) { ProError status; ProSurface* same_surfs; int n_same_surfs; /*-----------------------------------------------------*\ Determine if the surface has a matching surface (typically the other half of a split cylinder or cone). \*-----------------------------------------------------*/ ProArrayAlloc (0, sizeof (ProSurface), 1, (ProArray*)&same_surfs); status = ProSurfaceSameSrfsFind (solid, surface, &same_surfs, &n_same_surfs); ProArrayFree ((ProArray*)&same_surfs); if (status == PRO_TK_NO_ERROR && n_same_surfs > 1) return PRO_B_TRUE; else return PRO_B_FALSE; } /*====================================================*\ Function : AutoaxisSurfaceFilter() Purpose : Filter function for ProSolidSurfaceVisit \*====================================================*/ ProError AutoaxisSurfaceFilter( ProSurface p_surface, ProAppData app_data ) { ProSrftype surface_type; ProError status; Auto_srfs_data *data; ProFeattype ftype; ProFeature feature; ProGeomitem geom; int s_id; status = PRO_TK_NO_ERROR; data = (Auto_srfs_data *)app_data; data->total_srfs++; status = ProSurfaceIdGet ( p_surface, &s_id ); if(status == PRO_TK_NO_ERROR) { geom.id = s_id; geom.owner = data->owner; geom.type = PRO_SURFACE; } if(status == PRO_TK_NO_ERROR) status = ProSurfaceTypeGet ( p_surface, &surface_type); if ( status == PRO_TK_NO_ERROR && ( surface_type == PRO_SRF_CYL || surface_type == PRO_SRF_CONE || surface_type == PRO_SRF_REV ) && AutoaxisSurfaceIsHole (data->owner, p_surface) ) { return PRO_TK_NO_ERROR ; } return PRO_TK_CONTINUE; } /*====================================================*\ Function : AutoaxisAddSortedSurface() Purpose : Add the given surface to the surface array, in a position sorted by diameter (largest to smallest). Non-cylindrical surfaces are added to the end of the array. \*====================================================*/ ProError AutoaxisAddSortedSurface (Auto_srfs_data* data, Auto_srf_data* srf) { int num_srfs = data->num_rev_srfs; int i; ProSurface current_srf; ProSrftype surface_type; double current_diam = 0.0; ProError status; ProUvParam param = {0.0, 0.0}; status = ProSurfaceTypeGet ( srf->rev_srf, &surface_type); if (surface_type == PRO_SRF_CYL) { ProSurfaceDiameterEval (srf->rev_srf, param, &srf->diameter); } else srf->diameter = -1.0; if (num_srfs == 0) { ProArrayObjectAdd ((ProArray*)&data->srfs_array, PRO_VALUE_UNUSED, 1, srf); data->num_rev_srfs++; } else { for (i = 0; i < num_srfs; i++) { current_srf = data->srfs_array[i].rev_srf; current_diam = data->srfs_array[i].diameter; /* If its bigger than this surface, add it to the array just before */ if (srf->diameter > current_diam) { ProArrayObjectAdd ((ProArray*)&data->srfs_array, i, 1, srf); data->num_rev_srfs++; break; } /* If its smaller than all other surfaces, add it to the end of the array */ if (i == num_srfs - 1) { ProArrayObjectAdd ((ProArray*)&data->srfs_array, PRO_VALUE_UNUSED, 1, srf); data->num_rev_srfs++; } } } return PRO_TK_NO_ERROR; } /*====================================================*\ Function : AutoaxisCollectRevSurfaces() Purpose : Action function for ProSolidSurfaceVisit Collects revolved surfaces \*====================================================*/ ProError AutoaxisCollectRevSurfaces ( ProSurface p_surface, ProError status, ProAppData app_data ) { ProError err; int srf_id; Auto_srf_data srf; Auto_srfs_data *data; data = (Auto_srfs_data *)app_data; if ( status == PRO_TK_NO_ERROR ) { err = PRO_TK_NO_ERROR ; srf_id = 0; err = ProSurfaceIdGet ( p_surface, &srf_id); if ( err == PRO_TK_NO_ERROR ) { srf.axis_id = PRO_VALUE_UNUSED ; err = ProSurfaceInit ( data->owner, srf_id, &srf.rev_srf); if ( err == PRO_TK_NO_ERROR ) { err = AutoaxisAddSortedSurface (data, &srf); } } } return status; } /*====================================================*\ Function : AutoaxisCollectBodyRevSurfaces() Purpose : Action function for ProSolidBodySurfaceVisit Collects revolved surfaces on body \*====================================================*/ ProError AutoaxisCollectBodyRevSurfaces ( ProSurface p_surface, ProError status, ProAppData app_data ) { if ( PRO_TK_NO_ERROR == AutoaxisSurfaceFilter(p_surface, app_data) ) status = AutoaxisCollectRevSurfaces (p_surface, status, app_data); return status; } /*====================================================*\ Function : AutoaxisCollectQuiltSurfaces() Purpose : Action function for ProSolidQuiltVisit Collects the rev surfaces in the model. \*====================================================*/ ProError AutoaxisCollectQuiltSurfaces ( ProQuilt p_quilt, ProError status, ProAppData app_data ) { ProError err; if ( status == PRO_TK_NO_ERROR ) { err = ProQuiltSurfaceVisit( p_quilt,AutoaxisCollectRevSurfaces, AutoaxisSurfaceFilter,app_data ); } return err; } /*====================================================*\ Function : AutoaxisCollectAxes() Purpose : Action function for ProSolidAxisVisit Collects the axes in the model. \*====================================================*/ ProError AutoaxisCollectAxes ( ProAxis axis, ProError status, ProAppData app_data ) { ProError err; Auto_srfs_data *data; Axis_p12 pnts; ProGeomitemdata *a_gitem_data; a_gitem_data = NULL; data = ( Auto_srfs_data * ) app_data; err = ProAxisDataGet(axis, &a_gitem_data); if ( err == PRO_TK_NO_ERROR && a_gitem_data != NULL ) { err = ProLinedataGet( a_gitem_data->data.p_curve_data, pnts.p1, pnts.p2); } if ( err == PRO_TK_NO_ERROR ) { err = ProArrayObjectAdd ((ProArray*)&data->axes_pnts, PRO_VALUE_UNUSED, 1, &pnts); if ( err == PRO_TK_NO_ERROR ) { data->num_axes++; } } if( a_gitem_data != NULL ) { ProGeomitemdataFree( &a_gitem_data ); } return status; } /*====================================================*\ Function : AutoaxisElementAdd() Purpose : Adds elem to parent \*====================================================*/ ProError AutoaxisElementAdd( ProElemId id, ProElement *parent, ProValueData *elem_data, ProElement *elem ) { ProValue value ; ProError status = PRO_TK_NOT_VALID ; if ( elem_data == NULL || elem == NULL || parent == NULL ) return PRO_TK_BAD_INPUTS ; status = ProElementAlloc(id, elem) ; if ( status != PRO_TK_NO_ERROR ) return status; status = ProValueAlloc (&value) ; if ( status == PRO_TK_NO_ERROR ) status = ProValueDataSet (value, elem_data) ; if ( status == PRO_TK_NO_ERROR ) status = ProElementValueSet (*elem, value) ; if ( elem_data != NULL && status != PRO_TK_NO_ERROR ) return status; status = ProElemtreeElementAdd( *parent, NULL, *elem ) ; return status; } /*====================================================*\ Function : AutoaxisGeomVisitAction() Purpose : Collects end points of an axis \*====================================================*/ ProError AutoaxisGeomVisitAction ( ProGeomitem *p_geomitem, ProError err, ProAppData app_data) { ProError status; Auto_srfs_data *data; Axis_p12 pnts; ProGeomitemdata *a_gitem_data; ProAxis axis; if ( app_data == NULL ) return PRO_TK_BAD_INPUTS; status = PRO_TK_NO_ERROR; a_gitem_data = NULL; data = (Auto_srfs_data*) app_data; if ( status == PRO_TK_NO_ERROR ) status = ProGeomitemToAxis(p_geomitem, &axis); if ( status == PRO_TK_NO_ERROR ) status = ProAxisDataGet(axis, &a_gitem_data); if ( status == PRO_TK_NO_ERROR && a_gitem_data != NULL ) { status = ProLinedataGet( a_gitem_data->data.p_curve_data, pnts.p1, pnts.p2); } if ( status == PRO_TK_NO_ERROR ) { status = ProArrayObjectAdd ((ProArray*)&data->axes_pnts, PRO_VALUE_UNUSED, 1, &pnts); if ( status == PRO_TK_NO_ERROR ) { data->axes_created++ ; } } if( a_gitem_data != NULL ) { ProGeomitemdataFree( &a_gitem_data ); } return err; } /*====================================================*\ Function : AutoaxisSurfaceAxisCreate() Purpose : Creates axis for given revolve surface \*====================================================*/ ProError AutoaxisSurfaceAxisCreate( Auto_srfs_data *srfs, ProSurface surface, int* axis_id) { ProValueData value_data; ProElement root_tree, feat_type; ProElement cnstrnts, cnstrnt; ProElement cnstrnt_type, cnstrnt_ref; ProElemId elemid; ProError status; ProFeature feature; ProFeatureCreateOptions opts[1]; ProModelitem modelitem; ProSelection mdl_sel; ProErrorlist errors; ProGeomitem rev_srf; ProSelection rev_srf_sel; int srf_id; ProMdl model; if ( srfs == NULL || surface == NULL ) return PRO_TK_BAD_INPUTS; status = PRO_TK_NO_ERROR; srf_id = -1; mdl_sel = NULL; rev_srf_sel = NULL; root_tree = NULL; model = srfs->owner ; status = ProSurfaceIdGet (surface, &srf_id); if ( status == PRO_TK_NO_ERROR && srf_id ) { rev_srf.owner = model ; rev_srf.id = srf_id ; rev_srf.type = PRO_SURFACE ; status = ProSelectionAlloc(NULL, &rev_srf, &rev_srf_sel); if ( status != PRO_TK_NO_ERROR ) return status; } /*---------------------------------------------------------------------------*\ Prepare element tree for Axis Feature \*---------------------------------------------------------------------------*/ status = ProElementAlloc(PRO_E_FEATURE_TREE, &root_tree); elemid = PRO_E_FEATURE_TYPE ; value_data.type = PRO_VALUE_TYPE_INT; value_data.v.i = PRO_FEAT_DATUM_AXIS ; status = AutoaxisElementAdd(elemid, &root_tree,&value_data, &feat_type); elemid = PRO_E_DTMAXIS_CONSTRAINTS ; status = ProElementAlloc(elemid, &cnstrnts ); status = ProElemtreeElementAdd(root_tree, NULL, cnstrnts ); elemid = PRO_E_DTMAXIS_CONSTRAINT ; status = ProElementAlloc(elemid, &cnstrnt ); status = ProElemtreeElementAdd(cnstrnts, NULL, cnstrnt ); elemid = PRO_E_DTMAXIS_CONSTR_TYPE ; value_data.type = PRO_VALUE_TYPE_INT; value_data.v.i = PRO_DTMAXIS_CONSTR_TYPE_THRU ; status = AutoaxisElementAdd(elemid, &cnstrnt,&value_data, &cnstrnt_type); if ( rev_srf_sel != NULL ) { elemid = PRO_E_DTMAXIS_CONSTR_REF ; value_data.type = PRO_VALUE_TYPE_SELECTION; value_data.v.r = rev_srf_sel ; status = AutoaxisElementAdd(elemid, &cnstrnt,&value_data, &cnstrnt_ref); } status = ProMdlToModelitem(model, &modelitem); if ( status == PRO_TK_NO_ERROR ) status = ProSelectionAlloc(NULL, &modelitem, &mdl_sel); opts[0] = PRO_FEAT_CR_NO_OPTS; if ( status == PRO_TK_NO_ERROR ) { status = ProFeatureCreate(mdl_sel, root_tree, opts, 1, &feature, &errors); } if ( status == PRO_TK_NO_ERROR ) { *axis_id = feature.id; /* Collect the axis end points. This is to avoid visiting it again while creating another axis. */ ProFeatureGeomitemVisit( &feature, PRO_AXIS, AutoaxisGeomVisitAction, NULL,(ProAppData)srfs); } if( rev_srf_sel != NULL ) ProSelectionFree(&rev_srf_sel); if( rev_srf_sel != NULL ) ProSelectionFree(&mdl_sel); if( root_tree != NULL ) ProElementFree( &root_tree); return status; } /*====================================================*\ Function : AutoaxisCheckAxis() Purpose : Checks existance of any axis related to given surface \*====================================================*/ ProError AutoaxisCheckAxis( ProSurface surface, Auto_srfs_data *srfs ) { ProError status; int i,total_axes; if ( surface == NULL || srfs == NULL ) return PRO_TK_BAD_INPUTS; status = PRO_TK_E_NOT_FOUND ; total_axes = srfs->num_axes + srfs->axes_created ; for ( i = 0 ; i < total_axes ; i++ ) { status = AutoaxisSurfaceCheckAxis ( surface, &srfs->axes_pnts[i] ); if ( status == PRO_TK_E_FOUND ) return status; } return PRO_TK_E_NOT_FOUND; } /*====================================================*\ Function : AutoaxisAxesCreate() Purpose : Creates axes for revolve surfaces \*====================================================*/ ProError AutoaxisAxesCreate( Auto_srfs_data *surfaces) { ProError status; int j, axis_id = PRO_VALUE_UNUSED; for ( j = 0; j < surfaces->num_rev_srfs ; j++ ) { if( surfaces->srfs_array[j].axis_id != PRO_VALUE_UNUSED && surfaces->srfs_array[j].axis_id != AXIS_ALT_FOUND) continue; /* Any axis exists ? */ status = AutoaxisCheckAxis ( surfaces->srfs_array[j].rev_srf, surfaces ); if ( status == PRO_TK_E_FOUND ) { surfaces->srfs_array[j].axis_id = AXIS_ALT_FOUND; continue; } status = AutoaxisSurfaceAxisCreate( surfaces, surfaces->srfs_array[j].rev_srf, &axis_id); if ( status == PRO_TK_NO_ERROR ) { surfaces->srfs_array[j].axis_id = axis_id; } } return status; } /*====================================================*\ Function : AutoaxisAsmComponent() Purpose : Action function for components This is to run AutoAxis on Asm Comps. \*====================================================*/ ProError AutoaxisAsmComponent ( ProFeature *p_feature, ProError status, ProAppData app_data ) { ProMdl p_mdl; status = ProAsmcompMdlGet ((ProAsmcomp *)p_feature, &p_mdl); if ( status == PRO_TK_NO_ERROR ) status = AutoaxisMain(p_mdl); return status; } /*====================================================*\ Function : AutoaxisAsmcompFilter() Purpose : Filter function for components \*====================================================*/ ProError AutoaxisAsmcompFilter ( ProFeature* p_feature, ProAppData app_data ) { ProError status; ProFeattype ftype; ProMdl p_mdl; ProMdlType p_type; status = ProFeatureTypeGet(p_feature, &ftype); if ( status == PRO_TK_NO_ERROR && ftype == PRO_FEAT_COMPONENT) { status = ProAsmcompMdlGet ((ProAsmcomp *)p_feature, &p_mdl); if ( status == PRO_TK_NO_ERROR ) { status = ProMdlTypeGet (p_mdl, &p_type); if ( status == PRO_TK_NO_ERROR ) { if (p_type == PRO_MDL_ASSEMBLY || p_type == PRO_MDL_PART) { return(PRO_TK_NO_ERROR); } } } } return PRO_TK_CONTINUE; } /*====================================================*\ Function : AutoaxisGroupCreate Purpose : Create group of axes that go to matching diameter holes. \*====================================================*/ ProError AutoaxisGroupCreate (ProSolid owner, double target_diameter, int* feat_ids) { int num_feats; ProCharName name_buff; ProName name; ProGroup group; ProArraySizeGet (feat_ids, &num_feats); if (target_diameter > 0.0) { ProTKSprintf (name_buff, "AXES_DIAM_%.1lf", target_diameter); ProStringToWstring (name, name_buff); } else { ProTKSprintf (name_buff, "AXES_NOT_CYLINDRICAL"); ProStringToWstring (name, name_buff); } ProLocalGroupCreate (owner, feat_ids, num_feats, name, &group); return (PRO_TK_NO_ERROR); } #define D_EPS 0.1 /*====================================================*\ Function : AutoaxisAxesGroup Purpose : Group axes by diameter. \*====================================================*/ ProError AutoaxisAxesGroup ( Auto_srfs_data* data ) { int i, num_feats, current_id; int num_srfs = data->num_rev_srfs; int* feat_ids = NULL; double target_diameter = -1.0; double current_diameter; for (i = 0; i < num_srfs; i++) { current_diameter = data->srfs_array [i].diameter; current_id = data->srfs_array[i].axis_id; /* For the first surface found */ if (feat_ids == NULL) { target_diameter = current_diameter; /* if (target_diameter > 0.0) */ if (current_id > 0) { ProArrayAlloc (1, sizeof (int), 1, (ProArray*)&feat_ids); feat_ids [0] = current_id; } } else { /* If there's a true axis assigned to this surface */ if (current_id > 0) { /* If the diameter matches the target, add it and continue */ if (fabs (current_diameter - target_diameter) < D_EPS) { ProArrayObjectAdd ((ProArray*)&feat_ids, PRO_VALUE_UNUSED, 1, ¤t_id); } /* Otherwise, process the set of axes in the current group, and start collecting a new one */ else if (i != num_srfs -1) { AutoaxisGroupCreate (data->owner, target_diameter, feat_ids); ProArrayFree ((ProArray*)&feat_ids); target_diameter = current_diameter; ProArrayAlloc (1, sizeof (int), 1, (ProArray*)&feat_ids); feat_ids [0] = current_id; } } /* Finish the last group for the last surface */ if (i == num_srfs - 1) { AutoaxisGroupCreate (data->owner, target_diameter, feat_ids); ProArrayFree ((ProArray*)&feat_ids); } } } return PRO_TK_NO_ERROR; } #undef D_EPS /*====================================================*\ Function : AutoaxisMain() Purpose : Top level function to create Axes for Revolved surfaces \*====================================================*/ ProError AutoaxisMain( ProMdl imported_model ) { ProError status; Auto_srfs_data surfaces; ProMdlType mdl_type; ProSolidBody* bodies = NULL; int i = 0, body_num = 0; status = PRO_TK_NO_ERROR; status = ProMdlTypeGet ( imported_model, &mdl_type); if ( status != PRO_TK_NO_ERROR || (mdl_type != PRO_MDL_PART && mdl_type != PRO_MDL_ASSEMBLY && mdl_type != PRO_MDL_MFG) ) return PRO_TK_BAD_INPUTS; if ( status == PRO_TK_NO_ERROR ) { if ( mdl_type != PRO_MDL_PART ) { /* In case of assemblies visit all components recursively */ status = ProSolidFeatVisit (( ProSolid )imported_model, AutoaxisAsmComponent, AutoaxisAsmcompFilter, NULL ) ; } } surfaces.total_srfs = 0 ; surfaces.num_rev_srfs = 0 ; surfaces.srfs_array = NULL ; surfaces.num_axes = 0 ; surfaces.axes_pnts = NULL ; surfaces.axes_created = 0 ; surfaces.owner = imported_model ; /* Collect all Axes(End points) in the Model */ status = ProArrayAlloc (0, sizeof (Axis_p12), 1, (ProArray*)&surfaces.axes_pnts); if ( status == PRO_TK_NO_ERROR ) { status = ProSolidAxisVisit( (ProSolid) imported_model, AutoaxisCollectAxes, NULL, ( ProAppData ) &surfaces ); } /* Collect all revolve type surfaces in the Model */ status = ProArrayAlloc (0, sizeof (Auto_srf_data), 1, (ProArray*)&surfaces.srfs_array); if ( status == PRO_TK_NO_ERROR ) { status = ProSolidBodiesCollect((ProSolid)imported_model, &bodies); if (status == PRO_TK_NO_ERROR) { status = ProArraySizeGet(bodies, &body_num); for (i=0 ; i<body_num ; i++) status = ProSolidBodySurfaceVisit((ProSolidBody*)&bodies[i], AutoaxisCollectBodyRevSurfaces, ( ProAppData ) &surfaces ); } } status = ProSolidQuiltVisit( (ProSolid) imported_model, AutoaxisCollectQuiltSurfaces, NULL, ( ProAppData ) &surfaces ); if ( surfaces.num_rev_srfs > 0 ) { /* Create and group the axes */ status = AutoaxisAxesCreate( &surfaces ); status = AutoaxisAxesGroup ( &surfaces ); } ProTKPrintf("\n"); ProTKPrintf("\n**********************************************************"); ProTKPrintf("\n******************* AutoAxis Summary *********************"); ProTKPrintf("\n**********************************************************"); ProTKPrintf("\nTotal Surfaces found = %d",surfaces.total_srfs); ProTKPrintf("\nRev Surfaces found = %d",surfaces.num_rev_srfs); ProTKPrintf("\nAxes found = %d",surfaces.num_axes); ProTKPrintf("\nAxes Created = %d",surfaces.axes_created); ProTKPrintf("\n**********************************************************"); ProTKPrintf("\n**********************************************************"); ProTKPrintf("\n"); if ( surfaces.axes_pnts != NULL ) { status = ProArrayFree( ( ProArray *)&surfaces.axes_pnts); } if ( surfaces.srfs_array != NULL ) { status = ProArrayFree( ( ProArray *) &surfaces.srfs_array); } return PRO_TK_NO_ERROR; }