/* Copyright (c) 2024 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved. */ /*---------------------- Pro/Toolkit Includes ------------------------*/ #include "ProToolkit.h" #include "ProMdl.h" #include "ProModelitem.h" #include "ProSelection.h" #include "ProMessage.h" #include "ProMenu.h" #include "ProSurface.h" #include "ProCsys.h" #include "ProFeature.h" #include "ProDisplist.h" #include "ProGraphic.h" #include "ProXsec.h" #include "UtilMatrix.h" /*---------------------- Application Includes ------------------------*/ #include "UtilMath.h" /*------------------------- Global Data -----------------------------*/ static ProName msgfil; /*---------------------- Function Prototypes -------------------------*/ int user_Neutral_Axis(); void UsrPolylineDraw(); /*====================================================================* Function : user_Neutral_Axis() Purpose : Example for Calculating the Mass Properties of Cross Sections \*====================================================================*/ int user_Neutral_Axis() { ProError status; ProPart part; int n_sel; ProSelection *sel; ProModelitem surface_modelitem, csys_modelitem; ProSurface surface; ProSrftype stype; ProPoint3d finish, normal, pos, cross, xpos, cog; ProUvParam uv; double dist, absdist, offset; ProCsys csys; ProGeomitemdata *csys_geomdata; ProCsysdata *csys_data; ProMatrix transf, nulltransf; ProName w_csys_name, w_name; int n_steps, id=-1, surf_id; ProXsec xsec; ProDimension dimension; ProMassProperty mprop; ProPoint3d points[100]; int n_points=0; ProFeature feature; ProFeatureDeleteOptions *delete_opts = 0; int *feat_ids = NULL; ProStringToWstring(msgfil,"msg_ugxsec.txt"); ProMdlCurrentGet((ProMdl*)&part); /*-----------------------------------------------------------*\ Select a starting plane for the cross section. \*-----------------------------------------------------------*/ ProMessageDisplay(msgfil, "USER Pick the start plane"); status = ProSelect("face", 1, NULL, NULL, NULL, NULL, &sel, &n_sel); if(status != PRO_TK_NO_ERROR || n_sel < 1) return(0); ProSelectionModelitemGet(sel[0], &surface_modelitem); ProSurfaceInit(part, surface_modelitem.id, &surface); ProSurfaceTypeGet(surface, &stype); if(stype != PRO_SRF_PLANE) return(0); /*-----------------------------------------------------------*\ Select a finish point. \*-----------------------------------------------------------*/ ProMessageDisplay(msgfil, "USER Pick the end position"); status = ProSelect("face,edge", 1, NULL, NULL, NULL, NULL, &sel, &n_sel); if(status != PRO_TK_NO_ERROR || n_sel < 1) return(0); ProSelectionPoint3dGet(sel[0], finish); /*-----------------------------------------------------------*\ Get the geometry of the start plane. \*-----------------------------------------------------------*/ uv[0]=uv[1]=0.0; ProSurfaceXyzdataEval(surface, uv, pos, NULL, NULL, normal); dist = ProUtilPointPlaneDist(finish, pos, normal); /*-----------------------------------------------------------*\ Select a Csys Datum whose X and Y are parallel to the start plane. \*-----------------------------------------------------------*/ ProMessageDisplay(msgfil, "USER Pick the csys"); while (1) { status = ProSelect("csys", 1, NULL, NULL, NULL, NULL, &sel, &n_sel); if(status != PRO_TK_NO_ERROR || n_sel < 1) return(0); ProSelectionModelitemGet(sel[0], &csys_modelitem); ProCsysInit(part, csys_modelitem.id, &csys); ProCsysDataGet(csys, &csys_geomdata); csys_data = csys_geomdata->data.p_csys_data; ProUtilVectorCross(normal, csys_data->z_vector, cross); if (fabs(ProUtilVectorLength(cross)) > EPSM6) ProMessageDisplay(msgfil, "USER Csys has wrong orientation"); else break; } /*-----------------------------------------------------------*\ Get the name and location of the coordinate system. \*-----------------------------------------------------------*/ ProMatrixInit(csys_data->x_vector, csys_data->y_vector, csys_data->z_vector, csys_data->origin, transf); ProModelitemNameGet(&csys_modelitem, w_csys_name); /*-----------------------------------------------------------*\ Get the number of steps in the analysis. \*-----------------------------------------------------------*/ ProMessageDisplay(msgfil, "USER Number of steps [QUIT] : "); if(ProMessageIntegerRead(NULL, &n_steps) != PRO_TK_NO_ERROR) return(0); /*-----------------------------------------------------------*\ Create an initial cross section half-way down. \*-----------------------------------------------------------*/ ProStringToWstring(w_name, "ZZZ"); status = ProSurfaceIdGet (surface, &surf_id); status = ProXsecParallelCreate((ProSolid)part, w_name, surf_id, dist / 2.0, &xsec, &dimension); /*-----------------------------------------------------------*\ Step from start plane to finish. \*-----------------------------------------------------------*/ absdist = fabs(dist); for (offset = 0.0; offset <= absdist; offset += absdist / n_steps) { /*-----------------------------------------------------------*\ Modify the cross-sectional offset dimension to move it to the right position. \*-----------------------------------------------------------*/ ProDimensionValueSet(&dimension, offset); /*-----------------------------------------------------------*\ Regenerate the cross section, and calculate the mass properties. \*-----------------------------------------------------------*/ status = ProSolidRegenerate((ProSolid)part, PRO_REGEN_NO_FLAGS); status = ProXsecRegenerate(&xsec); status = ProXsecMassPropertyCompute(&xsec, w_csys_name, &mprop); if (PRO_TK_NO_ERROR != status) continue; /*-----------------------------------------------------------*\ Transform the COG to model coordinates. \*-----------------------------------------------------------*/ ProPntTrfEval(mprop.center_of_gravity, transf, cog); /*-----------------------------------------------------------*\ Shift the cross COG from the XY-plane of the coordinate system to the plane of the cross section. \*-----------------------------------------------------------*/ xpos[0] = pos[0] - normal[0] * offset; xpos[1] = pos[1] - normal[1] * offset; xpos[2] = pos[2] - normal[2] * offset; ProUtilPlaneLineX(xpos, normal, cog, normal, cog); ProUtilVectorCopy (cog, points[n_points++]); } /*-----------------------------------------------------------*\ Delete the cross section and the owning feature (a datum plane). \*-----------------------------------------------------------*/ ProDimensionFeatureGet (&dimension, &feature); status = ProXsecDelete(&xsec); status = ProArrayAlloc(1,sizeof(ProFeatureDeleteOptions), 1, (ProArray*)&delete_opts); delete_opts[0] = PRO_FEAT_DELETE_CLIP; status = ProArrayAlloc(1,sizeof(int), 1, (ProArray*)&feat_ids); feat_ids[0] = feature.id; ProFeatureWithoptionsDelete(part, feat_ids, delete_opts, PRO_REGEN_NO_FLAGS); status = ProArrayFree((ProArray*)&delete_opts); status = ProArrayFree((ProArray*)&feat_ids); /*-----------------------------------------------------------*\ Display the line of the COG as a 3D list of vectors. \*-----------------------------------------------------------*/ ProDisplist3dCreate(id, UsrPolylineDraw, points, &n_points, NULL, NULL, NULL, NULL); ProUtilMatrixCopy(NULL, nulltransf); ProDisplist3dDisplay(id++, nulltransf); ProWindowRepaint(-1); return (0); } /*===========================================================*\ Function to draw a polyline, with arguments suitable for acting as a callback to ProDisplist3dCreate() \*===========================================================*/ void UsrPolylineDraw( ProPoint3d *points, int *n_points) { ProColor old_color, warning_color; warning_color.method = PRO_COLOR_METHOD_TYPE; warning_color.value.type = PRO_COLOR_WARNING; ProGraphicsColorModify (&warning_color, &old_color); ProGraphicsPolylineDraw(points, *n_points); ProGraphicsColorModify(&old_color, NULL); }