/*
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);
}