home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 13 / 13.iso / p / p024 / 16.img / AME3.LIB / DESIGN.C < prev    next >
Encoding:
Text File  |  1992-06-17  |  50.7 KB  |  1,654 lines

  1. /* Next available MSG number is 113 */
  2.  
  3. /************************************************************************
  4. Name: design.c.  AME2_APLIB_SAMP_design.c
  5.  
  6. Description: AME/API sample program for basic machine elements modelling
  7.  
  8. Author: AME Group
  9.         Autodesk, Inc.
  10.  
  11.  
  12.  
  13.  
  14. Copyright (C) 1992 by Autodesk, Inc.
  15. **************************************************************************
  16. *                                                                        * 
  17. *    Permission to use, copy, modify, and distribute this software       *
  18. *    for any purpose and without fee is hereby granted, provided         *
  19. *    that the above copyright notice appears in all copies and that      *
  20. *    both that copyright notice and this permission notice appear in     *
  21. *    all supporting documentation.                                       *
  22. *                                                                        *
  23. *    THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED        *
  24. *    WARRANTY.  ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR     *
  25. *    PURPOSE AND OF MERCHANTABILITY ARE HEREBY DISCLAIMED.               *
  26. *                                                                        *
  27. *                                                                        *
  28. *    The objective of this sample program is to illustrate how to        *
  29. *    use AME/API as application programming interface for creation and   *
  30. *    manipulation of basic mechanical components.  Six commands are      *
  31. *    available in this program for users to create the geometric         *
  32. *    model of basic machine elements such as shaft, wheel, gear,         *
  33. *    bearing, bolt and nut.  Each part is characterized by design        *
  34. *    parameters which link to engineering applications.  All components  *
  35. *    are created in the world coordinate system.                         *
  36. *                                                                        *
  37. *    "SOLSHAFT" command allows the user to create a standard shaft by    *
  38. *    specifying shaft's diameter, length and keyway.  The shaft is       *
  39. *    positioned along positive Z axis with one end at insertion point.   *
  40. *    The keyway is cut from one end of the shaft (near the origin) along *
  41. *    the intersection of XZ plane and cylindrical surface at the         *
  42. *    specified depth, width and length.  The command syntax and design   *
  43. *    parameters associated with the "SOLSHAFT" are shown as follows:     *
  44. *                                                                        *
  45. *    Command: solshaft                                                   *
  46. *    Insertion base point <0,0,0>:                                       *
  47. *    Enter shaft diameter <1.0>:                                         *
  48. *    Enter shaft length <5.0>:                                           *
  49. *    Enter keyway depth <0.3>:                                           *
  50. *    Enter keyway width <0.4>:                                           *
  51. *    Enter keyway length <2.0>:                                          *
  52. *                                                                        *
  53. *                                                                        *
  54. *    "SOLWHEEL" command allows the user to create a standard flywheel    *
  55. *    by specifying flywheel's diameter, thickness, hub, hole and keyway. *
  56. *    The flywheel is created symmetrically about the XY plane with its   *
  57. *    central axis along Z axis. The keyway is cut on the hole surface    *
  58. *    along XZ plane at the specified depth and width.                    *
  59. *                                                                        *
  60. *    Command: solwheel                                                   *
  61. *    Insertion base point <0,0,0>:                                       *
  62. *    Enter wheel diameter <5.0>:                                         *
  63. *    Enter wheel thickness <1.0>:                                        *
  64. *    Enter hub diameter <3.0>:                                           *
  65. *    Enter hub extrusion thickness <0.25>:                               *
  66. *    Enter shaft hole diameter <1.0>:                                    *
  67. *    Enter keyway depth <0.2>:                                           *
  68. *    Enter keyway width <0.4>:                                           *
  69. *                                                                        *
  70. *                                                                        *
  71. *    "SOLGEAR" command allows the user to create a standard spur gear    *
  72. *    by specifying gear's pitch diameter, number of teeth, thickness,    *
  73. *    and pressure angle.  The gear is created by extrusion of a 2D       *
  74. *    polyline (defined on the XY plane) along positive Z axis.           *
  75. *    The involute profile of the teeth are represented by arcs.          *
  76. *                                                                        *
  77. *    Command: solgear                                                    *
  78. *    Insertion base point <0,0,0>:                                       *
  79. *    Enter pitch circle diameter <4.0>:                                  *
  80. *    Enter number of teeth <12>:                                         *
  81. *    Enter gear thickness <1.0>:                                         *
  82. *    Enter pressure angle <25 degrees>:                                  *
  83. *                                                                        *
  84. *                                                                        *
  85. *    "SOLBEAR" command allows the user to create a standard bearing by   *
  86. *    specifying bearing's outer diameter, thickness, height, hole and    *
  87. *    base.  The bearing is created by extrusion of a 2D polyline         *
  88. *    (defined on the XY plane) along positive Z axis.                    *
  89. *                                                                        *
  90. *    Command: solbear                                                    *
  91. *    Insertion base point <0,0,0>:                                       *
  92. *    Enter outer diameter <5.0>:                                         *
  93. *    Enter bearing thickness <3.0>:                                      *
  94. *    Enter hole diameter <2.0>:                                          *
  95. *    Enter distance from base to center of hole <5.0>:                   *
  96. *    Enter base height <1.0>:                                            *
  97. *    Enter base width <6.0>:                                             *
  98. *                                                                        *
  99. *                                                                        *
  100. *    "SOLBOLT" command allows the user to create a standard bolt by      *
  101. *    specifying bolt's head diameter and height, screw diameter and      *
  102. *    length.  The bolt is positioned along positive Z axis with one of   *
  103. *    its end located at insertion point.                                 *
  104. *                                                                        *
  105. *    Command: solbolt                                                    *
  106. *    Insertion base point <0,0,0>:                                       *
  107. *    Enter head diameter <2.0>:                                          *
  108. *    Enter head height <0.5>:                                            *
  109. *    Enter screw diameter <1.0>:                                         *
  110. *    Enter screw length <5.0>:                                           *
  111. *                                                                        *
  112. *    "SOLNUT" command allows the user to create a standard nut by        *
  113. *    specifying nut's diameter, height and hole.  The nut is positioned  *
  114. *    on the XY plane such that its central axis coincides with positive  *
  115. *    Z axis.                                                             *
  116. *                                                                        *
  117. *    Command: solnut                                                     *
  118. *    Insertion base point <0,0,0>:                                       *
  119. *    Enter nut diameter <2.0>:                                           *
  120. *    Enter nut height <0.5>:                                             *
  121. *    Enter hole diameter <1.0>:                                          *
  122. *                                                                        *
  123. *                                                                        *
  124. *    To run the program, You have to xload the executable code "design"  *
  125. *    Then enter any of the following command at regular AutoCAD prompt   *
  126. *                                                                        *
  127. *    command: solshaft                                                   *
  128. *    command: solwheel                                                   *
  129. *    command: solgear                                                    *
  130. *    command: solbear                                                    *
  131. *    command: solbolt                                                    *
  132. *    command: solnut                                                     *
  133. *                                                                        *
  134. **************************************************************************
  135.  
  136.  
  137. Modification history:
  138.     Refer to the RCS section at the end of this file.
  139.  
  140. Bugs and restrictions on use:
  141.  
  142. Notes:
  143.  
  144. **************************************************************************/
  145.  
  146.  
  147. /*************************************************************************/
  148. /* Includes */
  149. /*************************************************************************/
  150.  
  151. #include <stdio.h>
  152. #include <string.h>
  153. #include <math.h>
  154. #include <adslib.h>
  155. #include <aplib.h>
  156.  
  157. /*************************************************************************/
  158. /* Defines */
  159. /*************************************************************************/
  160.  
  161. #define  PI       3.14159265358979
  162. #define  EPSILON  1.0e-8
  163.  
  164. #ifndef ELEMENTS
  165. #define ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
  166. #endif
  167.  
  168. /*************************************************************************/
  169. /* Typedefs */
  170. /*************************************************************************/
  171.  
  172. /*************************************************************************/
  173. /* Global variables */
  174. /*************************************************************************/
  175.  
  176. /* Function type declaration */
  177.  
  178. int      funcload();
  179. void     print_new_command_set();
  180. void     create_shaft_func();
  181. ap_Bool  get_shaft_data();
  182. void     create_wheel_func();
  183. ap_Bool  get_wheel_data();
  184. void     create_gear_func();
  185. ap_Bool  get_gear_data();
  186. ap_Bool  define_gear_pline();
  187. void     create_bearing_func();
  188. ap_Bool  get_bearing_data();
  189. void     create_bolt_func();
  190. ap_Bool  get_bolt_data();
  191. ap_Bool  define_hexagon_pline();
  192. void     create_nut_func();
  193. ap_Bool  get_nut_data();
  194. void     trans_uc2wc();
  195.  
  196. /* Command definition and dispatch table.  */
  197.  
  198. struct ads_comm {
  199.     char   *cmdname;
  200.     void   (*cmdfunc) ();
  201. };
  202.  
  203. struct ads_comm cmdtab[] = {
  204.  
  205.      {/*MSG1*/"C:SOLSHAFT", create_shaft_func},
  206.      {/*MSG2*/"C:SOLWHEEL", create_wheel_func},
  207.      {/*MSG3*/"C:SOLGEAR", create_gear_func},
  208.      {/*MSG4*/"C:SOLBEAR", create_bearing_func},
  209.      {/*MSG5*/"C:SOLBOLT", create_bolt_func},
  210.      {/*MSG6*/"C:SOLNUT", create_nut_func},
  211.     };
  212.  
  213.  
  214. /*************************************************************************/
  215. /* .doc main() */
  216. /*+
  217. -*/
  218. /*************************************************************************/
  219.  
  220. void
  221. /*FCN*/main(argc, argv)
  222.   int             argc;
  223.   char           *argv[];
  224. {
  225.     int             stat, cindex;
  226.     short           scode = 1;
  227.  
  228.     ads_init(argc, argv);
  229.  
  230.     while (TRUE) {
  231.         if ((stat = ads_link(scode)) < 0) {
  232.             printf(/*MSG7*/"DESIGN: bad status from ads_link() = %d\n",
  233.                    stat);
  234.             fflush(stdout);
  235.             ads_exit(1);
  236.         }
  237.         scode = -RSRSLT;
  238.  
  239.         switch (stat) {
  240.  
  241.         case RQXLOAD:                 /* Load & register functions */
  242.             scode = -(funcload() ? RSRSLT : RSERR);
  243.             scode = -RSRSLT;
  244.             print_new_command_set();
  245.             break;
  246.  
  247.         case RQSUBR:                  /* Evaluate external lisp function */
  248.             cindex = ads_getfuncode();
  249.             (*cmdtab[cindex].cmdfunc) ();
  250.             break;
  251.  
  252.         case RQXUNLD:                 /* Unloading */
  253.             ads_printf (/*MSG8*/"Unloading: ");
  254.             break;
  255.  
  256.         case RQSAVE:                  /* AutoCAD SAVE notification */
  257.             break;
  258.  
  259.         case RQQUIT:                  /* AutoCAD QUIT notification */
  260.             break;
  261.  
  262.         case RQEND:                   /* AutoCAD END notification */
  263.             break;
  264.  
  265.         default:
  266.             break;
  267.  
  268.         }
  269.  
  270.     }
  271. }
  272.  
  273. /*************************************************************************/
  274. /* .doc funcload() */
  275. /*+
  276.    Load external functions into AutoCAD system
  277. -*/
  278. /*************************************************************************/
  279.  
  280. static int 
  281. /*FCN*/funcload()
  282.  
  283. {
  284.     int             i;
  285.  
  286.     for (i = 0; i < ELEMENTS(cmdtab); i++) {
  287.         if(! ads_defun (cmdtab[i].cmdname , i))
  288.             return  RTERROR;
  289.     }
  290.     return RTNORM;
  291. }
  292.  
  293. /*************************************************************************/
  294. /* .doc print_new_command_set() */
  295. /*+
  296.    Print new commands on the screen when the program is loaded
  297. -*/
  298. /*************************************************************************/
  299.  
  300. static  void
  301. /*FCN*/print_new_command_set()
  302. {
  303.     ads_printf(/*MSG9*/"\nNew loaded commands:");
  304.     ads_printf(/*MSG10*/"\nSOLSHAFT, SOLWHEEL, SOLGEAR, ");
  305.     ads_printf(/*MSG11*/"SOLBEAR, SOLBOLT, SOLNUT\n");
  306. }
  307.  
  308. /*************************************************************************/
  309. /* .doc create_shaft_func() */
  310. /*+
  311.    This function executes SOLSHAFT command.
  312. -*/
  313. /*************************************************************************/
  314.  
  315. static void
  316. /*FCN*/create_shaft_func ()
  317.  
  318. {
  319.     ap_Real  shaft_d, shaft_l, key_d, key_w, key_l;
  320.     ap_Real  radius, block_l, block_w, block_h, tx, ty, tz;
  321.     ap_Trans3d  matrix, mat;
  322.     ap_Objid  Block, Cyl, Shaft;
  323.     int stat;
  324.  
  325.     /* Initialize API */
  326.  
  327.     stat = ap_init();
  328.     if (stat != AP_NORMAL)
  329.         goto Error;
  330.  
  331.     /* Prompt user for shaft data */
  332.  
  333.     stat = get_shaft_data(&shaft_d, &shaft_l, &key_d, &key_w, &key_l, mat);
  334.     if (stat == FALSE)
  335.         goto Error;
  336.  
  337.     /* Create a cylindrical shaft with specified size */
  338.  
  339.     radius = shaft_d / 2.0;
  340.     stat = ap_cylinder (radius, radius, shaft_l, &Cyl);
  341.  
  342.     /* Verify whether cylinder has been created successfully */
  343.     if (stat != AP_NORMAL) {
  344.         ads_printf(/*MSG12*/"\nUnable to create cylinder.");
  345.         goto Error;
  346.     }
  347.  
  348.     /* Create a block of keyway size */
  349.  
  350.     block_l = 2.0 * key_d;
  351.     block_w = key_w;
  352.     block_h = 2.0 * key_l;
  353.     stat = ap_box (block_l, block_w, block_h, &Block);
  354.     if (stat != AP_NORMAL) {
  355.         ads_printf(/*MSG13*/"\nUnable to create a box.");
  356.         goto Error;
  357.     }
  358.  
  359.     /* Setup translation matrix */
  360.  
  361.     tx = radius - key_d;
  362.     ty = - key_w / 2.0;
  363.     tz = - key_l;
  364.     ap_translate (tx, ty, tz, matrix);
  365.  
  366.     /* Move Block to proper position */
  367.  
  368.     ap_move_obj (Block, matrix, TRUE);
  369.  
  370.     /* Subtract Block from Cylinder to create a keyway */
  371.  
  372.     stat = ap_subtract (Cyl, Block, &Shaft);
  373.  
  374.     if (stat != AP_NORMAL) {
  375.         ads_printf(/*MSG14*/"\nUnable to subtract solid.\n");
  376.         goto Error;
  377.     }
  378.  
  379.     /* Move shaft to UCS */
  380.  
  381.     ap_move_obj (Shaft, mat, FALSE);
  382.  
  383.     /* Display the shaft on the screen */
  384.  
  385.     ap_post_obj (Shaft, AP_POSTWIRE);
  386.  
  387. Error:
  388.     ads_retvoid();
  389.     return;
  390. }
  391.  
  392. /*************************************************************************/
  393. /* .doc get_shaft_data() */
  394. /*+
  395.    This routine prompts the user to enter shaft data.
  396. -*/
  397. /*************************************************************************/
  398. static ap_Bool
  399. /*FCN*/get_shaft_data (dia, len, keyd, keyw, keyl, mat)
  400.   ads_real  *dia, *len, *keyd, *keyw, *keyl;
  401.   ap_Trans3d  mat;
  402. {
  403.     int  stat;
  404.     ads_real  temp, keyw_max;
  405.     ads_point pt, pd;
  406.     ap_Trans3d  mat1, mat2;
  407.  
  408.     /* Initialization of shaft data for default input */
  409.  
  410.     pt[X] = 0.0;
  411.     pt[Y] = 0.0;
  412.     pt[Z] = 0.0;
  413.     *dia = 1.0;
  414.     *len = 5.0;
  415.     *keyd = 0.3;
  416.     *keyw = 0.4;
  417.     *keyl = 2.0;
  418.  
  419.  
  420.     /* Acquire values of design parameters associated with shaft  
  421.        from the user and verify the validity of input data */
  422.  
  423.     stat = ads_getpoint (NULL, /*MSG15*/"\nInsertion base point <0,0,0>: ", pt);
  424.     if (stat == RTCAN) {
  425.         return FALSE;
  426.     }
  427.  
  428.     stat = ads_getreal (/*MSG16*/"\nEnter shaft diameter <1.0>: ", dia);
  429.     if (stat == RTCAN) {
  430.         return FALSE;
  431.     } else if (*dia <= 0.0) {
  432.         ads_printf(/*MSG17*/"\nValue must be positive and nonzero.");
  433.         return FALSE;
  434.     }
  435.  
  436.     stat = ads_getreal (/*MSG18*/"\nEnter shaft length <5.0>: ", len);
  437.     if (stat == RTCAN) {
  438.         return FALSE;
  439.     } else if (*len <= 0.0) {
  440.         ads_printf(/*MSG19*/"\nValue must be positive and nonzero.");
  441.         return FALSE;
  442.     }
  443.  
  444.     stat = ads_getreal (/*MSG20*/"\nEnter keyway depth <0.3>: ", keyd);
  445.     if (stat == RTCAN) {
  446.         return FALSE;
  447.     } else if (*keyd <= 0.0) {
  448.         ads_printf(/*MSG21*/"\nValue must be positive and nonzero.");
  449.         return FALSE;
  450.     } else if (*keyd >= *dia) {
  451.         ads_printf(/*MSG22*/"\nValue must be less than shaft's diameter.");
  452.         return FALSE;
  453.     }
  454.  
  455.     temp = (*dia)*(*keyd) - (*keyd)*(*keyd);
  456.     keyw_max = 2.0 * sqrt(temp);
  457.     stat = ads_getreal (/*MSG23*/"\nEnter keyway width <0.4>: ", keyw);
  458.     if (stat == RTCAN) {
  459.         return FALSE;
  460.     } else if (*keyw <= 0.0) {
  461.         ads_printf(/*MSG24*/"\nValue must be positive and nonzero.");
  462.         return FALSE;
  463.     } else if (*keyw >= keyw_max) {
  464.         ads_printf(/*MSG25*/"\nValue must be less than %f.", keyw_max);
  465.         return FALSE;
  466.     }
  467.  
  468.     stat = ads_getreal (/*MSG26*/"\nEnter keyway length <2.0>: ", keyl);
  469.     if (stat == RTCAN) {
  470.         return FALSE;
  471.     } else if (*keyl <= 0.0) {
  472.         ads_printf(/*MSG27*/"\nValue must be positive and nonzero.");
  473.         return FALSE;
  474.     } else if (*keyl >= *len) {
  475.         ads_printf(/*MSG28*/"\nValue must be less than shaft's length.");
  476.         return FALSE;
  477.     }
  478.  
  479.     stat = ap_get_ucsmat(mat1);
  480.     if (stat != AP_NORMAL)
  481.         return FALSE;
  482.     trans_uc2wc(pt, TRUE, pd);
  483.     stat = ap_translate (pd[X], pd[Y], pd[Z], mat2);
  484.     if (stat != AP_NORMAL)
  485.         return FALSE;
  486.     stat = ap_compose(mat2, mat1, mat);
  487.     if (stat != AP_NORMAL)
  488.         return FALSE;
  489.  
  490.     return TRUE;
  491. }
  492.  
  493. /*************************************************************************/
  494. /* .doc create_wheel_func() */
  495. /*+
  496.    This function executes SOLWHEEL command.
  497. -*/
  498. /*************************************************************************/
  499.  
  500. static void
  501. /*FCN*/create_wheel_func ()
  502. {
  503.     ap_Real  wheel_d, wheel_b, hub_d, hub_t, hole_d, key_d, key_w;
  504.     ap_Real  radius, block_l, block_w, block_b, tx, ty, tz;
  505.     ap_Real  hub_b, hole_b;
  506.     ap_Trans3d  matrix, mat;
  507.     ap_Objid Block, Cyl[3], Temp1, Temp2, Hole, Wheel;
  508.     int  stat;
  509.  
  510.     /* Initialize API */
  511.  
  512.     stat = ap_init();
  513.     if (stat != AP_NORMAL)
  514.         goto Error;
  515.  
  516.     /* Prompt user for wheel data */
  517.  
  518.     stat = get_wheel_data(&wheel_d, &wheel_b, &hub_d, &hub_t,
  519.                           &hole_d, &key_d, &key_w, mat);
  520.     if (stat == FALSE)
  521.         goto Error;
  522.  
  523.     /* Create a cylindrical wheel of specified size */
  524.  
  525.     radius = wheel_d / 2.0;
  526.     stat = ap_cylinder (radius, radius, wheel_b, &Cyl[0]);
  527.     if (stat != AP_NORMAL) {
  528.         ads_printf(/*MSG29*/"\nUnable to create solid.\n");
  529.         goto Error;
  530.     }
  531.  
  532.     /* Move the cylinder down along z-axis and  
  533.        make it symmetric with respect to xy-plane */
  534.  
  535.     tx = 0.0;
  536.     ty = 0.0;
  537.     tz = - wheel_b / 2.0;
  538.     ap_translate (tx, ty, tz, matrix);
  539.     ap_move_obj (Cyl[0], matrix, TRUE);
  540.  
  541.     /* Create a cylindrical hub of specified size */
  542.  
  543.     radius = hub_d / 2.0;
  544.     hub_b = wheel_b + 2.0 * hub_t;
  545.     stat = ap_cylinder (radius, radius, hub_b, &Cyl[1]);
  546.     if (stat != AP_NORMAL) {
  547.         ads_printf(/*MSG30*/"\nUnable to create cylinder.\n");
  548.         goto Error;
  549.     }
  550.  
  551.     /* Move the cylinder down along z-axis and  
  552.        make it symmetric with respect to xy-plane */
  553.  
  554.     tx = 0.0;
  555.     ty = 0.0;
  556.     tz = - hub_b / 2.0;
  557.     ap_translate (tx, ty, tz, matrix);
  558.     ap_move_obj (Cyl[1], matrix, TRUE);
  559.  
  560.     /* Define a NULL solid to terminate array Cyl[] */
  561.  
  562.     Cyl[2] = (ap_Objid) NULL;
  563.  
  564.     /* Join wheel stored in Cyl[0]) and hub stored in Cyl[1] together */
  565.  
  566.     stat = ap_union (Cyl, &Temp1);
  567.     if (stat != AP_NORMAL) {
  568.         ads_printf(/*MSG31*/"\nUnable to perform union on solids.\n");
  569.         goto Error;
  570.     }
  571.  
  572.     /* Create a cylinder of the same size as the hole */
  573.  
  574.     radius = hole_d / 2.0;
  575.     hole_b = 2.0 * hub_b;
  576.     stat = ap_cylinder (radius, radius, hole_b, &Hole);
  577.     if (stat != AP_NORMAL) {
  578.         ads_printf(/*MSG32*/"\nUnable to create cylinder.\n");
  579.         goto Error;
  580.     }
  581.  
  582.     /* Move the cylinder down along z-axis and  
  583.         make it symmetric with respect to xy-plane */
  584.  
  585.     tx = 0.0;
  586.     ty = 0.0;
  587.     tz = - hole_b / 2.0;
  588.     ap_translate (tx, ty, tz, matrix);
  589.     ap_move_obj (Hole, matrix, TRUE);
  590.  
  591.     /* Subtract cylinder from wheel to produce a hole */
  592.  
  593.     stat = ap_subtract (Temp1, Hole, &Temp2);
  594.     if (stat != AP_NORMAL) {
  595.         ads_printf(/*MSG33*/"\nUnable to subtract solids.\n");
  596.         goto Error;
  597.     }
  598.  
  599.     /* Create a block of keyway size */
  600.  
  601.     block_l = (hole_d/2.0) +  key_d;
  602.     block_w = key_w;
  603.     block_b = 2.0 * hub_b;
  604.     stat = ap_box (block_l, block_w, block_b, &Block);
  605.     if (stat != AP_NORMAL) {
  606.         ads_printf(/*MSG34*/"\nUnable to create solid.\n");
  607.         goto Error;
  608.     }
  609.  
  610.     /* Move the block to proper position */
  611.  
  612.     tx = 0.0;
  613.     ty = - key_w / 2.0;
  614.     tz = - hub_b;
  615.     ap_translate (tx, ty, tz, matrix);
  616.     ap_move_obj (Block, matrix, TRUE);
  617.  
  618.     /* Subtract block from wheel to produce a keyway */
  619.  
  620.     stat = ap_subtract (Temp2, Block, &Wheel);
  621.     if (stat != AP_NORMAL) {
  622.         ads_printf(/*MSG35*/"\nUnable to subtract solids.\n");
  623.         goto Error;
  624.     }
  625.  
  626.     /* Move wheel to UCS */
  627.  
  628.     ap_move_obj (Wheel, mat, FALSE);
  629.  
  630.     /* Display the wheel on the screen */
  631.  
  632.     ap_post_obj (Wheel, AP_POSTWIRE);
  633.  
  634. Error:
  635.     ads_retvoid();
  636.     return;
  637. }
  638.  
  639. /*************************************************************************/
  640. /* .doc get_wheel_data() */
  641. /*+
  642.    This routine prompts the user to enter wheel data.
  643. -*/
  644. /*************************************************************************/
  645. static ap_Bool
  646. /*FCN*/get_wheel_data (wheeld, wheelb, hubd, hubt, holed, keyd, keyw, mat)
  647.   ads_real  *wheeld, *wheelb, *hubd, *hubt, *holed, *keyd, *keyw;
  648.   ap_Trans3d  mat;
  649. {
  650.     int  stat;
  651.     ads_real  keyw_max, temp1, temp2;
  652.     ads_point  pt, pd;
  653.     ap_Trans3d  mat1, mat2;
  654.  
  655.     /* Initialization of wheel data for default input */
  656.  
  657.     pt[X] = 0.0;
  658.     pt[Y] = 0.0;
  659.     pt[Z] = 0.0;
  660.     *wheeld = 5.0;
  661.     *wheelb = 1.0;
  662.     *hubd   = 3.0;
  663.     *hubt   = 0.25;
  664.     *holed  = 1.0;
  665.     *keyd   = 0.2;
  666.     *keyw   = 0.4;
  667.  
  668.     /* Acquire values of design parameters associated with wheel  
  669.        from the user and verify the validity of input data */
  670.  
  671.     stat = ads_getpoint (NULL, /*MSG36*/"\nInsertion base point <0,0,0>: ", pt);
  672.     if (stat == RTCAN) {
  673.         return FALSE;
  674.     }
  675.  
  676.     stat = ads_getreal (/*MSG37*/"\nEnter wheel diameter <5.0>: ", wheeld);
  677.     if (stat == RTCAN) {
  678.         return FALSE;
  679.     } else if (*wheeld <= 0.0) {      /* verify positive value */
  680.         ads_printf(/*MSG38*/"\nValue must be positive and nonzero.");
  681.         return FALSE;
  682.     }
  683.  
  684.     stat = ads_getreal (/*MSG39*/"\nEnter wheel thickness <1.0>: ", wheelb);
  685.     if (stat == RTCAN) {
  686.         return FALSE;
  687.     } else if (*wheelb <= 0.0) {
  688.         ads_printf(/*MSG40*/"\nValue must be positive and nonzero.");
  689.         return FALSE;
  690.     }
  691.  
  692.     stat = ads_getreal (/*MSG41*/"\nEnter hub diameter <3.0>: ", hubd);
  693.     if (stat == RTCAN) {
  694.         return FALSE;
  695.     } else if (*hubd <= 0.0) {
  696.         ads_printf(/*MSG42*/"\nValue must be positive and nonzero.");
  697.         return FALSE;
  698.     } else if (*hubd >= *wheeld) {
  699.         ads_printf(/*MSG43*/"\nValue must be less than wheel's diameter.");
  700.         return FALSE;
  701.     }
  702.  
  703.     stat = ads_getreal (/*MSG44*/"\nEnter hub extrusion thickness <0.25>: ", hubt);
  704.     if (stat == RTCAN) {
  705.         return FALSE;
  706.     } else if (*hubt <= 0.0) {
  707.         ads_printf(/*MSG45*/"\nValue must be positive and nonzero.");
  708.         return FALSE;
  709.     } else if (*hubt >= *wheeld) {
  710.         ads_printf(/*MSG46*/"\nValue must be less than wheel's diameter.");
  711.         return FALSE;
  712.     }
  713.  
  714.     stat = ads_getreal (/*MSG47*/"\nEnter hole diameter <1.0>: ", holed);
  715.     if (stat == RTCAN) {
  716.         return FALSE;
  717.     } else if (*holed <= 0.0) {
  718.         ads_printf(/*MSG48*/"\nValue must be positive and nonzero.");
  719.         return FALSE;
  720.     } else if (*holed >= *hubd) {
  721.         ads_printf(/*MSG49*/"\nValue must be less than hub's diameter.");
  722.         return FALSE;
  723.     }
  724.  
  725.     stat = ads_getreal (/*MSG50*/"\nEnter keyway depth <0.2>: ", keyd);
  726.     if (stat == RTCAN) {
  727.         return FALSE;
  728.     } else if (*keyd <= 0.0) {
  729.         ads_printf(/*MSG51*/"\nValue must be positive and nonzero.");
  730.         return FALSE;
  731.     } else if (*keyd >= (*hubd-*holed)/2.0) {
  732.         ads_printf
  733.     (/*MSG52*/"\nValue must be less than hub's radius minus hole's radius.");
  734.         return FALSE;
  735.     }
  736.  
  737.     temp1 = (*holed/2.0) + (*keyd);
  738.     temp2 = (*hubd/2.0)*(*hubd/2.0) - (temp1)*(temp1);
  739.     keyw_max = 2.0 * sqrt(temp2);      
  740.     stat = ads_getreal (/*MSG53*/"\nEnter keyway width <0.4>: ", keyw);
  741.     if (stat == RTCAN) {
  742.         return FALSE;
  743.     } else if (*keyw <= 0.0) {
  744.         ads_printf(/*MSG54*/"\nValue must be positive and nonzero.");
  745.         return FALSE;
  746.     } else if (*keyw > *holed) {
  747.         ads_printf(/*MSG55*/"\nValue must be less than hole's diameter.");
  748.         return FALSE;
  749.     } else if (*keyw >= keyw_max) {
  750.         ads_printf(/*MSG56*/"\nValue must be less than %f.", keyw_max);
  751.         return FALSE;
  752.     }
  753.  
  754.     stat = ap_get_ucsmat(mat1);
  755.     if (stat != AP_NORMAL)
  756.         return FALSE;
  757.     trans_uc2wc(pt, TRUE, pd);
  758.     stat = ap_translate (pd[X], pd[Y], pd[Z], mat2);
  759.     if (stat != AP_NORMAL)
  760.         return FALSE;
  761.     stat = ap_compose(mat2, mat1, mat);
  762.     if (stat != AP_NORMAL)
  763.         return FALSE;
  764.     return TRUE;
  765. }
  766.  
  767. /*************************************************************************/
  768. /* .doc create_gear_func() */
  769. /*+
  770.    This function executes SOLGEAR command.
  771. -*/
  772. /*************************************************************************/
  773.  
  774. static void
  775. /*FCN*/create_gear_func ()
  776. {
  777.     ap_Real  gear_d, gear_b, alpha;
  778.     int  number_t, np, stat;
  779.     ap_Objid Gear;
  780.     ap_Swp_pts  pts[501];
  781.     ap_Trans3d  mat;
  782.  
  783.  
  784.     /* Initialize API */
  785.  
  786.     stat = ap_init();
  787.     if (stat != AP_NORMAL)
  788.         goto Error;
  789.  
  790.     /* Prompt user for gear data */
  791.  
  792.     stat = get_gear_data(&gear_d, &gear_b, &number_t, &alpha, mat);
  793.     if (stat == FALSE)
  794.         goto Error;
  795.  
  796.     stat = define_gear_pline(gear_d, number_t, alpha, pts, &np);
  797.     if (stat == FALSE)
  798.         goto Error;
  799.  
  800.     ads_printf (/*MSG57*/"\n\nWorking...");
  801.  
  802.     /* Extrude gear profile to obtain 3D gear model */
  803.  
  804.     stat = ap_extrude_pline(np, pts, gear_b, 0.0, &Gear);
  805.     if (stat != AP_NORMAL) {
  806.         ads_printf(/*MSG58*/"\nUnable to generate extruded solids.\n");
  807.         goto Error;
  808.     }
  809.  
  810.     /* Move gear to UCS */
  811.  
  812.     ap_move_obj (Gear, mat, FALSE);
  813.  
  814.     /* Display gear on the screen */
  815.  
  816.     ap_post_obj (Gear, AP_POSTWIRE);
  817.  
  818. Error:
  819.     ads_retvoid();
  820.     return;
  821. }
  822.  
  823. /*************************************************************************/
  824. /* .doc get_gear_data() */
  825. /*+
  826.    This routine prompts the user to enter gear data.
  827. -*/
  828. /*************************************************************************/
  829. static ap_Bool
  830. /*FCN*/get_gear_data (dia, thick, nteeth, pangle, mat)
  831.   ads_real  *dia, *thick, *pangle;
  832.   int  *nteeth;
  833.   ap_Trans3d  mat;
  834. {
  835.     int  stat;
  836.     ads_point pt, pd;
  837.     ap_Trans3d  mat1, mat2;
  838.  
  839.     /* Initialization of gear data for default input */
  840.  
  841.     pt[X] = 0.0;
  842.     pt[Y] = 0.0;
  843.     pt[Z] = 0.0;
  844.     *dia = 4.0;
  845.     *thick = 1.0;
  846.     *nteeth = 12;
  847.     *pangle = 25.0;
  848.  
  849.     /* Acquire values of design parameters associated with gear  
  850.        from the user and verify the validity of input data */
  851.  
  852.     stat = ads_getpoint (NULL, /*MSG59*/"\nInsertion base point <0,0,0>: ", pt);
  853.     if (stat == RTCAN) {
  854.         return FALSE;
  855.     }
  856.  
  857.     stat = ads_getreal (/*MSG60*/"\nEnter pitch circle diameter <4.0>: ", dia);
  858.     if (stat == RTCAN) {
  859.         return FALSE;
  860.     } else if (*dia <= 0.0) {
  861.         ads_printf(/*MSG61*/"\nValue must be positive and nonzero.");
  862.         return FALSE;
  863.     }
  864.  
  865.     stat = ads_getint (/*MSG62*/"\nEnter number of teeth <12>: ", nteeth);
  866.     if (stat == RTCAN) {
  867.         return FALSE;
  868.     } else if (*nteeth <= 3) {
  869.         ads_printf(/*MSG63*/"\nCan not handle less than 4 teeth.");
  870.         return FALSE;
  871.     } else if (*nteeth >= 37) {
  872.         ads_printf(/*MSG64*/"\nCan not handle more than 36 teeth.");
  873.         return FALSE;
  874.     }
  875.  
  876.     stat = ads_getreal (/*MSG65*/"\nEnter gear thickness <1.0>: ", thick);
  877.     if (stat == RTCAN) {
  878.         return FALSE;
  879.     } else if (*thick <= 0.0) {
  880.         ads_printf(/*MSG66*/"\nValue must be positive and nonzero.");
  881.         return FALSE;
  882.     }
  883.  
  884.     stat = ads_getreal (/*MSG67*/"\nEnter pressure angle <25 degrees>: ", pangle);
  885.     if (stat == RTCAN) {
  886.         return FALSE;
  887.     } else if (*pangle < 14.5) {
  888.         ads_printf
  889.         (/*MSG68*/"\nAngle must be greater or equal to 14.5 degrees.");
  890.         return FALSE;
  891.     } else if (*pangle > 25.0) {
  892.         ads_printf(/*MSG69*/"\nAngle must be less or equal to 25 degrees.");
  893.         return FALSE;
  894.     }
  895.  
  896.     stat = ap_get_ucsmat(mat1);
  897.     if (stat != AP_NORMAL)
  898.         return FALSE;
  899.     trans_uc2wc(pt, TRUE, pd);
  900.     stat = ap_translate (pd[X], pd[Y], pd[Z], mat2);
  901.     if (stat != AP_NORMAL)
  902.         return FALSE;
  903.     stat = ap_compose(mat2, mat1, mat);
  904.     if (stat != AP_NORMAL)
  905.         return FALSE;
  906.     return TRUE;
  907. }
  908.  
  909. /*************************************************************************/
  910. /* .doc define_gear_pline() */
  911. /*+
  912.    This routine computes the gear profile based on the input 
  913.    arguments gear_d (pitch diameter), number_t (number of teeth)
  914.    and alpha (pressure angle). It returns a polyline vertex array pts
  915.    and the total number of vertices npoint contained in the polyline.
  916.    The routine first generates an involute tooth, then rotates and
  917.    copies the tooth to obtain a complete gear profile. The gear
  918.    profile is defined in the xy plane and centered at the origin.
  919. -*/
  920. /*************************************************************************/
  921.  
  922. static ap_Bool
  923. /*FCN*/define_gear_pline (gear_d, number_t, alpha, pts, npoint)
  924.   ap_Real  gear_d, alpha;
  925.   ap_Swp_pts  pts[];
  926.   int      number_t, *npoint;
  927. {
  928.     ap_Real  angle_a, angle_b, angle_c, angle_d, angle_e, angle_f;
  929.     ap_Real  angle_h, angle_i, angle_j, angle_k;
  930.     ap_Real  angle_rot, cos_rot, sin_rot, omega, phi, temp;
  931.     ap_Real  rad_pitch, rad_base, rad_adden, rad_deden;
  932.     int  i, j, k, nt;
  933.  
  934.     if((gear_d <= 0.0) || (number_t <= 2))
  935.         return FALSE;
  936.  
  937.     nt = 10 * number_t + 1;
  938.     phi = alpha * PI / 180;
  939.  
  940.     /* Define radius for pitch circle */
  941.  
  942.     rad_pitch = gear_d / 2;
  943.  
  944.     /* Define radius for base circle */
  945.  
  946.     rad_base = rad_pitch * cos (phi);
  947.  
  948.     /* Define radius for addendum circle */
  949.  
  950.     rad_adden = rad_pitch + gear_d / number_t;
  951.  
  952.     /* Define radius for dedendum circle */
  953.  
  954.     rad_deden = rad_pitch - 1.25 * gear_d / number_t;
  955.  
  956.     if (rad_deden > rad_base)
  957.         rad_deden = 0.99 * rad_base;
  958.     temp = rad_adden * rad_adden / (rad_base * rad_base) - 1;
  959.     omega = sqrt (temp);
  960.  
  961.     /* Define angles for construction of the tooth profile */
  962.  
  963.     angle_i = PI/ (2 * number_t);
  964.     angle_j = angle_i + tan (phi) - phi;
  965.     angle_k = angle_j;
  966.     angle_h = angle_j - omega + atan (omega);
  967.     angle_a = angle_j - 2 * PI / number_t;
  968.     angle_b = (angle_a - angle_j) / 2;
  969.     angle_c = - angle_k;
  970.     angle_d = - angle_j;
  971.     angle_e = - angle_i;
  972.     angle_f = - angle_h;
  973.  
  974.     /* Define the coordinates of the polyline vertices 
  975.            for one tooth profile consisting of line
  976.            and arc segments */
  977.  
  978.     pts[0].x = rad_deden * cos (angle_a);
  979.     pts[0].y = rad_deden * sin (angle_a);
  980.     pts[0].type = AP_PT_LINE;
  981.  
  982.     pts[1].x = rad_deden * cos (angle_b);
  983.     pts[1].y = rad_deden * sin (angle_b);
  984.     pts[1].type = AP_PT_LINE;
  985.  
  986.     pts[2].x = rad_deden * cos (angle_c);
  987.     pts[2].y = rad_deden * sin (angle_c);
  988.     pts[2].type = AP_PT_ARCEND;
  989.  
  990.     pts[3].x = rad_base * cos (angle_d);
  991.     pts[3].y = rad_base * sin (angle_d);
  992.     pts[3].type = AP_PT_LINE;
  993.  
  994.     pts[4].x = rad_pitch * cos (angle_e);
  995.     pts[4].y = rad_pitch * sin (angle_e);
  996.     pts[4].type = AP_PT_LINE;
  997.  
  998.     pts[5].x = rad_adden * cos (angle_f);
  999.     pts[5].y = rad_adden * sin (angle_f);
  1000.     pts[5].type = AP_PT_ARCEND;
  1001.  
  1002.     pts[6].x = rad_adden;
  1003.     pts[6].y = 0.0;
  1004.     pts[6].type = AP_PT_LINE;
  1005.  
  1006.     pts[7].x = pts[5].x;
  1007.     pts[7].y = -pts[5].y;
  1008.     pts[7].type = AP_PT_ARCEND;
  1009.  
  1010.     pts[8].x = pts[4].x;
  1011.     pts[8].y = -pts[4].y;
  1012.     pts[8].type = AP_PT_LINE;
  1013.  
  1014.     pts[9].x = pts[3].x;
  1015.     pts[9].y = -pts[3].y;
  1016.     pts[9].type = AP_PT_ARCEND;
  1017.  
  1018.     pts[10].x = pts[2].x;
  1019.     pts[10].y = -pts[2].y;
  1020.     pts[10].type = AP_PT_LINE;
  1021.  
  1022.     /* Rotate and copy one tooth profile to obtain
  1023.            a complete gear profile */
  1024.  
  1025.     for (i=1; i<number_t; i++) {
  1026.         angle_rot = i * 2 * PI / number_t;
  1027.         cos_rot = cos (angle_rot);
  1028.         sin_rot = sin (angle_rot);
  1029.  
  1030.         for (j=1; j<11; j++) {
  1031.             k = 10 * i + j;
  1032.             pts[k].x = cos_rot * pts[j].x - sin_rot * pts[j].y;
  1033.             pts[k].y = sin_rot * pts[j].x + cos_rot * pts[j].y;
  1034.             pts[k].type = pts[j].type;
  1035.         }
  1036.     }
  1037.  
  1038.     pts[nt-1].x = pts[0].x;
  1039.     pts[nt-1].y = pts[0].y;
  1040.     pts[nt-1].type = pts[0].type;
  1041.  
  1042.     *npoint = nt;
  1043.     return TRUE;
  1044. }
  1045.  
  1046. /*************************************************************************/
  1047. /* .doc create_bearing_func() */
  1048. /*+
  1049.    This function executes SOLBEAR command.
  1050. -*/
  1051. /*************************************************************************/
  1052.  
  1053. static void
  1054. /*FCN*/create_bearing_func ()
  1055. {
  1056.     ap_Real  bear_d, bear_b, hole_d, hole_h, base_h, base_w;
  1057.     ap_Real  radius, tx, ty, tz;
  1058.     ap_Trans3d  matrix, mat;
  1059.     ap_Objid Temp, Hole, Bear;
  1060.     ap_Swp_pts  pts[10];
  1061.     int      np, stat;
  1062.  
  1063.  
  1064.     /* Initialize API */
  1065.  
  1066.     stat = ap_init();
  1067.     if (stat != AP_NORMAL)
  1068.         goto Error;
  1069.  
  1070.     /* Prompt user for bearing data */
  1071.  
  1072.     stat = get_bearing_data(&bear_d, &bear_b, &hole_d, &hole_h,
  1073.                             &base_h, &base_w, mat);
  1074.     if (stat == FALSE)
  1075.         goto Error;
  1076.  
  1077.     /* Define a 2D sectional profile for extrusion */
  1078.  
  1079.     np = 10;
  1080.     pts[0].x = base_w / 2.0;
  1081.     pts[0].y = 0.0;
  1082.     pts[0].type = AP_PT_LINE;
  1083.  
  1084.     pts[1].x = base_w / 2.0;
  1085.     pts[1].y = base_h;
  1086.     pts[1].type = AP_PT_LINE;
  1087.  
  1088.     radius = bear_d / 2.0;
  1089.     pts[3].x = radius * sin (PI/6.0);
  1090.     pts[3].y = hole_h - radius * cos (PI/6.0);
  1091.     pts[3].type = AP_PT_LINE;
  1092.  
  1093.     pts[2].x = pts[3].x;
  1094.     pts[2].y = pts[1].y;
  1095.     pts[2].type = AP_PT_LINE;
  1096.  
  1097.     pts[4].x = 0.0;
  1098.     pts[4].y = hole_h + radius;
  1099.     pts[4].type = AP_PT_LINE;
  1100.  
  1101.     pts[5].x = - pts[3].x;
  1102.     pts[5].y = pts[3].y;
  1103.     pts[5].type = AP_PT_ARCEND;
  1104.  
  1105.     pts[6].x = pts[5].x;
  1106.     pts[6].y = base_h;
  1107.     pts[6].type = AP_PT_LINE;
  1108.  
  1109.     pts[7].x = - base_w / 2.0;
  1110.     pts[7].y = base_h;
  1111.     pts[7].type = AP_PT_LINE;
  1112.  
  1113.     pts[8].x = - base_w / 2.0;
  1114.     pts[8].y = 0.0;
  1115.     pts[8].type = AP_PT_LINE;
  1116.  
  1117.     pts[9].x = pts[0].x;
  1118.     pts[9].y = pts[0].y;
  1119.     pts[9].type = AP_PT_LINE;
  1120.  
  1121.     /* Extrude 2D sectional profile to create 3D bearing */
  1122.  
  1123.     stat = ap_extrude_pline(np, pts, bear_b, 0.0, &Temp);
  1124.     if (stat != AP_NORMAL) {
  1125.         ads_printf(/*MSG70*/"\nUnable to generate extruded solid.\n");
  1126.         goto Error;
  1127.     }
  1128.  
  1129.     /* Create a cylinder tool to drill the hole */
  1130.  
  1131.     radius = hole_d / 2.0;
  1132.     stat = ap_cylinder (radius, radius, bear_b, &Hole);
  1133.     if (stat != AP_NORMAL) {
  1134.         ads_printf(/*MSG71*/"\nUnable to create a cylinder.\n");
  1135.         goto Error;
  1136.     }
  1137.  
  1138.     /* Move cylinder to proper position */
  1139.  
  1140.     tx = 0.0;
  1141.     ty = hole_h;
  1142.     tz = 0.0;
  1143.     ap_translate (tx, ty, tz, matrix);
  1144.     ap_move_obj (Hole, matrix, TRUE);
  1145.  
  1146.     /* Subtract cylinder from bearing to create a hole 
  1147.        for houseing shaft */
  1148.  
  1149.     stat = ap_subtract (Temp, Hole, &Bear);
  1150.     if (stat != AP_NORMAL) {
  1151.         ads_printf(/*MSG72*/"\nUnable to subtract solids.\n");
  1152.         goto Error;
  1153.     }
  1154.  
  1155.     /* Move bearing to UCS */
  1156.  
  1157.     ap_move_obj (Bear, mat, FALSE);
  1158.  
  1159.     /* Display the bearing on the screen */
  1160.  
  1161.     ap_post_obj (Bear, AP_POSTWIRE);
  1162.  
  1163. Error:
  1164.     ads_retvoid();
  1165.     return;
  1166. }
  1167.  
  1168. /*************************************************************************/
  1169. /* .doc get_bearing_data() */
  1170. /*+
  1171.    This routine prompts the user to enter bearing data.
  1172. -*/
  1173. /*************************************************************************/
  1174. static ap_Bool
  1175. /*FCN*/get_bearing_data (beard, bearb, holed, holeh, baseh, basew,mat)
  1176.   ads_real  *beard, *bearb, *holed, *holeh, *baseh, *basew;
  1177.   ap_Trans3d  mat;
  1178. {
  1179.     int  stat;
  1180.     ads_real  baseh_max, basew_min;
  1181.     ads_point pt, pd;
  1182.     ap_Trans3d  mat1, mat2;
  1183.  
  1184.     /* Initialization of bearing data for default input */
  1185.  
  1186.     pt[X] = 0.0;
  1187.     pt[Y] = 0.0;
  1188.     pt[Z] = 0.0;
  1189.     *beard = 5.0;
  1190.     *bearb = 3.0;
  1191.     *holed  = 2.0;
  1192.     *holeh  = 5.0;
  1193.     *baseh  = 1.0;
  1194.     *basew  = 6.0;
  1195.  
  1196.     /* Acquire values of design parameters associated with bearing  
  1197.        from the user and verify the validity of input data */
  1198.  
  1199.     stat = ads_getpoint (NULL, /*MSG73*/"\nInsertion base point <0,0,0>: ", pt);
  1200.     if (stat == RTCAN) {
  1201.         return FALSE;
  1202.     }
  1203.     stat = ads_getreal (/*MSG74*/"\nEnter bearing diameter <5.0>: ", beard);
  1204.     if (stat == RTCAN) {
  1205.         return FALSE;
  1206.     } else if (*beard <= 0.0) {
  1207.         ads_printf(/*MSG75*/"\nValue must be positive and nonzero.");
  1208.         return FALSE;
  1209.     }
  1210.  
  1211.     stat = ads_getreal (/*MSG76*/"\nEnter bearing thickness <3.0>: ", bearb);
  1212.     if (stat == RTCAN) {
  1213.         return FALSE;
  1214.     } else if (*bearb <= 0.0) {
  1215.         ads_printf(/*MSG77*/"\nValue must be positive and nonzero.");
  1216.         return FALSE;
  1217.     }
  1218.  
  1219.     stat = ads_getreal (/*MSG78*/"\nEnter hole diameter <2.0>: ", holed);
  1220.     if (stat == RTCAN) {
  1221.         return FALSE;
  1222.     } else if (*holed <= 0.0) {
  1223.         ads_printf(/*MSG79*/"\nValue must be positive and nonzero.");
  1224.         return FALSE;
  1225.     } else if (*holed >= *beard) {
  1226.         ads_printf(/*MSG80*/"\nHole diameter must be less than bearing diameter.");
  1227.         return FALSE;
  1228.     }
  1229.  
  1230.     stat = ads_getreal 
  1231.     (/*MSG81*/"\nEnter distance from base to center of hole <5.0>: ", holeh);
  1232.     if (stat == RTCAN) {
  1233.         return FALSE;
  1234.     } else if (*holeh <= (*beard/2.0)) {
  1235.         ads_printf(/*MSG82*/"\nValue must be greater than bearing's radius.");
  1236.         return FALSE;
  1237.     }
  1238.  
  1239.     baseh_max = *holeh - (*beard/2.0) * cos(PI/6.0);
  1240.     stat = ads_getreal (/*MSG83*/"\nEnter base height <1.0>: ", baseh);
  1241.     if (stat == RTCAN) {
  1242.         return FALSE;
  1243.     } else if (*baseh <= 0.0) {
  1244.         ads_printf(/*MSG84*/"\nValue must be positive and nonzero.");
  1245.         return FALSE;
  1246.     } else if (*baseh >= baseh_max) {
  1247.         ads_printf(/*MSG85*/"\nValue must be less than %f.", baseh_max);
  1248.         return FALSE;
  1249.     }
  1250.  
  1251.     basew_min = (*beard) * sin(PI/6.0);
  1252.     stat = ads_getreal (/*MSG86*/"\nEnter base width <6.0>: ", basew);
  1253.     if (stat == RTCAN) {
  1254.         return FALSE;
  1255.     } else if (*basew <= basew_min) {
  1256.         ads_printf(/*MSG87*/"\nValue must be greater than %f.", basew_min);
  1257.         return FALSE;
  1258.     }
  1259.  
  1260.     stat = ap_get_ucsmat(mat1);
  1261.     if (stat != AP_NORMAL)
  1262.         return FALSE;
  1263.     trans_uc2wc(pt, TRUE, pd);
  1264.     stat = ap_translate (pd[X], pd[Y], pd[Z], mat2);
  1265.     if (stat != AP_NORMAL)
  1266.         return FALSE;
  1267.     stat = ap_compose(mat2, mat1, mat);
  1268.     if (stat != AP_NORMAL)
  1269.         return FALSE;
  1270.     return TRUE;
  1271. }
  1272.  
  1273. /*************************************************************************/
  1274. /* .doc create_bolt_func() */
  1275. /*+
  1276.    This function executes SOLBOLT command.
  1277. -*/
  1278. /*************************************************************************/
  1279.  
  1280. static void
  1281. /*FCN*/create_bolt_func ()
  1282. {
  1283.     ap_Real  head_d, head_h, screw_d, screw_h;
  1284.     ap_Real  radius, length;
  1285.     ap_Objid Temp[3], Bolt;
  1286.     ap_Swp_pts  pts[10];
  1287.     ap_Trans3d  mat;
  1288.     int      np, stat;
  1289.  
  1290.  
  1291.     /* Initialize API */
  1292.  
  1293.     stat = ap_init();
  1294.     if (stat != AP_NORMAL)
  1295.         goto Error;
  1296.  
  1297.     /* Prompt user for bolt data */
  1298.  
  1299.     stat = get_bolt_data(&head_d, &head_h, &screw_d, &screw_h, mat);
  1300.     if (stat == FALSE)
  1301.         goto Error;
  1302.  
  1303.     /* Define a 2D six-sided polygon profile */
  1304.  
  1305.     radius = head_d / 2;
  1306.     define_hexagon_pline(radius, pts, &np);
  1307.  
  1308.     /* Extrude the profile to create bolt's head */
  1309.  
  1310.     stat = ap_extrude_pline(np, pts, head_h, 0.0, &Temp[0]);
  1311.     if (stat != AP_NORMAL) {
  1312.         ads_printf(/*MSG88*/"\nUnable to generate extruded solid.\n");
  1313.         goto Error;
  1314.     }
  1315.  
  1316.     /* Create a cylinder of the same size as bolt's shank */
  1317.  
  1318.     radius = screw_d / 2.0;
  1319.     length = screw_h + head_h;
  1320.     stat = ap_cylinder (radius, radius, length, &Temp[1]);
  1321.     if (stat != AP_NORMAL) {
  1322.         ads_printf(/*MSG89*/"\nUnable to create cylinder.\n");
  1323.         goto Error;
  1324.     }
  1325.  
  1326.     /* Define a NULL solid to terminate Temp[] array */
  1327.  
  1328.     Temp[2] = (ap_Objid)NULL;
  1329.  
  1330.     stat = ap_union (Temp, &Bolt);
  1331.     if (stat != AP_NORMAL) {
  1332.         ads_printf(/*MSG90*/"\nUnable to perform union on solids.\n");
  1333.         goto Error;
  1334.     }
  1335.  
  1336.     /* Move bolt to UCS */
  1337.  
  1338.     ap_move_obj (Bolt, mat, FALSE);
  1339.  
  1340.     /* Display the bolt on the screen */
  1341.  
  1342.     ap_post_obj (Bolt, AP_POSTWIRE);
  1343.  
  1344. Error:
  1345.     ads_retvoid();
  1346.     return;
  1347. }
  1348.  
  1349. /*************************************************************************/
  1350. /* .doc get_bolt_data() */
  1351. /*+
  1352.    This routine prompts the user to enter bolt data.
  1353. -*/
  1354. /*************************************************************************/
  1355. static ap_Bool
  1356. /*FCN*/get_bolt_data (headd, headh, screwd, screwh, mat)
  1357.   ads_real  *headd, *headh, *screwd, *screwh;
  1358.   ap_Trans3d  mat;
  1359. {
  1360.     int  stat;
  1361.     ads_real  screwd_max;
  1362.     ads_point pt, pd;
  1363.     ap_Trans3d  mat1, mat2;
  1364.  
  1365.     /* Initialization of wheel data for default input */
  1366.  
  1367.     pt[X] = 0.0;
  1368.     pt[Y] = 0.0;
  1369.     pt[Z] = 0.0;
  1370.     *headd  = 2.0;
  1371.     *headh  = 0.5;
  1372.     *screwd = 1.0;
  1373.     *screwh = 5.0;
  1374.  
  1375.     /* Acquire values of design parameters associated with bolt  
  1376.        from the user and verify the validity of input data */
  1377.  
  1378.     stat = ads_getpoint (NULL, /*MSG91*/"\nInsertion base point <0,0,0>: ", pt);
  1379.     if (stat == RTCAN) {
  1380.         return FALSE;
  1381.     }
  1382.     stat = ads_getreal (/*MSG92*/"\nEnter head diameter <2.0>: ", headd);
  1383.     if (stat == RTCAN) {
  1384.         return FALSE;
  1385.     } else if (*headd <= 0.0) {
  1386.         ads_printf(/*MSG93*/"\nValue must be positive and nonzero.");
  1387.         return FALSE;
  1388.     }
  1389.  
  1390.     stat = ads_getreal (/*MSG94*/"\nEnter head height <0.5>: ", headh);
  1391.     if (stat == RTCAN) {
  1392.         return FALSE;
  1393.     } else if (*headh <= 0.0) {
  1394.         ads_printf(/*MSG95*/"\nValue must be positive and nonzero.");
  1395.         return FALSE;
  1396.     }
  1397.  
  1398.     screwd_max = (*headd) * sin(60.0*PI/180.0);
  1399.     stat = ads_getreal (/*MSG96*/"\nEnter screw diameter <1.0>: ", screwd);
  1400.     if (stat == RTCAN) {
  1401.         return FALSE;
  1402.     } else if (*screwd <= 0.0) {
  1403.         ads_printf(/*MSG97*/"\nValue must be positive and nonzero.");
  1404.         return FALSE;
  1405.     } else if (*screwd >= screwd_max) {
  1406.         ads_printf(/*MSG98*/"\nValue must be less than %f.", screwd_max);
  1407.         return FALSE;
  1408.     }
  1409.  
  1410.     stat = ads_getreal (/*MSG99*/"\nEnter screw length <5.0>: ", screwh);
  1411.     if (stat == RTCAN) {
  1412.         return FALSE;
  1413.     } else if (*screwh <= 0.0) {
  1414.         ads_printf(/*MSG100*/"\nValue must be positive and nonzero.");
  1415.         return FALSE;
  1416.     }
  1417.  
  1418.     stat = ap_get_ucsmat(mat1);
  1419.     if (stat != AP_NORMAL)
  1420.         return FALSE;
  1421.     trans_uc2wc(pt, TRUE, pd);
  1422.     stat = ap_translate (pd[X], pd[Y], pd[Z], mat2);
  1423.     if (stat != AP_NORMAL)
  1424.         return FALSE;
  1425.     stat = ap_compose(mat2, mat1, mat);
  1426.     if (stat != AP_NORMAL)
  1427.         return FALSE;
  1428.     return TRUE;
  1429. }
  1430.  
  1431. /*************************************************************************/
  1432. /* .doc define_hexagon_pline() */
  1433. /*+
  1434.    This routine defines a regular six sides polygon.
  1435.    The polygon locates on xy plane and inscribes to a circle 
  1436.    of specified radius and centered at the origin.
  1437. -*/
  1438. /*************************************************************************/
  1439.  
  1440. static ap_Bool
  1441. /*FCN*/define_hexagon_pline (rad, pts, np)
  1442.   ap_Swp_pts  pts[];
  1443.   ads_real   rad;
  1444.   int  *np;
  1445. {
  1446.     rad = fabs(rad);
  1447.     if (rad < EPSILON) {
  1448.         ads_printf(/*MSG101*/"\nThe radius is too small.");
  1449.         return FALSE;
  1450.     }
  1451.     pts[0].x = rad;
  1452.     pts[0].y = 0.0;
  1453.     pts[0].type = AP_PT_LINE;
  1454.  
  1455.     pts[1].x = rad * cos (PI/3);
  1456.     pts[1].y = rad * sin (PI/3);
  1457.     pts[1].type = AP_PT_LINE;
  1458.  
  1459.     pts[2].x = rad * cos (2*PI/3);
  1460.     pts[2].y = rad * sin (2*PI/3);
  1461.     pts[2].type = AP_PT_LINE;
  1462.  
  1463.     pts[3].x = rad * cos (PI);
  1464.     pts[3].y = rad * sin (PI);
  1465.     pts[3].type = AP_PT_LINE;
  1466.  
  1467.     pts[4].x = rad * cos (4*PI/3);
  1468.     pts[4].y = rad * sin (4*PI/3);
  1469.     pts[4].type = AP_PT_LINE;
  1470.  
  1471.     pts[5].x = rad * cos (5*PI/3);
  1472.     pts[5].y = rad * sin (5*PI/3);
  1473.     pts[5].type = AP_PT_LINE;
  1474.  
  1475.     pts[6].x = pts[0].x;
  1476.     pts[6].y = pts[0].y;
  1477.     pts[6].type = AP_PT_LINE;
  1478.  
  1479.     *np = 7;
  1480.     return TRUE;
  1481. }
  1482.  
  1483. /*************************************************************************/
  1484. /* .doc create_nut_func() */
  1485. /*+
  1486.    This function executes SOLNUT command.
  1487. -*/
  1488. /*************************************************************************/
  1489.  
  1490. static void
  1491. /*FCN*/create_nut_func ()
  1492. {
  1493.     ap_Real  nut_d, nut_h, hole_d;
  1494.     ap_Real  radius;
  1495.     ap_Objid Temp1, Temp2, Nut;
  1496.     ap_Swp_pts  pts[10];
  1497.     ap_Trans3d  mat;
  1498.     int      np, stat;
  1499.  
  1500.  
  1501.     /* Initialize API */
  1502.  
  1503.     stat = ap_init();
  1504.     if (stat != AP_NORMAL)
  1505.         goto Error;
  1506.  
  1507.     /* Prompt user for nut data */
  1508.  
  1509.     stat = get_nut_data(&nut_d, &nut_h, &hole_d, mat);
  1510.     if (stat == FALSE)
  1511.         goto Error;
  1512.  
  1513.     /* Define a 2D six-sided polygon profile */
  1514.  
  1515.     radius = nut_d / 2;
  1516.     define_hexagon_pline(radius, pts, &np);
  1517.  
  1518.     /* Extrude the profile to create a nut */
  1519.  
  1520.     stat = ap_extrude_pline(np, pts, nut_h, 0.0, &Temp1);
  1521.     if (stat != AP_NORMAL) {
  1522.         ads_printf(/*MSG102*/"\nUnable to generate extruded solids.\n");
  1523.         goto Error;
  1524.     }
  1525.  
  1526.     /* Create a cylinder of the same size as the hole */
  1527.  
  1528.     radius = hole_d / 2.0;
  1529.     stat = ap_cylinder (radius, radius, nut_h, &Temp2);
  1530.     if (stat != AP_NORMAL) {
  1531.         ads_printf(/*MSG103*/"\nUnable to create solid.\n");
  1532.         goto Error;
  1533.     }
  1534.  
  1535.     /* Subtract cylinder from nut to produce a hole */
  1536.  
  1537.     stat = ap_subtract (Temp1, Temp2, &Nut);
  1538.     if (stat != AP_NORMAL) {
  1539.         ads_printf(/*MSG104*/"\nUnable to subtract solids.\n");
  1540.         goto Error;
  1541.     }
  1542.  
  1543.     /* Move nut to UCS */
  1544.  
  1545.     ap_move_obj (Nut, mat, FALSE);
  1546.  
  1547.     /* Display the solid */
  1548.  
  1549.     ap_post_obj (Nut, AP_POSTWIRE);
  1550.  
  1551. Error:
  1552.     ads_retvoid();
  1553.     return;
  1554. }
  1555.  
  1556. /*************************************************************************/
  1557. /* .doc get_nut_data() */
  1558. /*+
  1559.    This routine prompts the user to enter nut data.
  1560. -*/
  1561. /*************************************************************************/
  1562. static ap_Bool
  1563. /*FCN*/get_nut_data (nutd, nuth, holed, mat)
  1564.   ads_real  *nutd, *nuth, *holed;
  1565.   ap_Trans3d mat;
  1566. {
  1567.     int  stat;
  1568.     ads_real  holed_max;
  1569.     ads_point pt, pd;
  1570.     ap_Trans3d  mat1, mat2;
  1571.  
  1572.     /* Initialization of nut data for default input */
  1573.  
  1574.     pt[X] = 0.0;
  1575.     pt[Y] = 0.0;
  1576.     pt[Z] = 0.0;
  1577.     *nutd  = 2.0;
  1578.     *nuth  = 0.5;
  1579.     *holed = 1.0;
  1580.  
  1581.     /* Acquire values of design parameters associated with nut  
  1582.        from the user and verify the validity of input data */
  1583.  
  1584.     stat = ads_getpoint (NULL, /*MSG105*/"\nInsertion base point <0,0,0>: ", pt);
  1585.     if (stat == RTCAN) {
  1586.         return FALSE;
  1587.     }
  1588.     stat = ads_getreal (/*MSG106*/"\nEnter nut diameter <2.0>: ", nutd);
  1589.     if (stat == RTCAN) {
  1590.         return FALSE;
  1591.     } else if (*nutd <= 0.0) {
  1592.         ads_printf(/*MSG107*/"\nValue must be positive and nonzero.");
  1593.         return FALSE;
  1594.     }
  1595.  
  1596.     stat = ads_getreal (/*MSG108*/"\nEnter nut height <0.5>: ", nuth);
  1597.     if (stat == RTCAN) {
  1598.         return FALSE;
  1599.     } else if (*nuth <= 0.0) {
  1600.         ads_printf(/*MSG109*/"\nValue must be positive and nonzero.");
  1601.         return FALSE;
  1602.     }
  1603.  
  1604.     holed_max = (*nutd) * sin(60.0*PI/180.0);
  1605.     stat = ads_getreal (/*MSG110*/"\nEnter hole diameter <1.0>: ", holed);
  1606.     if (stat == RTCAN) {
  1607.         return FALSE;
  1608.     } else if (*holed <= 0.0) {
  1609.         ads_printf(/*MSG111*/"\nValue must be positive and nonzero.");
  1610.         return FALSE;
  1611.     } else if (*holed >= holed_max) {
  1612.         ads_printf(/*MSG112*/"\nValue must be less than %f.", holed_max);
  1613.         return FALSE;
  1614.     }
  1615.  
  1616.     stat = ap_get_ucsmat(mat1);
  1617.     if (stat != AP_NORMAL)
  1618.         return FALSE;
  1619.     trans_uc2wc(pt, TRUE, pd);
  1620.     stat = ap_translate (pd[X], pd[Y], pd[Z], mat2);
  1621.     if (stat != AP_NORMAL)
  1622.         return FALSE;
  1623.     stat = ap_compose(mat2, mat1, mat);
  1624.     if (stat != AP_NORMAL)
  1625.         return FALSE;
  1626.     return TRUE;
  1627. }
  1628.  
  1629. /*************************************************************************/
  1630. /* .doc trans_uc2wc() */
  1631. /*+
  1632.    Transform a point p in ucs into point q in wcs
  1633.    If vec = TRUE, then p is a vector
  1634.    If vec = FALSE, then p is a point
  1635. -*/
  1636. /*************************************************************************/
  1637.  
  1638. static void
  1639. /* FCN */trans_uc2wc(p,vec,q)
  1640.   ads_point p, q;
  1641.   ap_Bool vec;
  1642. {
  1643.     struct resbuf rbfrom, rbto;
  1644.  
  1645.     rbfrom.restype = RTSHORT;
  1646.     rbto.restype = RTSHORT;
  1647.     rbfrom.resval.rint = 1;           /* from ucs */
  1648.     rbto.resval.rint = 0;             /* to world */
  1649.     ads_trans(p, &rbfrom, &rbto, vec, q);
  1650. }
  1651.  
  1652.  
  1653. /* EOF */
  1654.