/*
Copyright (c) 2019 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved.
*/
#include <ProToolkit.h>
#include <ProSurface.h>
#include <ProArray.h>
#include <ProGtol.h>
#include <ProUtil.h>
#include <ProModelitem.h>
#include <ProMessage.h>
#include <ProAnnotation.h>
#include <ProSolid.h>
#include <ProDisplist.h>
#include <ProWindows.h>
#include <UtilMessage.h>
#include <PTApplsUnicodeUtils.h>
#define EPSM6 0.0001
/*---------------------------------------------------------------------*\
Data structure for finding parallel solid plane surfaces
\*---------------------------------------------------------------------*/
typedef struct planes_data
{
ProGeomitem reference;
ProAnnotationPlane ap;
ProVector normal;
double tolerance;
} Planesdata_t;
/*====================================================================*\
FUNCTION: UsrPlanePositiontolSet()
PURPOSE: To add a position gtol to the specified surface
\*====================================================================*/
int UsrPlanePositiontolSet(
ProSelection surface, /* The surface */
ProVector pos, /* The position of the gtol */
ProGeomitem *reference, /* The datum reference */
ProAnnotationPlane* ap, /* The annotation plane */
double tolerance) /* The tolerance value */
{
ProError status;
ProGtoldata gdata;
ProGtoldataStatus gstatus;
ProGtolleader leader, *leaders;
ProName wname;
ProCharName name;
ProModelitem modelitem;
ProGtoldatumref datumref;
ProSelection ref;
ProGtol gtol;
/*--------------------------------------------------------------------*\
Allocate the gtol data structure
\*--------------------------------------------------------------------*/
ProGtoldataAlloc(reference->owner, &gdata);
/*--------------------------------------------------------------------*\
Set the gtol type
\*--------------------------------------------------------------------*/
ProGtoldataTypeSet(gdata, PROGTOLTYPE_POSITION, &gstatus);
/*--------------------------------------------------------------------*\
Set the gtol model
\*--------------------------------------------------------------------*/
ProGtoldataModelSet(gdata, reference->owner, &gstatus);
/*--------------------------------------------------------------------*\
Set the reference to the surface
\*--------------------------------------------------------------------*/
ProGtoldataReferenceSet(gdata, PROGTOLRTYPE_SURF, surface, &gstatus);
/*--------------------------------------------------------------------*\
Allocate a leader which is attached to the surface
\*--------------------------------------------------------------------*/
ProGtolleaderAlloc(PROLEADERTYPE_ARROWHEAD, surface, &leader);
/*--------------------------------------------------------------------*\
Set up an array of leaders with the one leader in it
\*--------------------------------------------------------------------*/
ProArrayAlloc(0, sizeof(ProGtolleader), 1, (ProArray)&leaders);
ProArrayObjectAdd((ProArray)&leaders, -1, 1, &leader);
/*--------------------------------------------------------------------*\
Set the placement using the leader and the specified position
\*--------------------------------------------------------------------*/
ProGtoldataPlacementSet(gdata, PROGTOLPTYPE_LEADERS, NULL, leaders,
pos, NULL, &gstatus);
/*--------------------------------------------------------------------*\
Set the annotation plane
\*--------------------------------------------------------------------*/
ProGtoldataPlaneSet(gdata, ap);
/*--------------------------------------------------------------------*\
Free the leader
\*--------------------------------------------------------------------*/
ProGtolleaderFree(&leader);
/*--------------------------------------------------------------------*\
Set up a ProSelection for the datum, and set it as the basic reference
\*--------------------------------------------------------------------*/
ProSelectionAlloc(NULL, reference, &ref);
ProGtoldatumrefAlloc(ref, PROGTOLMATCOND_DEFAULT_RFS, NULL,
PROGTOLMATCOND_DEFAULT_RFS, &datumref);
ProGtoldataGtoldatumrefSet(gdata, datumref, NULL, NULL, &gstatus);
ProGtoldatumrefFree(&datumref);
/*--------------------------------------------------------------------*\
Set the tolerance value
\*--------------------------------------------------------------------*/
ProSelectionModelitemGet(surface, &modelitem);
ProTKSprintf(name, "surf%d",modelitem.id); ProStringToWstring(wname, name);
ProGtoldataValueSet(gdata, PRO_B_TRUE, tolerance, wname, &gstatus);
/*--------------------------------------------------------------------*\
Create the tolerance
\*--------------------------------------------------------------------*/
status = ProGtolCreate(gdata, >ol);
/*--------------------------------------------------------------------*\
Free the gtol data
\*--------------------------------------------------------------------*/
ProGtoldataFree(&gdata);
return(status == PRO_TK_NO_ERROR ? 1 : 0);
}
/*====================================================================*\
FUNCTION: UsrSurfAction()
PURPOSE: Action function called when visiting solid surfaces to
attach gtol to.
\*====================================================================*/
ProError UsrSurfAction(
ProSurface surface,
ProError filt_status,
ProAppData data)
{
Planesdata_t *pdata=(Planesdata_t*)data;
ProVector normal, cross, pos;
ProUvParam uv;
ProSrftype stype;
int id;
ProModelitem modelitem;
ProSelection sel;
/*--------------------------------------------------------------------*\
If the surface is not a plane, skip it.
\*--------------------------------------------------------------------*/
ProSurfaceTypeGet(surface, &stype);
if(stype != PRO_SRF_PLANE)
return(PRO_TK_NO_ERROR);
/*--------------------------------------------------------------------*\
If the surface is not parallel to the reference datum, skip it.
\*--------------------------------------------------------------------*/
uv[0]=uv[1]=0.0;
ProSurfaceXyzdataEval(surface, uv, pos, NULL, NULL, normal);
ProUtilVectorCross(normal, pdata->normal, cross);
if(fabs(ProUtilVectorLength(cross)) > EPSM6)
return(PRO_TK_NO_ERROR);
/*--------------------------------------------------------------------*\
Set the position of the gtol to be the point for zero UV, offset
by the outward normal.
\*--------------------------------------------------------------------*/
pos[0] += normal[0];
pos[1] += normal[1];
pos[2] += normal[2];
/*--------------------------------------------------------------------*\
Add the gtol to the surface
\*--------------------------------------------------------------------*/
ProSurfaceIdGet(surface, &id);
ProModelitemInit(pdata->reference.owner, id, PRO_SURFACE, &modelitem);
ProSelectionAlloc(NULL, &modelitem, &sel);
UsrPlanePositiontolSet(sel, pos, &pdata->reference, &pdata->ap, pdata->tolerance);
return(PRO_TK_NO_ERROR);
}
/*====================================================================*\
FUNCTION: UsrPlanesTol()
PURPOSE: Command to add a position gtol to all solid planes that are
parallel to a selected datum. Makes the selected datum
into a gtol reference if required.
\*====================================================================*/
int UsrPlanesTol()
{
ProError status;
ProSelection *sel;
int n_sel;
ProGeomitem datum;
ProName wname;
ProBoolean ref_datum, is_in_dim;
ProDimension dim;
Planesdata_t data;
ProUvParam uv;
ProSurface surface;
ProFileName msgfil;
ProAnnotationPlane ap;
ProVector normal;
ProModelitem ap_datum;
ProSurface ap_surf;
ProGeomitemdata* gdata;
ProStringToWstring (msgfil, "msg_uggtol.txt");
/*--------------------------------------------------------------------*\
Select the datum
\*--------------------------------------------------------------------*/
ProMessageDisplay(msgfil,
"USER Select a datum plane for gtol references");
if(ProSelect("datum",1,NULL,NULL,NULL,NULL,&sel,&n_sel)
!= PRO_TK_NO_ERROR || n_sel < 0)
return(0);
ProSelectionModelitemGet(sel[0], &datum);
/*--------------------------------------------------------------------*\
Convert it's type to be a DATUM_PLANE
\*--------------------------------------------------------------------*/
ProModelitemInit(datum.owner, datum.id, PRO_DATUM_PLANE, &datum);
ProModelitemNameGet(&datum, wname);
/*--------------------------------------------------------------------*\
Is the datum a gtol reference?
\*--------------------------------------------------------------------*/
ProGeomitemIsGtolref(&datum, &ref_datum, &is_in_dim, &dim);
/*--------------------------------------------------------------------*\
If so, say so; if not, ask whether it should be made one
\*--------------------------------------------------------------------*/
if(ref_datum)
ProMessageDisplay(msgfil,"USER %0w is already a reference datum",
wname);
else
{
ProMessageDisplay(msgfil,"USER %0w is not a reference datum."
"Do you wish to set it (yes/no)?|||yes", wname);
ref_datum = ProUtilYesnoGet("YES");
/*--------------------------------------------------------------------*\
If "no" then exit, else set the datum ad a gtol reference
\*--------------------------------------------------------------------*/
if(!ref_datum)
return(0);
ProGeomitemSetdatumSet (&datum, NULL);
}
/*--------------------------------------------------------------------*\
Remember the reference
\*--------------------------------------------------------------------*/
memcpy(&data.reference, &datum, sizeof(ProGeomitem));
/*--------------------------------------------------------------------*\
Calculate the normal, used in checking for parallel surfaces
\*--------------------------------------------------------------------*/
ProSurfaceInit(datum.owner, datum.id, &surface);
uv[0]=uv[1]=0.0;
ProSurfaceXyzdataEval(surface, uv, NULL, NULL, NULL, data.normal);
/*--------------------------------------------------------------------*\
Ask the user for the annotation plane
\*--------------------------------------------------------------------*/
ProMessageDisplay(msgfil,"USER Select the annotation plane to use");
if (ProSelect ("datum", 1, NULL, NULL, NULL, NULL, &sel, &n_sel))
return (0);
/*--------------------------------------------------------------------*\
Create the annotation plane using the default normal vector
\*--------------------------------------------------------------------*/
status = ProSelectionModelitemGet (sel[0], &ap_datum);
status = ProGeomitemToSurface (&ap_datum, &ap_surf);
status = ProSurfaceDataGet (ap_surf, &gdata);
memcpy (normal, gdata->data.p_surface_data->srf_shape.plane.e3, sizeof (ProVector));
ProGeomitemdataFree (&gdata);
status = ProAnnotationplaneCreate (sel[0], normal, &ap);
memcpy(&data.ap, &ap, sizeof(ProAnnotationPlane));
/*--------------------------------------------------------------------*\
Ask the user for the tolerance value
\*--------------------------------------------------------------------*/
ProMessageDisplay(msgfil,"USER Enter the tolerance value|||0.1");
status = ProMessageDoubleRead(NULL, &data.tolerance);
if(status == PRO_TK_MSG_USER_QUIT)
return(0);
if(status != PRO_TK_NO_ERROR)
data.tolerance = 0.1;
/*--------------------------------------------------------------------*\
Visit all the solid surfaces, attaching a gtol to each one which is
plane and parallel to the reference.
\*--------------------------------------------------------------------*/
ProSolidSurfaceVisit(datum.owner, UsrSurfAction, NULL, &data);
/*--------------------------------------------------------------------*\
Repaint the model to show the added geometric tolerances
\*--------------------------------------------------------------------*/
ProDisplistInvalidate (datum.owner);
ProWindowRepaint (PRO_VALUE_UNUSED);
return(1);
}