/* Copyright (c) 2024 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved. */ #include <ProToolkit.h> #include <ProMdl.h> #include <ProElement.h> #include <ProFeature.h> #include <ProFeatType.h> #include <ProFeatForm.h> #include <ProModFeat.h> #include <ProExtrude.h> #include <ProSection.h> #include <ProSelection.h> #include <ProStdSection.h> #include <ProSecdim.h> #include <ProUtil.h> #include <TestError.h> #include <PTApplsUnicodeUtils.h> #include <math.h> #include <UtilMath.h> #include <UtilMatrix.h> #include <ProMessage.h> #include <ProSurface.h> #include <ProSolid.h> /*---------------------------External Functions------------------------------*/ extern void ProUtil2DPointTrans(); extern double *ProUtilLineLineX(); /*--------------------------Globlal Definition ------------------------------*/ typedef struct mtrx_data{ ProVector x_axis[2]; ProVector y_axis[2]; ProMatrix sec_trf; ProMatrix sk_mtrx; ProSelection sk_plane; double angle; }Matrix_data; static wchar_t msgfile[PRO_NAME_SIZE]; ProSelection *temp2 = NULL; ProSelection *temp1 = NULL; #ifndef PI # define PI 3.141592 #endif /* --------------------------Function Prototypes ----------------------------*/ ProError UserSelectSketchPlaneRefs(ProSelection **sketch_refs); ProError UserSelectProjectionEntities(ProSelection **proj_refs); ProError UserSelectOffsetDistances(double *offset_vals); ProError UserCreateTrfMatrix(Matrix_data *m_data); ProError UserSecerrorPrint ( ProWSecerror *section_errors ); ProError UserSweepSectionAdd ( ProSection ); ProError UserSweepSpineAdd ( ProSection , ProSelection * ); ProError UserSectionCircleToEllipseReplace (ProSection sect_handle); /* =============================================================== *\ Function: UsetUtilItemSelect Purpose: Selection utility for feature create examples \* =============================================================== */ ProError UserUtilItemSelect (char* filter_string, char* message, int* id, ProType* type) { ProError err; ProSelection* sels; ProModelitem item; int n_sels; err = PRO_TK_GENERAL_ERROR; do { ProMessageDisplay (msgfile, message); err = ProSelect (filter_string, 1, NULL, NULL, NULL, NULL, &sels, &n_sels); if (err == PRO_TK_USER_ABORT || err == PRO_TK_PICK_ABOVE) return err; } while (err != PRO_TK_NO_ERROR); err = ProSelectionModelitemGet (sels[0], &item); *id = item.id; *type = item.type; return PRO_TK_NO_ERROR; } /* =============================================================== *\ Function: UserSectionBuild(ProSection section, ProSelection *sketch_refs) Purpose: Creates 3D section \* =============================================================== */ ProError UserSectionBuild(ProSection section, ProSelection *sketch_refs) { ProSelection *proj_ents; int status, i, num_errors, err_counter, proj_ids[2]; int ctr_line_id, rt_line_id, lt_line_id, top_line_id, btm_line_id; int upper_arc_id, lower_arc_id, ent_id[1], c_ent_id[2], proj_ent_id[2]; int ll_dim_id, tl_dim_id, ua_dim_id, la_dim_id, cl_dim_id, proj_dim_id[2]; ProWSecerror sec_errors; Pro2dLinedef line; Pro2dClinedef c_line; Pro2dLinedef *left_linedef, *btm_linedef; ProSectionPointType pt_type[1], proj_pt_type[2]; Pro2dArcdef arc; Pro2dPnt place_pnt; ProMsg wmsg; char msg[PRO_PATH_SIZE]; double offsets[2]; Matrix_data matrix_data; ProStringToWstring(msgfile, "msg_ug3dsketch.txt"); /* =============================================================== *\ Obtain projection entity handles as ProSelection structures \* =============================================================== */ status = UserSelectProjectionEntities(&proj_ents); ERROR_CHECK("UserSelectrojectionEntities", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Project reference edges onto section \* =============================================================== */ for (i = 0; i < 2; i++) { status = ProSectionEntityFromProjection(section, proj_ents[i], &proj_ids[i]); ERROR_CHECK("ProSectionEntityFromProjection", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; } /* =============================================================== *\ Create section csys from edges, and obtion transformation matrix between sketch plane csys and section csys \* =============================================================== */ status = ProSectionEntityGet(section, proj_ids[0], (Pro2dEntdef **)&btm_linedef); ERROR_CHECK("ProSectionEntityGet", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; for (i = 0; i < 2; i++) { matrix_data.x_axis[0][i] = btm_linedef->end1[i]; matrix_data.x_axis[1][i] = btm_linedef->end2[i]; matrix_data.x_axis[i][2] = 0.0; } status = ProSectionEntityGet(section, proj_ids[1], (Pro2dEntdef **)&left_linedef); ERROR_CHECK("ProSectionEntityGet", "UserSectionBuild", status); if ( status != PRO_TK_NO_ERROR ) return status; for (i = 0; i < 2; i++) { matrix_data.y_axis[0][i] = left_linedef->end1[i]; matrix_data.y_axis[1][i] = left_linedef->end2[i]; matrix_data.y_axis[i][2] = 0.0; } status = ProSectionLocationGet(section, matrix_data.sk_mtrx); ERROR_CHECK("ProSectionLocationGet", "UserCreateTrfMatrix", status); if (status != PRO_TK_NO_ERROR) return status; status = ProSelectionCopy(sketch_refs[0], &(matrix_data.sk_plane)); ERROR_CHECK("ProSelectionCopy", "UserSectionBuild", status) ; if (status != PRO_TK_NO_ERROR) return status; status = UserCreateTrfMatrix(&matrix_data); ERROR_CHECK("UseCreateTrfMatrix", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Obtain offset values from projection entities \* =============================================================== */ status = UserSelectOffsetDistances(offsets); ERROR_CHECK("UserSelectOffsetDistances", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Add geometry center line ... \* =============================================================== */ c_line.type = PRO_2D_CENTER_LINE; c_line.end1[0] = 0.0; c_line.end1[1] = 0.0; c_line.end2[0] = 0.0; c_line.end2[1] = 1.0; ProUtil2DPointTrans(matrix_data.sec_trf, c_line.end1, c_line.end1); ProUtil2DPointTrans(matrix_data.sec_trf, c_line.end2, c_line.end2); status = ProSectionEntityAdd(section, (Pro2dEntdef*)&c_line, &ctr_line_id); ERROR_CHECK("UserSectionEntityAdd - 1", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; status = ProSectionEntityConstructionSet(section, ctr_line_id, PRO_B_FALSE); ERROR_CHECK("ProSectionEntityConstructionSet", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Add left vertical line ... \* =============================================================== */ line.type = PRO_2D_LINE; line.end1[0] = offsets[1]; line.end1[1] = offsets[0]; line.end2[0] = offsets[1]; line.end2[1] = offsets[0] + 50.0; ProUtil2DPointTrans(matrix_data.sec_trf, line.end1, line.end1); ProUtil2DPointTrans(matrix_data.sec_trf, line.end2, line.end2); status = ProSectionEntityAdd(section, (Pro2dEntdef*)&line, <_line_id); ERROR_CHECK("UserSectionEntityAdd - 1", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Add top line ... \* =============================================================== */ line.type = PRO_2D_LINE; line.end1[0] = offsets[1]; line.end1[1] = offsets[0] + 50.0; line.end2[0] = offsets[1] + 25.0; line.end2[1] = offsets[0] + 50.0; ProUtil2DPointTrans(matrix_data.sec_trf, line.end1, line.end1); ProUtil2DPointTrans(matrix_data.sec_trf, line.end2, line.end2); status = ProSectionEntityAdd(section, (Pro2dEntdef*)&line, &top_line_id); ERROR_CHECK("UserSectionEntityAdd - 2", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Add upper arc ... \* =============================================================== */ arc.type = PRO_2D_ARC; arc.center[0] = offsets[1] + 40.0; arc.center[1] = offsets[0] + 50.0; arc.start_angle = PI + matrix_data.angle; arc.end_angle = 1.5*PI + matrix_data.angle; arc.radius = 15.0; ProUtil2DPointTrans(matrix_data.sec_trf, arc.center, arc.center); status = ProSectionEntityAdd(section, (Pro2dEntdef*)&arc, &upper_arc_id); ERROR_CHECK("UserSectionEntityAdd - 3", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Add right vertical line ... \* =============================================================== */ line.type = PRO_2D_LINE; line.end1[0] = offsets[1] + 40.0; line.end1[1] = offsets[0] + 35.0; line.end2[0] = offsets[1] + 40.0; line.end2[1] = offsets[0] + 10.0; ProUtil2DPointTrans(matrix_data.sec_trf, line.end1, line.end1); ProUtil2DPointTrans(matrix_data.sec_trf, line.end2, line.end2); status = ProSectionEntityAdd(section, (Pro2dEntdef*)&line, &rt_line_id); ERROR_CHECK("UserSectionEntityAdd - 4", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Add lower arc ... \* =============================================================== */ arc.type = PRO_2D_ARC; arc.center[0] = offsets[1] + 40.0; arc.center[1] = offsets[0]; arc.start_angle = 0.5*PI + matrix_data.angle; arc.end_angle = PI + matrix_data.angle; arc.radius = 10.0; ProUtil2DPointTrans(matrix_data.sec_trf, arc.center, arc.center); status = ProSectionEntityAdd(section, (Pro2dEntdef*)&arc, &lower_arc_id); ERROR_CHECK("UserSectionEntityAdd - 5", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Add bottom line ... \* =============================================================== */ line.type = PRO_2D_LINE; line.end1[0] = offsets[1] + 30.0; line.end1[1] = offsets[0]; line.end2[0] = offsets[1]; line.end2[1] = offsets[0]; ProUtil2DPointTrans(matrix_data.sec_trf, line.end1, line.end1); ProUtil2DPointTrans(matrix_data.sec_trf, line.end2, line.end2); status = ProSectionEntityAdd(section, (Pro2dEntdef*)&line, &btm_line_id); ERROR_CHECK("UserSectionEntityAdd - 6", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Add dimension for left line \* =============================================================== */ ent_id[0] = lt_line_id; pt_type[0] = PRO_ENT_WHOLE; place_pnt[0] = offsets[1] - 2.0; place_pnt[1] = offsets[0] + 25.0; ProUtil2DPointTrans(matrix_data.sec_trf, place_pnt, place_pnt); status = ProSecdimCreate(section, ent_id, pt_type, 1, PRO_TK_DIM_LINE, place_pnt, &ll_dim_id); ERROR_CHECK("ProSecdimCreate - 1", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Add dimension for top line \* =============================================================== */ ent_id[0] = top_line_id; pt_type[0] = PRO_ENT_WHOLE; place_pnt[0] = offsets[1] + 13.0; place_pnt[1] = offsets[0] + 52.0; ProUtil2DPointTrans(matrix_data.sec_trf, place_pnt, place_pnt); status = ProSecdimCreate(section, ent_id, pt_type, 1, PRO_TK_DIM_LINE, place_pnt, &tl_dim_id); ERROR_CHECK("ProSecdimCreate - 2", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Add dimension for upper arc \* =============================================================== */ ent_id[0] = upper_arc_id; pt_type[0] = PRO_ENT_WHOLE; place_pnt[0] = offsets[1] + 42.0; place_pnt[1] = offsets[0] + 42.0; ProUtil2DPointTrans(matrix_data.sec_trf, place_pnt, place_pnt); status = ProSecdimCreate(section, ent_id, pt_type, 1, PRO_TK_DIM_RAD, place_pnt, &ua_dim_id); ERROR_CHECK("ProSecdimCreate - 3", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Add dimension for lower arc \* =============================================================== */ ent_id[0] = lower_arc_id; pt_type[0] = PRO_ENT_WHOLE; place_pnt[0] = offsets[1] +42.0; place_pnt[1] = offsets[0] + 5.0; ProUtil2DPointTrans(matrix_data.sec_trf, place_pnt, place_pnt); status = ProSecdimCreate(section, ent_id, pt_type, 1, PRO_TK_DIM_RAD, place_pnt, &la_dim_id); ERROR_CHECK("ProSecdimCreate - 4", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Add section dimension between center line and left line \* =============================================================== */ c_ent_id[0] = ctr_line_id; c_ent_id[1] = lt_line_id; proj_pt_type[0] = PRO_ENT_WHOLE; proj_pt_type[1] = PRO_ENT_WHOLE; place_pnt[0] = offsets[1] - 2.0; place_pnt[1] = offsets[0] + 15.0; ProUtil2DPointTrans(matrix_data.sec_trf, place_pnt, place_pnt); status = ProSecdimCreate(section, c_ent_id, proj_pt_type, 2, PRO_TK_DIM_LINE_LINE, place_pnt, &cl_dim_id); ERROR_CHECK("ProSecdimCreate - 5", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; status = ProSecdimValueSet(section, cl_dim_id, offsets[1]); ERROR_CHECK("ProSecdimValueSet", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Add section dimension between center line and left projection entity \* =============================================================== */ proj_ent_id[0] = ctr_line_id; proj_ent_id[1] = proj_ids[1]; proj_pt_type[0] = PRO_ENT_WHOLE; proj_pt_type[1] = PRO_ENT_WHOLE; place_pnt[0] = -2.0; place_pnt[1] = 15.0; ProUtil2DPointTrans(matrix_data.sec_trf, place_pnt, place_pnt); status = ProSecdimCreate(section, proj_ent_id, proj_pt_type, 2, PRO_TK_DIM_LINE_LINE, place_pnt, &proj_dim_id[0]); ERROR_CHECK("ProSecdimCreate - 5", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; status = ProSecdimValueSet(section, proj_dim_id[0], 0.0); ERROR_CHECK("ProSecdimValueSet", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Add section dimension between bottom proj ent and bottom line \* =============================================================== */ proj_ent_id[0] = btm_line_id; proj_ent_id[1] = proj_ids[0]; proj_pt_type[0] = PRO_ENT_WHOLE; proj_pt_type[1] = PRO_ENT_WHOLE; place_pnt[0] = offsets[1] + 20.0; place_pnt[1] = offsets[0] - 3.0; ProUtil2DPointTrans(matrix_data.sec_trf, place_pnt, place_pnt); status = ProSecdimCreate(section, proj_ent_id, proj_pt_type, 2, PRO_TK_DIM_LINE_LINE, place_pnt, &proj_dim_id[1]); ERROR_CHECK("ProSecdimCreate - 6", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; status = ProSecdimValueSet(section, proj_dim_id[1], offsets[0]); ERROR_CHECK("ProSecdimValueSet", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; /* =============================================================== *\ Solve and regenerate the section \* =============================================================== */ status = ProSecerrorAlloc(&sec_errors); ERROR_CHECK("ProSecerrorAlloc", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR) return status; status = ProSectionSolve(section, &sec_errors); if (status != 0) { UserSecerrorPrint ( &sec_errors ); return status; } status = ProSectionRegenerate(section, &sec_errors); if (status != 0) { UserSecerrorPrint ( &sec_errors ); return status; } status = ProSelectionFree(&(matrix_data.sk_plane)); ERROR_CHECK("ProSelectionFree", "UserSectionBuild", status); free(temp1); free(temp2); temp1 = NULL; temp2 = NULL; return(status); } /* =============================================================== *\ Function: UserSelectSketchPlaneRefs Purpose: Select references for sketch plane and orientation plane \* =============================================================== */ ProError UserSelectSketchPlaneRefs(ProSelection **sketch_refs) { ProSelection *sel; int num_sel; ProError status; if (temp1 == NULL) temp1 = (ProSelection *)calloc(2, sizeof(ProSelection)); ProStringToWstring(msgfile, "msg_ug3dsketch.txt"); status = ProMessageDisplay(msgfile, "USER Select sketch plane"); ERROR_CHECK("ProMessageDisplay", "UserSectionBuild", status); status = ProSelect("surface", 1, NULL, NULL, NULL, NULL, &sel, &num_sel); ERROR_CHECK("ProSelect", "UserSectionBuild", status); status = ProSelectionCopy(sel[0],&temp1[0]); ERROR_CHECK("ProSelectionCopy", "UserSectionBuild", status); status = ProMessageDisplay(msgfile, "USER Select top plane for orientation"); ERROR_CHECK("ProMessageDisplay", "UserSectionBuild", status); status = ProSelect("surface", 1, NULL, NULL, NULL, NULL, &sel, &num_sel); ERROR_CHECK("ProSelect", "UserSectionBuild", status); status = ProSelectionCopy(sel[0], &temp1[1]); ERROR_CHECK("ProSelectionCopy", "UserSectionBuild", status); *sketch_refs = temp1; return(status); } /* =============================================================== *\ Function: UserSelectProjectionEntities Purpose: Select projection entity references from existing geometry \* =============================================================== */ ProError UserSelectProjectionEntities(ProSelection **proj_refs) { ProSelection *sel; int num_sel; ProError status; if (temp2== NULL) temp2= (ProSelection *)calloc(2, sizeof(ProSelection)); /* =============================================================== *\ Prompt user to select reference geometry \* =============================================================== */ ProStringToWstring(msgfile, "msg_ug3dsketch.txt"); status = ProMessageDisplay(msgfile, "USER Select first projection reference (bottom edge of sketch plane)"); ERROR_CHECK("ProMessageDisplay", "UserSectionBuild", status); status = ProSelect("edge", 1, NULL, NULL, NULL, NULL, &sel, &num_sel); ERROR_CHECK("ProSelect", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR || num_sel < 1) return(status); status = ProSelectionCopy(sel[0], &temp2[0]); ERROR_CHECK("ProSelectionCopy", "UserSectionBuild", status); status = ProMessageDisplay(msgfile, "USER Select second projection reference (left edge of sketch plane)"); ERROR_CHECK("ProMessageDisplay", "UserSectionBuild", status); status = ProSelect("edge", 1, NULL, NULL, NULL, NULL, &sel, &num_sel); ERROR_CHECK("ProSelect", "UserSectionBuild", status); if (status != PRO_TK_NO_ERROR || num_sel < 1) return(status); status = ProSelectionCopy(sel[0], &temp2[1]); ERROR_CHECK("ProSelectionCopy", "UserSectionBuild", status); *proj_refs = temp2; return(status); } ProError UserSelectOffsetDistances(double *offset_vals) { ProError status; ProStringToWstring(msgfile, "msg_ug3dsketch.txt"); status = ProMessageDisplay(msgfile, "USER Enter offset distance from first projection reference"); ERROR_CHECK("ProMessageDisplay", "UserSelectOffsetDistances", status); status = ProMessageDoubleRead(NULL, &offset_vals[0]); ERROR_CHECK("ProMessageDoubleRead", "UserSelectOffsetDistances", status); status = ProMessageDisplay(msgfile, "USER Enter offset distance from second projection reference"); ERROR_CHECK("ProMessageDisplay", "UserSelectOffsetDistances", status); status = ProMessageDoubleRead(NULL, &offset_vals[1]); ERROR_CHECK("ProMessageDoubleRead", "UserSelectOffsetDistances", status); return(status); } ProError UserCreateTrfMatrix(Matrix_data *m_data) { ProPoint3d origin; double sel_pnt[3], proj_sel_pnt[3], sel_vect[3]; double x_plane[3]; ProVector x, y, sk_plane_norm; ProVector d1[2], d2[2], norm; int status; ProMatrix inv_sk_mtrx; ProModelitem sk_modelitem; ProSurface sk_surf; ProUvParam sk_param; /* =============================================================== *\ Project point selected on sketch plane onto section \* =============================================================== */ ProUtilMatrixInvert(m_data->sk_mtrx, inv_sk_mtrx); status = ProSelectionUvParamGet(m_data->sk_plane, sk_param); ERROR_CHECK("ProSelectionUvParamGet", "UserCreateTrfMatrix", status); status = ProSelectionModelitemGet(m_data->sk_plane, &sk_modelitem); ERROR_CHECK("ProSelectionModelitemGet", "UserCreateTrfMatrix", status); status = ProGeomitemToSurface((ProGeomitem *)&sk_modelitem, &sk_surf); ERROR_CHECK("ProGeomitemToSurface", "UserCreateTrfMatrix", status); status = ProSurfaceXyzdataEval(sk_surf, sk_param, sel_pnt, d1, d2, norm); ERROR_CHECK("ProSurfaceXyzdataEval", "UserCreateTrfMatrix", status); ProUtilPointTrans(inv_sk_mtrx, sel_pnt, proj_sel_pnt); proj_sel_pnt[2] = 0.0; /* =============================================================== *\ Create x and y vectors of transformation matrix such that selected point on sketch plane is in first quadrant \* =============================================================== */ ProUtilLineLineX(m_data->x_axis, m_data->y_axis, origin); ProUtilVectorDiff(proj_sel_pnt, origin, sel_vect); sel_vect[2] = 0.0; ProUtilVectorNormalize(sel_vect, sel_vect); ProUtilVectorDiff(m_data->x_axis[0], m_data->x_axis[1], x); ProUtilVectorNormalize(x, x); ProUtilVectorDiff(m_data->y_axis[0], m_data->y_axis[1], y); ProUtilVectorNormalize(y, y); /* ========= Selected point should be in first quadrant ======= */ if ((ProUtilVectorDot(x,sel_vect)) < 0.0) ProUtilVectorScale(-1.0, x, x); if ((ProUtilVectorDot(y,sel_vect)) < 0.0) ProUtilVectorScale(-1.0, y, y); /* ========= Make sure surface normal is properly oriented ======= */ /* ========= with respect to x and y ============================= */ ProUtilVectorCross(x, y, sk_plane_norm); ProUtilVectorTrans(m_data->sk_mtrx, sk_plane_norm, sk_plane_norm); ProUtilMatrixCopy(NULL, m_data->sec_trf); if ((ProUtilVectorDot(sk_plane_norm, m_data->sk_mtrx[2])) < 0.0) { ProUtilVectorCopy(y, m_data->sec_trf[0]); ProUtilVectorCopy(x, m_data->sec_trf[1]); ProUtilVectorCopy(NULL, m_data->sec_trf[2]); ProUtilVectorCopy(origin, m_data->sec_trf[3]); } else { ProUtilVectorCopy(x, m_data->sec_trf[0]); ProUtilVectorCopy(y, m_data->sec_trf[1]); ProUtilVectorCopy(NULL, m_data->sec_trf[2]); ProUtilVectorCopy(origin, m_data->sec_trf[3]); } m_data->sec_trf[2][2] = m_data->sec_trf[3][3] = 1.0; /* =============================================================== *\ Calculate rotation angle \* =============================================================== */ x_plane[0] = 1.0; x_plane[1] = x_plane[2] = 0.0; ProUtilVectorCross(x_plane, m_data->sk_mtrx[0], norm); ProUtilVectorCross(m_data->sec_trf[0], m_data->sec_trf[1], sk_plane_norm); m_data->angle = fabs(acos(ProUtilVectorDot(x_plane, m_data->sec_trf[0]))); if (ProUtilVectorDot(norm, sk_plane_norm) < 0.0) m_data->angle *= -1.0; return(status); } /*====================================================================*\ FUNCTION: UserSectionReplace PURPOSE: Menu button action function for section replacement \*====================================================================*/ ProError UserSectionReplace () { ProError status; ProSelection* sel_array; int n_sels; ProFeature feat; ProElement sk_elem_tree; ProElempath sk_elem_path; ProElempathItem elem_path_data [3]; ProElement sk_elem; ProSection sect_handle; ProFeatureCreateOptions *options = 0; int n_opts = 1; ProErrorlist redef_errs; elem_path_data [0].type = PRO_ELEM_PATH_ITEM_TYPE_ID; elem_path_data [0].path_item.elem_id = PRO_E_STD_SECTION; elem_path_data [1].type = PRO_ELEM_PATH_ITEM_TYPE_ID; elem_path_data [1].path_item.elem_id = PRO_E_SKETCHER; status = ProSelect ("feature", 1, NULL, NULL, NULL, NULL, &sel_array, &n_sels); ERROR_CHECK ("ProSelect", "UserSectionReplace", status); if (status != PRO_TK_NO_ERROR) return status; status = ProSelectionModelitemGet (sel_array [0], &feat); ERROR_CHECK ("ProSelectionModelitemGet", "UserSectionReplace", status); /*--------------------------------------------------------------------*\ Find the sketch handle from the feature handle. \*--------------------------------------------------------------------*/ status = ProFeatureElemtreeExtract (&feat, NULL, PRO_FEAT_EXTRACT_NO_OPTS, &sk_elem_tree); ERROR_CHECK ("ProFeatureElemtreeExtract()", "UserSectionReplace", status); status = ProElempathAlloc (&sk_elem_path); ERROR_CHECK ("ProElempathAlloc()", "UserSectionReplace", status); status = ProElempathDataSet (sk_elem_path, elem_path_data, 2); ERROR_CHECK ("ProElempathDataSet()", "UserSectionReplace", status); status = ProElemtreeElementGet (sk_elem_tree, sk_elem_path, &sk_elem); ERROR_CHECK ("ProElemtreeElementGet()", "UserSectionReplace", status); ProElempathFree (&sk_elem_path); status = ProElementSpecialvalueGet(sk_elem, NULL, (ProAppData *) §_handle); ERROR_CHECK ("ProElementSpecialvalueGet()", "UserSectionReplace", status); /*--------------------------------------------------------------------*\ Replace the section entity \*--------------------------------------------------------------------*/ status = UserSectionCircleToEllipseReplace (sect_handle); ERROR_CHECK ("UserSectionCircleToEllipseReplace", "UserSectionReplace", status); if (status == PRO_TK_NO_ERROR) { status = ProArrayAlloc(1,sizeof(ProFeatureCreateOptions), 1, (ProArray*)&options); options[0]= PRO_FEAT_CR_DO_NOT_DISPLAY; status = ProFeatureWithoptionsRedefine (NULL, &feat, sk_elem_tree, options, PRO_REGEN_NO_FLAGS, &redef_errs); ERROR_CHECK ("ProFeatureWithoptionsRedefine()", "UserSectionReplace", status); status = ProArrayFree((ProArray*)&options); ProWindowRepaint (-1); } return (1); } /*====================================================================*\ FUNCTION: UserSectionCircleToEllipseReplace PURPOSE: Replace a circular sketch entity with ellipse entity \*====================================================================*/ ProError UserSectionCircleToEllipseReplace (ProSection sect_handle) { ProError status; ProBoolean is_proj; ProIntlist id_array; int array_size, i, replace_id; Pro2dEntdef* ent_def; Pro2dEllipsedef ellipse_def; Pro2dCircledef* circle_def; int project_1 = -1; int project_2 = -1; int circle_id = -1; int ellipse_id; int ent_ids [2]; ProSectionPointType pnt_types [2]; Pro2dPnt place_pnt = {0.0, 0.0}; int dim_id; ProWSecerror sec_errs; /*--------------------------------------------------------------------*\ Get existing entities (needed to do the replacement) \*--------------------------------------------------------------------*/ status = ProSectionEntityIdsGet (sect_handle, &id_array, &array_size); ERROR_CHECK ("ProSectionEntityIdsGet()", "UserSectionCircleToEllipseReplace", status); for (i = 0; i < array_size; i++) { status = ProSectionEntityGet (sect_handle, id_array[i], &ent_def); if (ent_def->type == PRO_2D_LINE) { /*--------------------------------------------------------------------*\ Check for reference entity \*--------------------------------------------------------------------*/ status = ProSectionEntityIsProjection (sect_handle, id_array [i], &is_proj); if (!is_proj) return /*PRO_TK_UNAV_SEC;*/13; else { if (project_1 == -1) project_1 = id_array [i]; else if (project_2 == -1) project_2 = id_array [i]; else return /*PRO_TK_UNAV_SEC;*/14; } } else if (ent_def->type == PRO_2D_CIRCLE) { circle_id = id_array [i]; circle_def = (Pro2dCircledef*)ent_def; } else return /*PRO_TK_UNAV_SEC;*/15; } if (project_1 == -1 || project_2 == -1 || circle_id == -1) return /*PRO_TK_UNAV_SEC;*/16; ProArrayFree ((ProArray*)&id_array); /*--------------------------------------------------------------------*\ Add the new entity (ellipse) \*--------------------------------------------------------------------*/ ellipse_def.type = PRO_2D_ELLIPSE; memcpy (ellipse_def.origin, circle_def->center, sizeof (Pro2dPnt)); ellipse_def.x_radius = circle_def->radius * 1.2; ellipse_def.y_radius = circle_def->radius * 0.8; status = ProSectionEntityAdd (sect_handle, (Pro2dEntdef*)&ellipse_def, &ellipse_id); ERROR_CHECK ("ProSectionEntityAdd()", "UserSectionCircleToEllipseReplace", status); /*--------------------------------------------------------------------*\ Manually dimension to new entity to the reference entities -- The replacement process will remove projected entities not currently in use. -- Adding dimensions from the replacement ellipse to the projected entities forces the entities to remain. \*--------------------------------------------------------------------*/ ent_ids [0] = project_1; ent_ids [1] = ellipse_id; pnt_types [0] = PRO_ENT_WHOLE; pnt_types [1] = PRO_ENT_CENTER; status = ProSecdimCreate (sect_handle, ent_ids, pnt_types, 2, PRO_TK_DIM_LINE_POINT, place_pnt, &dim_id); ERROR_CHECK ("ProSecdimCreate()", "UserSectionCircleToEllipseReplace", status); ent_ids [0] = project_2; status = ProSecdimCreate (sect_handle, ent_ids, pnt_types, 2, PRO_TK_DIM_LINE_POINT, place_pnt, &dim_id); ERROR_CHECK ("ProSecdimCreate()", "UserSectionCircleToEllipseReplace", status); /*--------------------------------------------------------------------*\ Perform the replacement \*--------------------------------------------------------------------*/ status = ProSectionEntityReplace (sect_handle, circle_id, ellipse_id); ERROR_CHECK ("ProSectionEntityReplace()", "UserSectionCircleToEllipseReplace", status); /*--------------------------------------------------------------------*\ Finish up dimensioning (x- and y- radius dimensions) \*--------------------------------------------------------------------*/ status = ProSectionAutodim (sect_handle, &sec_errs); ERROR_CHECK ("ProSectionAutodim()", "UserSectionCircleToEllipseReplace", status); if ( status != PRO_TK_NO_ERROR ) { UserSecerrorPrint ( &sec_errs ); return status; } status = ProSectionRegenerate (sect_handle, &sec_errs); ERROR_CHECK ("ProSectionRegenerate()", "UserSectionCircleToEllipseReplace", status); if ( status != PRO_TK_NO_ERROR ) { UserSecerrorPrint ( &sec_errs ); } return (status); } /* =============================================================== *\ Function: UserSectionPointBuild(ProSection section, ProSelection *sketch_refs) Purpose: Creates a 3D Section consisting of Geometry Points \* =============================================================== */ ProError UserSectionPointBuild(ProSection section, ProSelection *sketch_refs) { int status, i, num_errors, err_counter, proj_ids[2]; int point_id; double offsets[2]; char msg[PRO_PATH_SIZE]; ProMsg wmsg; Matrix_data matrix_data; ProSelection *proj_ents; ProWSecerror sec_errors; Pro2dPointdef point; Pro2dLinedef *btm_linedef, *left_linedef; ProStringToWstring(msgfile, "msg_ug3dsketch.txt"); /* =============================================================== *\ Obtain projection entity handles as ProSelection structures \* =============================================================== */ status = UserSelectProjectionEntities(&proj_ents); ERROR_CHECK("UserSelectrojectionEntities", "UserSectionPointBuild", status); /* =============================================================== *\ Project reference edges onto section \* =============================================================== */ for (i = 0; i < 2; i++) { status = ProSectionEntityFromProjection(section, proj_ents[i], &proj_ids[i]); ERROR_CHECK("ProSectionEntityFromProjection", "UserSectionPointBuild", status); if (status != PRO_TK_NO_ERROR) return(status); } /* =============================================================== *\ Create section csys from edges, and obtion transformation matrix between sketch plane csys and section csys \* =============================================================== */ status = ProSectionEntityGet(section, proj_ids[0], (Pro2dEntdef **)&btm_linedef); ERROR_CHECK("ProSectionEntityGet", "UserSectionPointBuild", status); for (i = 0; i < 2; i++) { matrix_data.x_axis[0][i] = btm_linedef->end1[i]; matrix_data.x_axis[1][i] = btm_linedef->end2[i]; matrix_data.x_axis[i][2] = 0.0; } status = ProSectionEntityGet(section, proj_ids[1], (Pro2dEntdef **)&left_linedef); ERROR_CHECK("ProSectionEntityGet", "UserSectionPointBuild", status); for (i = 0; i < 2; i++) { matrix_data.y_axis[0][i] = left_linedef->end1[i]; matrix_data.y_axis[1][i] = left_linedef->end2[i]; matrix_data.y_axis[i][2] = 0.0; } status = ProSectionLocationGet(section, matrix_data.sk_mtrx); ERROR_CHECK("ProSectionLocationGet", "UserCreateTrfMatrix", status); status = ProSelectionCopy(sketch_refs[0], &(matrix_data.sk_plane)); ERROR_CHECK("ProSelectionCopy", "UserSectionPointBuild", status) ; status = UserCreateTrfMatrix(&matrix_data); ERROR_CHECK("UseCreateTrfMatrix", "UserSectionPointBuild", status); /* =============================================================== *\ Obtain offset values from projection entities \* =============================================================== */ status = UserSelectOffsetDistances(offsets); ERROR_CHECK("UserSelectOffsetDistances", "UserSectionPointBuild", status); /* =============================================================== *\ Add the required point(s) Currently only one point is added This may be extended to add any number of points \* =============================================================== */ point.type = PRO_2D_POINT; point.pnt[0] = 100; point.pnt[1] = 100; ProUtil2DPointTrans(matrix_data.sec_trf, point.pnt, point.pnt ); status = ProSectionEntityAdd (section, (Pro2dEntdef*)&point, &point_id); ERROR_CHECK("ProSectionEntityAdd - 1", "UserSectionPointBuild", status); status = ProSectionEntityConstructionSet(section, point_id, PRO_B_FALSE); ERROR_CHECK("ProSectionEntityConstructionSet - 1", "UserSectionPointBuild", status); /* =============================================================== *\ Dimension, Solve and regenerate the section \* =============================================================== */ status = ProSecerrorAlloc(&sec_errors); ERROR_CHECK("ProSecerrorAlloc", "UserSectionPointBuild", status); status = ProSectionAutodim(section, &sec_errors); if (status != 0) { UserSecerrorPrint ( &sec_errors ); return status; } status = ProSectionRegenerate(section, &sec_errors); if (status != 0) { UserSecerrorPrint ( &sec_errors ); return status; } status = ProSelectionFree(&(matrix_data.sk_plane)); ERROR_CHECK("ProSelectionFree", "UserSectionPointBuild", status); free(temp1); free(temp2); temp1 = NULL; temp2 = NULL; return(status); } /* Purpose : To print the Section errors and then free memory */ ProError UserSecerrorPrint ( ProWSecerror *section_errors ) { ProError status; ProMsg error_message; char error_message_s[PRO_PATH_SIZE]; int error_count; int n_sec, error_id; status = ProSecerrorCount ( section_errors, &n_sec ); ERROR_CHECK (" ProSecerrorCount", "UserSecerrorPrint", status ); ProTKPrintf("Number of errors in ProWSecerror = %d \n",n_sec ); if ( status == PRO_TK_NO_ERROR ) { for ( error_count = 0; error_count < n_sec; error_count++ ) { status = ProSecerrorMsgGet ( *section_errors, error_count, error_message); ERROR_CHECK (" ProSecerrorMsgGet", "UserSecerrorPrint", status ); if ( status == PRO_TK_NO_ERROR ) { status = ProSecerrorItemGet ( *section_errors, error_count, &error_id); ERROR_CHECK (" ProSecerrorItemGet", "UserSecerrorPrint", status ); if ( status == PRO_TK_NO_ERROR ) { ProWstringToString (error_message_s, error_message); ProTKPrintf(" %s : Problem ID : %d \n", error_message_s, error_id ); } } } } status = ProSecerrorFree ( section_errors ); ERROR_CHECK (" ProSecerrorFree", "UserSecerrorPrint", status ); return status; } /*===============================================================*\ FUNCTION: UserSweepSectionAdd ProError UserSweepSectionAdd ( ProSection ); PURPOSE: Creates a 2D sketch for sweep section \*===============================================================*/ ProError UserSweepSectionAdd ( ProSection section_here ) { Pro2dLinedef line; ProError status; int line_id[4]; int cline_id1, cline_id2; ProSelection *proj_ents; int proj_ids[2]; Pro2dLinedef *left_linedef, *btm_linedef; ProName section_name; ProWSecerror section_errors; int n_sec; ProMsg error_message; char error_message_s[100]; int i, error_id; status = ProSecerrorAlloc ( §ion_errors ); ERROR_CHECK (" ProSecerrorAlloc", "UserSweepSectionAdd", status ); { /* Adding Projection Entities => Specific to C/S in Sweep */ /*---------------------------------------------------------------*\ Get the projection entity handles as ProSelection structures. \*---------------------------------------------------------------*/ status = UserSelectProjectionEntities (&proj_ents); ERROR_CHECK (" UserSelectProjectionEntities", "UserSweepSectionAdd", status ); if (status != PRO_TK_NO_ERROR) return status; /*---------------------------------------------------------------*\ Project the reference edges onto the section. \*---------------------------------------------------------------*/ for (i = 0; i < 2; i++) { status = ProSelectionVerify ( proj_ents[i] ); ERROR_CHECK (" ProSelectionVerify", "UserSweepSectionAdd", status ); if (status != PRO_TK_NO_ERROR) return status; status = ProSectionEntityFromProjection ( section_here, proj_ents[i], &proj_ids[i]); ERROR_CHECK (" ProSectionEntityFromProjection", "UserSweepSectionAdd", status ); if (status != PRO_TK_NO_ERROR) return status; } status = ProSectionEntityGet ( section_here, proj_ids[0], (Pro2dEntdef**)&left_linedef); ERROR_CHECK (" ProSectionEntityGet", "UserSweepSectionAdd", status ); if (status != PRO_TK_NO_ERROR) return status; status = ProSectionEntityGet ( section_here, proj_ids[1], (Pro2dEntdef**)&btm_linedef); ERROR_CHECK (" ProSectionEntityGet", "UserSweepSectionAdd", status ); if (status != PRO_TK_NO_ERROR) return status; } line.type = PRO_2D_LINE; line.end1[0] = 0; line.end1[1] = 0; line.end2[0] = 100; line.end2[1] = 0; status = ProSectionEntityAdd ( section_here, (Pro2dEntdef*)&line, &line_id[0] ) ; ERROR_CHECK (" ProSectionEntityAdd", "UserSweepSectionAdd", status ); if (status != PRO_TK_NO_ERROR) return status; line.type = PRO_2D_LINE; line.end1[0] = 100; line.end1[1] = 0; line.end2[0] = 100; line.end2[1] = 100; status = ProSectionEntityAdd ( section_here, (Pro2dEntdef*)&line, &line_id[1] ) ; ERROR_CHECK (" ProSectionEntityAdd", "UserSweepSectionAdd", status ); if (status != PRO_TK_NO_ERROR) return status; line.type = PRO_2D_LINE; line.end1[0] = 100; line.end1[1] = 100; line.end2[0] = 0; line.end2[1] = 100; status = ProSectionEntityAdd ( section_here, (Pro2dEntdef*)&line, &line_id[2] ) ; ERROR_CHECK (" ProSectionEntityAdd", "UserSweepSectionAdd", status ); if (status != PRO_TK_NO_ERROR) return status; line.type = PRO_2D_LINE; line.end1[0] = 0; line.end1[1] = 100; line.end2[0] = 0; line.end2[1] = 0; status = ProSectionEntityAdd ( section_here, (Pro2dEntdef*)&line, &line_id[3] ) ; ERROR_CHECK (" ProSectionEntityAdd", "UserSweepSectionAdd", status ); if (status != PRO_TK_NO_ERROR) return status; { double epsilon; status = ProSectionEpsilonGet( section_here, &epsilon ); ERROR_CHECK (" ProSectionEpsilonGet", "UserSweepSectionAdd", status ); ProTKPrintf ("The current epsilon is %f\n", epsilon ); } status = ProSectionEpsilonSet( section_here, 0.1 ); ERROR_CHECK (" ProSectionEpsilonSet", "UserSweepSectionAdd", status ); if (status != PRO_TK_NO_ERROR) return status; status = ProSectionAutodim ( section_here, §ion_errors ); ERROR_CHECK (" ProSectionAutodim", "UserSweepSectionAdd", status ); if ( status != PRO_TK_NO_ERROR ) { UserSecerrorPrint ( §ion_errors ); return status; } status = ProSectionRegenerate ( section_here, §ion_errors ); ERROR_CHECK (" ProSectionRegenerate", "UserSweepSectionAdd", status ); if ( status != PRO_TK_NO_ERROR ) { UserSecerrorPrint ( §ion_errors ); return status; } return ( status ); } /*===============================================================*\ FUNCTION: UserSweepSpineAdd ProError UserSweepSpineAdd ( ProSection, ProSelection * ); PURPOSE: Creates a 3D trajectory for sweep section \*===============================================================*/ ProError UserSweepSpineAdd (ProSection section_here, ProSelection *sketch_refs ) { ProSelection *proj_ents; int status, i, num_errors, err_counter, proj_ids[2]; int ctr_line_id, rt_line_id, lt_line_id, top_line_id, btm_line_id; int upper_arc_id, lower_arc_id, ent_id[1], c_ent_id[2], proj_ent_id[2]; int ll_dim_id, tl_dim_id, ua_dim_id, la_dim_id, cl_dim_id, proj_dim_id[2]; ProWSecerror sec_errors; Pro2dLinedef line; Pro2dClinedef c_line; Pro2dLinedef *left_linedef, *btm_linedef; ProSectionPointType pt_type[1], proj_pt_type[2]; Pro2dArcdef arc; Pro2dPnt place_pnt; ProMsg wmsg; char msg[PRO_PATH_SIZE]; double offsets[2]; Matrix_data matrix_data; int row, column; /* initializing the matrices */ for ( row = 0; row < 4; row++ ) { for ( column = 0 ; column < 4; column++ ) { matrix_data.sec_trf[row][column] = 0.0; matrix_data.sk_mtrx[row][column] = 0.0; } } /*---------------------------------------------------------------*\ Get the projection entity handles as ProSelection structures. \*---------------------------------------------------------------*/ status = UserSelectProjectionEntities (&proj_ents); ERROR_CHECK (" UserSelectProjectionEntities", "UserSweepSpineAdd", status ); if (status != PRO_TK_NO_ERROR) return status; /*---------------------------------------------------------------*\ Project the reference edges onto the section. \*---------------------------------------------------------------*/ for (i = 0; i < 2; i++) { status = ProSelectionVerify ( proj_ents[i] ); ERROR_CHECK (" ProSelectionVerify", "UserSweepSpineAdd", status ); if (status != PRO_TK_NO_ERROR) return status; status = ProSectionEntityFromProjection ( section_here, proj_ents[i], &proj_ids[i]); ERROR_CHECK (" ProSectionEntityFromProjection", "UserSweepSpineAdd", status ); if (status != PRO_TK_NO_ERROR) return status; } /*---------------------------------------------------------------*\ Create the section coordinate system from the edges. Get the transformation matrix between the sketch plane coordinate system and the section coordinate system. \*---------------------------------------------------------------*/ status = ProSectionEntityGet ( section_here, proj_ids[0], (Pro2dEntdef**)&btm_linedef); ERROR_CHECK (" ProSectionEntityGet", "UserSweepSpineAdd", status ); if (status != PRO_TK_NO_ERROR) return status; for (i = 0; i < 2; i++) { matrix_data.x_axis[0][i] = btm_linedef->end1[i]; matrix_data.x_axis[1][i] = btm_linedef->end2[i]; matrix_data.x_axis[i][2] = 0.0; } status = ProSectionEntityGet ( section_here, proj_ids[1], (Pro2dEntdef**)&left_linedef); ERROR_CHECK (" ProSectionEntityGet", "UserSweepSpineAdd", status ); if (status != PRO_TK_NO_ERROR) return status; for (i = 0; i < 2; i++) { matrix_data.y_axis[0][i] = left_linedef->end1[i]; matrix_data.y_axis[1][i] = left_linedef->end2[i]; matrix_data.y_axis[i][2] = 0.0; } status = ProSectionLocationGet ( section_here, matrix_data.sk_mtrx); ERROR_CHECK (" ProSectionLocationGet", "UserSweepSpineAdd", status ); if (status != PRO_TK_NO_ERROR) return status; status = ProSelectionCopy (sketch_refs[0], &(matrix_data.sk_plane)); ERROR_CHECK (" ProSelectionCopy", "UserSweepSpineAdd", status ); if (status != PRO_TK_NO_ERROR) return status; status = UserCreateTrfMatrix (&matrix_data); ERROR_CHECK (" UserCreateTrfMatrix", "UserSweepSpineAdd", status ); if (status != PRO_TK_NO_ERROR) return status; /*---------------------------------------------------------------*\ Get the offset values from the projection entities. \*---------------------------------------------------------------*/ status = UserSelectOffsetDistances (offsets); ERROR_CHECK (" UserSelectOffsetDistances", "UserSweepSpineAdd", status ); if (status != PRO_TK_NO_ERROR) return status; ProTKPrintf("Offset Distances in main are offset[0] = %f : offset[1] = %f\n", offsets[0], offsets[1]); /*---------------------------------------------------------------*\ Add the left vertical line. \*---------------------------------------------------------------*/ line.type = PRO_2D_LINE; line.end1[0] = offsets[1]; line.end1[1] = offsets[0]; line.end2[0] = offsets[1]; line.end2[1] = offsets[0] + 50.0; ProUtil2DPointTrans (matrix_data.sec_trf, line.end1, line.end1); ProUtil2DPointTrans (matrix_data.sec_trf, line.end2, line.end2); status = ProSectionEntityAdd ( section_here, (Pro2dEntdef*)&line, <_line_id); ERROR_CHECK (" ProSectionEntityAdd", "UserSweepSpineAdd", status ); if (status != PRO_TK_NO_ERROR) return status; /*---------------------------------------------------------------*\ Solve and regenerate the section. \*---------------------------------------------------------------*/ status = ProSecerrorAlloc (&sec_errors); ERROR_CHECK (" ProSecerrorAlloc", "UserSweepSpineAdd", status ); status = ProSectionEpsilonSet( section_here, 0.1 ); ERROR_CHECK (" ProSectionEpsilonSet", "UserSweepSpineAdd", status ); if (status != PRO_TK_NO_ERROR) return status; status = ProSectionAutodim ( section_here, &sec_errors); ERROR_CHECK (" ProSectionAutodim", "UserSweepSpineAdd", status ); if (status != PRO_TK_NO_ERROR) { UserSecerrorPrint ( &sec_errors ); return status; } status = ProSectionRegenerate ( section_here, &sec_errors); ERROR_CHECK (" ProSectionRegenerate", "UserSweepSpineAdd", status ); if (status != PRO_TK_NO_ERROR) { UserSecerrorPrint ( &sec_errors ); return status; } status = ProSelectionFree (&(matrix_data.sk_plane)); ERROR_CHECK (" ProSelectionFree", "UserSweepSpineAdd", status ); return (status); }