/* Copyright (c) 2024 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 <ProGtolAttach.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; ProGtol gtol; ProGtolAttach gtolAttach; ProPath path; ProAnnotationReference* refs = NULL; wchar_t* symStr = NULL; /*--------------------------------------------------------------------*\ 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); /*--------------------------------------------------------------------*\ Free the leader \*--------------------------------------------------------------------*/ ProGtolleaderFree(&leader); /*--------------------------------------------------------------------*\ Set up a ProSelection for the datum, and set it as the basic reference \*--------------------------------------------------------------------*/ status = ProArrayAlloc(1, sizeof(ProAnnotationReference), 1, (ProArray*)&refs); refs[0].type = PRO_ANNOT_REF_SINGLE; refs[0].object.reference = NULL; status = ProSelectionToReference(surface, &(refs[0].object.reference)); status = ProGtolSymbolStringGet(PRO_GTOL_SYMBOL_DEFAULT_RFS, PRO_FONT_ISO, &symStr); /*--------------------------------------------------------------------*\ Set the tolerance value \*--------------------------------------------------------------------*/ ProSelectionModelitemGet(surface, &modelitem); ProTKSprintf(name, "surf%d",modelitem.id); ProStringToWstring(wname, name); // ProGtoldataValueSet(gdata, PRO_B_TRUE, tolerance, wname, &gstatus); status = ProGtolAttachAlloc(reference->owner, >olAttach); status = ProGtolAttachLeadersSet(gtolAttach, ap, PRO_GTOL_LEADER, leaders, pos); /*--------------------------------------------------------------------*\ Create the tolerance \*--------------------------------------------------------------------*/ ProStringToWstring(path, "gp"); ProWstringConcatenate(symStr, path, PRO_VALUE_UNUSED); status = ProMdlGtolCreate(reference->owner, PROGTOLTYPE_POSITION, gtolAttach, path, >ol); status = ProGtolReferencesAdd(>ol, refs); status = ProArrayFree((ProArray*)&refs); /*--------------------------------------------------------------------*\ Free the gtol data \*--------------------------------------------------------------------*/ 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((double)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; ProSolidBody* bodies = NULL; int i = 0, body_num = 0; 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 bodies surfaces, attaching a gtol to each one which is plane and parallel to the reference. \*--------------------------------------------------------------------*/ status = ProSolidBodiesCollect(datum.owner, &bodies); if (status == PRO_TK_NO_ERROR) { status = ProArraySizeGet(bodies, &body_num); for (i=0 ; i<body_num ; i++) status = ProSolidBodySurfaceVisit((ProSolidBody*)&bodies[i], UsrSurfAction, &data); } /*--------------------------------------------------------------------*\ Repaint the model to show the added geometric tolerances \*--------------------------------------------------------------------*/ ProDisplistInvalidate (datum.owner); ProWindowRepaint (PRO_VALUE_UNUSED); return(1); }