/*====================================================================*\
FILE    : UgXsecMassProps.c
PURPOSE : ProTK doc sample-code toplevel

HISTORY..
DATE      BUILD   AUTHOR   MODIFICATIONS
04-dec-97 H-02-02 Stefan   $$1 Setup 
29-Dec-97 H-03-33 Philippe $$2 Initialize id to -1
\*====================================================================*/

/*---------------------- 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"

/*---------------------- Application Includes ------------------------*/
#include "UtilMath.h"

/*---------------------- Pro/Develop Includes ------------------------*/
#include "prodevelop.h"

/*------------------------- Global Data -----------------------------*/
static ProName msgfil;

/*---------------------- Function Prototypes -------------------------*/
int user_Neutral_Axis();
void UsrPolylineDraw();
int UsrDimFeatureGet();


/*====================================================================*
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, xsec_status, dim_id, id=-1;
    Prohandle xsec;
    PRODIMENSION dimension;
    Pro_mass_property  *mprop;
    ProPoint3d points[100];
    int n_points=0;
    ProFeature feature;
    int feat_ids[1];
    ProFeatureDeleteOptions opts[1];

    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");
    xsec = prodb_create_parallel_xsec((Prohandle)part, w_name,
     (Prohandle)surface, dist / 2.0, NULL, NULL, &dim_id, &xsec_status);

/*-----------------------------------------------------------*\
    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.
\*-----------------------------------------------------------*/
        prodim_get_dim((Prohandle)part, dim_id, &dimension);
        dimension.value = offset;
        prodim_set_dim ((Prohandle)part, dim_id, &dimension);

/*-----------------------------------------------------------*\
        Regenerate the cross section, and calculate the
        mass properties.
\*-----------------------------------------------------------*/
        prodb_regen_parallel_xsec((Prohandle)part, xsec);
        if (prodb_mass_prop_xsec((Prohandle)part, xsec,
            w_csys_name, &mprop) == 0)
            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).
\*-----------------------------------------------------------*/
    UsrDimFeatureGet(part, dim_id, &feature);
    prodb_delete_xsec((Prohandle)part, xsec);
    feat_ids[0] = feature.id;
    opts[0] = PRO_FEAT_DELETE_CLIP;
    ProFeatureDelete(part, feat_ids, 1, opts, 1);

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

/*===========================================================*\
    Function to draw a polyline, with arguments suitable 
    for acting as a callback to ProDisplist3dCreate()
\*===========================================================*/
void UsrPolylineDraw(
    ProPoint3d *points,
    int *n_points)
{
    ProColortype old_color, c;
    ProGraphicsColorSet(PRO_COLOR_WARNING, &old_color);
    ProGraphicsPolylineDraw(points, *n_points);
    ProGraphicsColorSet(old_color, &c);
}

/*===========================================================*\
    Function to get the identifier of the feature to which
    a specified dimension belongs
\*===========================================================*/
int UsrDimFeatureGet(
    ProSolid part,
    int      dim_id,
    ProFeature *feature)
{
    Object_element   input, *output;

    input.type = SEL_3D_DIMENSION;
    input.id = dim_id;
    input.ptr = NULL;

    if(pro_element_info((Prohandle)part, &input, PRO_BELONG_TO,
        -1, &output) <= 0)
	return (0);

    ProModelitemInit(part, output[0].id, PRO_FEATURE, feature);
    return(1);
}
