extern "C"{ // extern directive because I want to work with C++ // since Pro/TOOLKIT stuff is all written in C it // must be designated as C code #include #include #include #include #include #include #include #include #include #include // these 2 function must always be decreated and // defined in your Pro/TOOLKIT dll application int user_initialize(int argc,char ** argv); void user_terminate(); } #include #define PI 3.14159265 int user_evaluate(); // declare these functions int user_create_develop_menu(); void DrawLine(ProPoint3d p1,ProPoint3d p2); void UserArrowTipDraw(ProVector,ProVector,ProVector,double); static ProName dev_msg; // this macro will be a time saver #define MSGFILE ProStringToWstring(dev_msg,"develop_msg.txt") /*====================================================================*\ FUNCTION : ProUtilVectorCopy() PURPOSE : Copy a vector to another \*====================================================================*/ double *ProUtilVectorCopy( double from[3], double to[3]) { if(from == NULL) to[0] = to[1] = to[2] = 0.0; else { to[0] = from[0]; to[1] = from[1]; to[2] = from[2]; } return(to); } /*====================================================================*\ FUNCTION : ProUtilVectorCross() PURPOSE : Cross product of two vectors \*====================================================================*/ double *ProUtilVectorCross( double v1[3], double v2[3], double c[3]) { c[0] = v1[1] * v2[2] - v1[2] * v2[1]; c[1] = v1[2] * v2[0] - v1[0] * v2[2]; c[2] = v1[0] * v2[1] - v1[1] * v2[0]; return(c); } /*====================================================================*\ FUNCTION : ProUtilVectorsLincom() PURPOSE : Linear combination of two vectors \*====================================================================*/ double *ProUtilVectorsLincom( double scalar_a, double vector_a[3], double scalar_b, double vector_b[3], double result[3]) { result[0] = scalar_a * vector_a[0] + scalar_b * vector_b[0]; result[1] = scalar_a * vector_a[1] + scalar_b * vector_b[1]; result[2] = scalar_a * vector_a[2] + scalar_b * vector_b[2]; return(result); } /*====================================================================*\ FUNCTION : user_initialize() PURPOSE : the first function that gets executed when appl loads \*====================================================================*/ int user_initialize(int argc,char ** argv) { int menuId; // tell Pro/E to load its own menus // and extend them with our stuff as // specified in part.aux ProMenuFileRegister("MAIN","main.mnu", &menuId); ProMenuFileRegister("PART","part.mnu", &menuId); ProMenuAuxfileRegister("PART","part.aux", &menuId); // designated Develop button that will initiate // our menu creating function (note that there are no passing of arguments // to that function therefore NULL and 0) ProMenubuttonActionSet("PART", "Develop", (ProMenubuttonAction)user_create_develop_menu, NULL, 0); return(0); } /*====================================================================*\ FUNCTION : user_terminate() PURPOSE : gets executed when Pro/TOOLKIT application exits \*====================================================================*/ void user_terminate() { // clean up here if necessary return; } /*====================================================================*\ FUNCTION : user_create_develop_menu() PURPOSE : creates our menu \*====================================================================*/ int user_create_develop_menu(){ int action,menuId; // lets register our menu file ProMenuFileRegister ("Develop", "develop.mnu", &menuId); // and set up a function that will be called on clicking Evaluate ProMenubuttonActionSet ("Develop", "Evaluate", (ProMenubuttonAction)user_evaluate,NULL, 0); // also allow the user to quit so that menu will close itself ProMenubuttonActionSet ("Develop", "Quit Develop", (ProMenubuttonAction)ProMenuDelete, NULL, 0); ProMenubuttonActionSet("Develop", "Develop", (ProMenubuttonAction)ProMenuDelete, NULL, 0); // create the menu ProMenuCreate (PROMENUTYPE_MAIN, "Develop", &menuId); // and make it active ProMenuProcess ("", &action); return 0; } /*====================================================================*\ FUNCTION : DrawLine() PURPOSE : draws a line between two points \*====================================================================*/ void DrawLine( ProPoint3d p1, ProPoint3d p2) { ProPoint3d points[3]; int j; for (j=0; j<=2; j++) points[0][j]=p1[j]; for (j=0; j<=2; j++) points[1][j]=p2[j]; ProGraphicsColorSet(PRO_COLOR_HIGHLITE,NULL); ProGraphicsPolylineDraw(points,2); } /*====================================================================*\ FUNCTION : UserArrowTipDraw PURPOSE : Draw the tip of the arrow. \*====================================================================*/ void UserArrowTipDraw( ProVector e1, ProVector normal, ProVector h_start, double lenght) { double max_radius = 2. * .05 * lenght,u,deltau; /* max rad 5% of the lenght */ int i; ProVector e2,xx,cups,cus; ProUtilVectorCross(normal,e1,e2); for(i=0; i<3; i++) { u = 0.; deltau =.8; ProUtilVectorsLincom(cos(u),e1,sin(u),e2,xx); ProUtilVectorsLincom(max_radius,xx,1.,h_start,cups); u += deltau; while(u <= 2.5*PI) { ProUtilVectorsLincom(cos(u),e1,sin(u),e2,xx); ProUtilVectorsLincom(max_radius,xx,1.,h_start,cus); DrawLine(cus,cups); ProUtilVectorCopy(cus,cups); u += deltau; } max_radius -= 2. * .01666667 * lenght; ProUtilVectorsLincom(1.,h_start,(.05*lenght),normal,h_start); } } /*====================================================================*\ FUNCTION : DrawArrow() PURPOSE : Draws the whole arrow. \*====================================================================*/ void DrawArrow(ProVector org, ProVector vs,ProVector vt,double lenght){ ProVector vsXvt,dummy1; ProUtilVectorCross(vs,vt,vsXvt); DrawLine(org,ProUtilVectorsLincom(1.,org,lenght,vs,dummy1)); UserArrowTipDraw(vsXvt,vs,dummy1,lenght); } /*====================================================================*\ FUNCTION : user_evaluate() PURPOSE : main driver function ... put anything you want in here \*====================================================================*/ int user_evaluate() { ProSelection *sel = NULL; int n_sel; ProSelect("surface", -1, NULL, NULL, NULL, NULL, &sel, &n_sel); ProWindowRepaint(PRO_VALUE_UNUSED); ProModelitem mdlitem; ProSelectionModelitemGet(*sel, & mdlitem); // narrow the object ProSurface surface; ProGeomitemToSurface(&mdlitem,&surface); // we know it is a surface ProSrftype p_srf_type; ProSurfaceTypeGet(surface,&p_srf_type); // we need it to be planar if(PRO_SRF_PLANE != p_srf_type){ ProMessageDisplay(MSGFILE,"USER %0s","Surface is not plannar, try again."); ProMessageClear(); return -1; } ProGeomitemdata *p_data_ptr; ProSurfaceDataGet(surface,&p_data_ptr); // get the big structure // get the surface vectors double *_org=p_data_ptr->data.p_surface_data->srf_shape.plane.origin; double *_e1=p_data_ptr->data.p_surface_data->srf_shape.plane.e1; double *_e2=p_data_ptr->data.p_surface_data->srf_shape.plane.e2; double *_e3=p_data_ptr->data.p_surface_data->srf_shape.plane.e3; double surface_area; ProSurfaceAreaEval(surface,&surface_area); double lenght = sqrt(surface_area)/3.; // scale the arrow to look good DrawArrow(_org,_e3,_e1,lenght); // draw the normal to the surface DrawArrow(_org,_e1,_e3,lenght); DrawArrow(_org,_e2,_e3,lenght); // don't forget to clean up ProGeomitemdataFree(&p_data_ptr); return 0; }