home *** CD-ROM | disk | FTP | other *** search
- /* Next available MSG number is 48 */
-
- /************************************************************************
- Name: layout.c. AME2_APLIB_SAMP_layout.c
-
- Description: AME/API sample program for automatic layout of regions
-
- Author: AME Group
- Autodesk, Inc.
-
-
-
-
- Copyright (C) 1992 by Autodesk, Inc.
- **************************************************************************
- * *
- * Permission to use, copy, modify, and distribute this software *
- * for any purpose and without fee is hereby granted, provided *
- * that the above copyright notice appears in all copies and that *
- * both that copyright notice and this permission notice appear in *
- * all supporting documentation. *
- * *
- * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED *
- * WARRANTY. ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR *
- * PURPOSE AND OF MERCHANTABILITY ARE HEREBY DISCLAIMED. *
- * *
- * *
- * Blanking is a typical sheet-metal forming process for mass *
- * production of parts such as gear, cam levers, etc. The basic *
- * tools used with this manufacture process are the punch and the die. *
- * The punch is the convex tool which mates with the concave die. *
- * This process often requires a layout plan of the part pattern *
- * within a given area in order to produce maximum number of parts *
- * from a given metal sheet. *
- * *
- * This sample program illustrates how to use AME/API as *
- * development tool for creating 2D parts such as gear and sheet *
- * as regions, retrieving topological & geometric data information *
- * from the regions for reasoning & evaluation, and performing *
- * automatic layout of the part on the sheet. *
- * *
- * Three commands are available in this application, "GEAR", *
- * "SHEET" and "LAYOUT". "GEAR" allows the user to create a 2D gear *
- * profile as sample part by specifying design parameters such as *
- * pitch circle diameter, number of teeth, and pressure angle. *
- * The gear is placed in a plane parallel to current ucs plane *
- * and is centered at the selected center point. *
- * The command syntax for "GEAR" is shown as follows: *
- * *
- * Command: gear *
- * Select center <0,0,0>: Pick a point *
- * Enter pitch circle diameter <4.0>: Enter a value *
- * Enter number of teeth <12>: Enter a number *
- * Enter pressure angle <25 degrees>: Enter a value *
- * *
- * *
- * "SHEET" allows the user to create a 2D rectangular region *
- * as sample metal sheet by specifying parameters such as length *
- * and width. The sheet is placed in a plane parallel to *
- * current ucs with its center at the selected center point. *
- * The command syntax for "SHEET" is shown as follows: *
- * *
- * Command: sheet *
- * Select center <0,0,0>: Pick a point *
- * Enter length <10.0>: Enter a value *
- * Enter width <8>: Enter a value *
- * *
- * *
- * "LAYOUT" performs automatic layout of the selected part *
- * in the selected metal sheet. It verifies the validity of the *
- * selected sheet and determines its border and size. The part is *
- * then copied and placed in the sheet, beginning from left to right *
- * and then from bottom to top until it fills up the whole sheet. *
- * It also counts the number of parts in the sheet and calculates *
- * the material utilization rate for the proposed layout. The user *
- * can experiment various layout by trying different rotation angle *
- * of the selected part with respect to the selected sheet. *
- * The command syntax for "LAYOUT" is shown as follows: *
- * *
- * Command: layout *
- * Select a rectangular sheet: Pick a region *
- * Select a part: Pick a region *
- * Rotation angle of part <0.0>: Enter a value *
- * *
- **************************************************************************
-
-
- Modification history:
- Refer to the RCS section at the end of this file.
-
- Bugs and restrictions on use:
-
- Notes:
-
- **************************************************************************/
-
-
- /*************************************************************************/
- /* Includes */
- /*************************************************************************/
-
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
- #include <adslib.h>
- #include <aplib.h>
-
- /*************************************************************************/
- /* Defines */
- /*************************************************************************/
-
- #define PI 3.14159265358927
- #define EPSILON 1.0e-8
- #define PMAX 10
-
- #ifndef ELEMENTS
- #define ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
- #endif
-
- /*************************************************************************/
- /* Typedefs */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* Global variables */
- /*************************************************************************/
-
- /* Function type declaration */
-
- int funcload();
- void print_new_command_set();
- void create_gear_func();
- ap_Bool get_gear_data();
- void create_sheet_func();
- ap_Bool get_sheet_data();
- void create_layout_func();
- ap_Bool select_region();
- ap_Bool define_gear_pline();
- ap_Bool define_rectangle_pline();
- void trans_wc2uc();
- void trans_uc2wc();
- ap_Bool get_region_plane();
- ap_Bool verify_region_in_ucs();
- ap_Bool verify_region_rectangular();
- ap_Bool verify_line_horizontal();
- ap_Bool verify_line_vertical();
- ap_Bool insert_pt_to_array();
- ap_Bool verify_2pts_equal();
- ads_real find_maximum();
- ads_real find_minimum();
-
- /* Command definition and dispatch table. */
-
- struct ads_comm {
- char *cmdname;
- void (*cmdfunc) ();
- };
-
- struct ads_comm cmdtab[] = {
-
- {/*MSG1*/"C:GEAR", create_gear_func},
- {/*MSG2*/"C:SHEET", create_sheet_func},
- {/*MSG3*/"C:LAYOUT", create_layout_func},
- };
-
-
- /*************************************************************************/
- /* .doc main() */
- /*+
- -*/
- /*************************************************************************/
-
- void
- /*FCN*/main(argc, argv)
- int argc;
- char *argv[];
- {
- int stat, cindex;
- short scode = 1;
-
- ads_init(argc, argv);
-
- while (TRUE) {
- if ((stat = ads_link(scode)) < 0) {
- printf(/*MSG4*/"LAYOUT: bad status from ads_link() = %d\n",
- stat);
- fflush(stdout);
- ads_exit(1);
- }
- scode = -RSRSLT;
-
- switch (stat) {
-
- case RQXLOAD: /* Load & register functions */
- scode = -(funcload() ? RSRSLT : RSERR);
- scode = -RSRSLT;
- print_new_command_set();
- break;
-
- case RQSUBR: /* Evaluate external lisp function */
- cindex = ads_getfuncode();
- (*cmdtab[cindex].cmdfunc) ();
- break;
-
- case RQXUNLD: /* Unloading */
- ads_printf (/*MSG5*/"Unloading: ");
- break;
-
- case RQSAVE: /* AutoCAD SAVE notification */
- break;
-
- case RQQUIT: /* AutoCAD QUIT notification */
- break;
-
- case RQEND: /* AutoCAD END notification */
- break;
-
- default:
- break;
-
- }
-
- }
- }
-
- /*************************************************************************/
- /* .doc funcload() */
- /*+
- Load external functions into AutoCAD system
- -*/
- /*************************************************************************/
-
- static int
- /*FCN*/funcload()
-
- {
- int i;
-
- for (i = 0; i < ELEMENTS(cmdtab); i++) {
- if(! ads_defun (cmdtab[i].cmdname , i))
- return RTERROR;
- }
- return RTNORM;
- }
-
- /*************************************************************************/
- /* .doc print_new_command_set() */
- /*+
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/print_new_command_set()
- {
- ads_printf(/*MSG6*/"\nNew loaded commands:");
- ads_printf(/*MSG7*/"\nGEAR, SHEET, LAYOUT\n");
- }
-
- /*************************************************************************/
- /* .doc create_gear_func() */
- /*+
- Creates a 2D gear parallel to current ucs plane with center at
- specified location. The gear is represented as a region.
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/create_gear_func ()
- {
- ads_point pc;
- ap_Real gear_d, alpha;
- int np, stat, number_t;
- ap_Objid Gear;
- ap_Swp_pts pline[501];
- ap_Trans3d mat;
-
- /* Initialize API */
-
- stat = ap_init();
- if (stat != AP_NORMAL)
- goto Error;
-
- /* Prompt user for gear data */
-
- stat = get_gear_data(pc, &gear_d, &number_t, &alpha, mat);
- if (stat == FALSE)
- goto Error;
-
- /* Defines the profile for the gear boundary */
-
- stat = define_gear_pline(gear_d, number_t, alpha, pline, &np);
- if (stat == FALSE)
- goto Error;
-
- /* Creates a region defined by pline */
-
- stat = ap_polyline (np, pline, &Gear);
- if (stat != AP_NORMAL)
- goto Error;
-
- /* Move the Gear to the desired location */
-
- stat = ap_move_obj(Gear, mat, FALSE);
- if (stat != AP_NORMAL)
- goto Error;
-
- /* Displays the wireframe model of the gear on the screen */
-
- stat = ap_post_obj (Gear, AP_POSTWIRE);
- if (stat != AP_NORMAL)
- goto Error;
-
- Error:
- ads_retvoid();
- return;
-
- }
-
- /*************************************************************************/
- /* .doc get_gear_data() */
- /*+
- This routine prompts the user to enter gear data.
- -*/
- /*************************************************************************/
- static ap_Bool
- /*FCN*/get_gear_data (pc, dia, nteeth, pangle, mat)
- ads_point pc;
- ads_real *dia, *pangle;
- int *nteeth;
- ap_Trans3d mat;
- {
- int stat;
- ads_point pt, pd;
- ap_Trans3d mat1, mat2;
-
- /* Initialization of gear data for default input */
-
- pt[X] = 0.0;
- pt[Y] = 0.0;
- pt[Z] = 0.0;
- *dia = 4.0;
- *nteeth = 12;
- *pangle = 25.0;
-
- /* Acquire values of design parameters associated with gear
- from the user and verify the validity of input data */
-
- stat = ads_getpoint (NULL, /*MSG8*/"\nCenter <0,0,0>: ", pt);
- if (stat == RTCAN) {
- return FALSE;
- }
- trans_uc2wc(pt, FALSE, pc);
- stat = ads_getreal (/*MSG9*/"\n\nEnter pitch circle diameter <4.0>: ", dia);
- if (stat == RTCAN) {
- return FALSE;
- } else if (*dia <= 0.0) {
- ads_printf(/*MSG10*/"\nValue must be positive and nonzero.");
- return FALSE;
- }
-
- stat = ads_getint (/*MSG11*/"\nEnter number of teeth <12>: ", nteeth);
- if (stat == RTCAN) {
- return FALSE;
- } else if (*nteeth <= 3) {
- ads_printf(/*MSG12*/"\nCan not handle less than 4 teeth.");
- return FALSE;
- } else if (*nteeth > 36) {
- ads_printf(/*MSG13*/"\nCan not handle more than 36 teeth.");
- return FALSE;
- }
-
- stat = ads_getreal (/*MSG14*/"\nEnter pressure angle <25 degrees>: ", pangle);
- if (stat == RTCAN) {
- return FALSE;
- } else if (*pangle < 14.5) {
- ads_printf(/*MSG15*/"\nAngle must be greater or equal to 14.5 degrees.");
- return FALSE;
- } else if (*pangle > 25.0) {
- ads_printf(/*MSG16*/"\nAngle must be less or equal to 25 degrees.");
- return FALSE;
- }
-
- stat = ap_get_ucsmat(mat1);
- if (stat != AP_NORMAL)
- return FALSE;
- trans_uc2wc(pt, TRUE, pd);
- stat = ap_translate (pd[X], pd[Y], pd[Z], mat2);
- if (stat != AP_NORMAL)
- return FALSE;
- stat = ap_compose(mat2, mat1, mat);
- if (stat != AP_NORMAL)
- return FALSE;
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc create_sheet_func() */
- /*+
- Creates a rectangle parallel to current ucs plane with
- center at the selected location. The rectangle is
- represented as a region.
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/create_sheet_func()
- {
- ap_Real rect_l, rect_w;
- ads_point pc;
- ap_Trans3d mat;
- int np, stat;
- ap_Objid Rect;
- ap_Swp_pts pline[5];
-
- /* Initialize API */
-
- stat = ap_init();
- if (stat != AP_NORMAL)
- goto Error;
-
- /* Prompt user for rectangular sheet data */
-
- stat = get_sheet_data(pc, &rect_l, &rect_w, mat);
- if (stat == FALSE)
- goto Error;
-
- /* Defines the profile for the rectangular boundary */
-
- stat = define_rectangle_pline(rect_l, rect_w, pline, &np);
- if (stat == FALSE)
- goto Error;
-
- /* Creates a region with boundary defined by pline */
-
- stat = ap_polyline (np, pline, &Rect);
- if (stat != AP_NORMAL)
- goto Error;
-
- /* Move the Sheet to the specified location */
-
- stat = ap_move_obj(Rect, mat, FALSE);
- if (stat != AP_NORMAL)
- goto Error;
-
- /* Displays the wireframe model of the sheet on the screen */
-
- stat = ap_post_obj (Rect, AP_POSTWIRE);
- if (stat != AP_NORMAL)
- goto Error;
-
- Error:
- ads_retvoid();
- return;
- }
-
- /*************************************************************************/
- /* .doc get_sheet_data() */
- /*+
- This routine prompts the user to enter sheet data.
- -*/
- /*************************************************************************/
- static ap_Bool
- /*FCN*/get_sheet_data (pc, length, width, mat)
- ads_point pc;
- ads_real *length, *width;
- ap_Trans3d mat;
- {
- int stat;
- ads_point pt, pd;
- ap_Trans3d mat1, mat2;
-
- /* Initialization of gear data for default input */
-
- pt[X] = 0.0;
- pt[Y] = 0.0;
- pt[Z] = 0.0;
- *length = 10.0;
- *width = 8.0;
-
- /* Acquire values of design parameters associated with gear
- from the user and verify the validity of input data */
-
- stat = ads_getpoint (NULL, /*MSG17*/"\nCenter <0,0,0>: ", pt);
- if (stat == RTCAN) {
- return FALSE;
- }
- trans_uc2wc(pt, FALSE, pc);
-
- stat = ads_getreal (/*MSG18*/"\n\nEnter length <10.0>: ", length);
- if (stat == RTCAN) {
- return FALSE;
- } else if (*length <= 0.0) {
- ads_printf(/*MSG19*/"\nValue must be positive and nonzero.");
- return FALSE;
- }
-
- stat = ads_getreal (/*MSG20*/"\nEnter width <8.0>: ", width);
- if (stat == RTCAN) {
- return FALSE;
- } else if (*width <= 0.0) {
- ads_printf(/*MSG21*/"\nValue must be positive and nonzero.");
- return FALSE;
- }
-
- stat = ap_get_ucsmat(mat1);
- if (stat != AP_NORMAL)
- return FALSE;
- pt[X] = pt[X] - (*length) / 2.0;
- pt[Y] = pt[Y] - (*width) / 2.0;
- trans_uc2wc(pt, TRUE, pd);
- stat = ap_translate (pd[X], pd[Y], pd[Z], mat2);
- if (stat != AP_NORMAL)
- return FALSE;
- stat = ap_compose(mat2, mat1, mat);
- if (stat != AP_NORMAL)
- return FALSE;
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc create_layout_func() */
- /*+
- This routine performs the following tasks:
-
- 1. Prompt the user to select a rectangular region as metal sheet.
- 2. Verify that the selected sheet lies in current ucs plane.
- 3. Verify whether the selected region is a rectangular sheet
- and retrieve the border and the area of the sheet.
- 4. Prompt the user to select a part and a rotation angle.
- 5. Verify that the selected part lies in current ucs plane.
- 6. Retrieve the mass property and obtain the centroid of the part.
- 7. Duplicate a copy (Template) of the selected part
- and rotate the Template about the centroid of the part.
- 8. Obtain the bounding box of the Template.
- 9. Copy and place the Template to the metal sheet, beginning
- from left to right, from bottom to top until it fills
- up the sheet.
- 10. Print out the area of the metal sheet and the part, the total
- number of parts in the layout and the material utilization
- rate corresponding to the layout.
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/create_layout_func ()
- {
- ap_Real sheet_l, sheet_w, sheet_area, urate;
- ap_Real part_l, part_w, part_area, part_angle;
- ap_Objid Sheet, Part, Template, Temp;
- ap_Massprop mp;
- ap_Trans3d m;
- ads_name chosen1, chosen2;
- ads_point loc, smin, smax, tmin, tmax, pc, pd;
- ads_point pt, rot_axis[2];
- int stat, i, j, ncolumn, nrow, ntotal;
-
- /* Initialize API */
-
- stat = ap_init();
- if (stat != AP_NORMAL)
- goto Error0;
-
- /* Prompt the user to select a rectangular region for metal sheet */
-
- stat = select_region(/*MSG22*/"\nSelect a rectangular sheet:", &Sheet, chosen1, loc);
- if(stat == FALSE)
- goto Error0;
-
- /* Highlight the selected entity */
-
- ads_redraw(chosen1, 3);
-
- /* Verify region in current ucs plane */
-
- stat = verify_region_in_ucs(Sheet);
- if(stat == FALSE) {
- ads_printf(/*MSG23*/"\nThe selected region must lie in current ucs plane.");
- goto Error2;
- }
-
- /* Verify that the selected region is a rectangular sheet,
- and retrieve its border, size and area. */
-
- stat = verify_region_rectangular(Sheet, smin, smax);
- if(stat == FALSE)
- goto Error1;
-
- sheet_l = fabs(smax[X] - smin[X]);
- sheet_w = fabs(smax[Y] - smin[Y]);
- sheet_area = sheet_l * sheet_w;
-
- /* Prompt the user to select a part pattern which will
- be blanked out from the sheet */
-
- stat = select_region(/*MSG24*/"\nSelect a part:", &Part, chosen2, loc);
- if(stat == FALSE)
- goto Error1;
-
- /* Highlight the selected entity */
-
- ads_redraw(chosen2, 3);
-
- /* Verify that the selected region is in xy plane */
-
- stat = verify_region_in_ucs(Part);
- if(stat == FALSE) {
- ads_printf
- (/*MSG25*/"\nThe selected entity must lie in current ucs plane.");
- goto Error2;
- }
-
- /* Prompt the user to enter rotation angle for the
- selected part */
-
- part_angle = 0.0;
- stat = ads_getreal (/*MSG26*/"\n\nRotation angle of part <0.0>: ", &part_angle);
- if (stat == RTCAN)
- goto Error2;
-
- /* Retrieve the mass properties of the part and
- obtain the centroid pc of the selected part */
-
- stat = ap_get_massprop(Part, &mp);
- if(stat != AP_NORMAL) {
- ads_printf(/*MSG27*/"\nUnable to retrieve mass properties.");
- goto Error2;
- }
-
- pc[X] = mp.centroid.x;
- pc[Y] = mp.centroid.y;
- pc[Z] = mp.centroid.z;
- part_area = mp.area;
-
- /* Duplicate a copy of the part called Template and rotate
- Template about the center of the its bounding box */
-
- stat = ap_dup_obj(Part, &Template);
- if (stat != AP_NORMAL)
- goto Error2;
-
- /* Define a rotation axis from pc to pd which is
- perpendicular to ucs plane */
-
- pd[X] = pc[X];
- pd[Y] = pc[Y];
- pd[Z] = 1.0;
-
- trans_uc2wc(pc, FALSE, rot_axis[0]);
- trans_uc2wc(pd, FALSE, rot_axis[1]);
-
- /* Rotate Template about the rotation axis through
- the specified angle part_angle */
-
- part_angle = part_angle * PI / 180.0;
- stat = ap_rotate_axis(rot_axis, part_angle, m);
- if (stat != AP_NORMAL)
- goto Error2;
- stat = ap_move_obj(Template, m, FALSE);
- if (stat != AP_NORMAL)
- goto Error2;
-
- /* Retrieve the bounding box for the Template */
-
- stat = ap_obj2extents(Template, TRUE, tmin, tmax);
- if (stat != AP_NORMAL)
- goto Error2;
- part_l = fabs(tmax[X] - tmin[X]);
- part_w = fabs(tmax[Y] - tmin[Y]);
-
- /* Verify that the validity of the size for the Template */
-
- if((part_l < EPSILON) || (part_w < EPSILON)) {
- ads_printf(/*MSG28*/"\nThe selected part is too narrow.");
- ap_del_obj(Template);
- goto Error2;
- }
-
- /* Compute the number of columns and rows that can fit
- into the sheet without overlaping each other */
-
- ncolumn = sheet_l / part_l;
- nrow = sheet_w / part_w;
- ntotal = ncolumn * nrow;
- if(ntotal > 1000) {
- ads_printf(/*MSG29*/"\nCan't lay out more than 1000 copies.");
- goto Error2;
- }
-
- /* Move Template to the low-left corner of the sheet
- which is the beginning position of the layout */
-
- pt[X] = smin[X] - tmin[X];
- pt[Y] = smin[Y] - tmin[Y];
- pt[Z] = 0.0;
- trans_uc2wc(pt, TRUE, pd);
- stat = ap_translate(pd[X], pd[Y], pd[Z], m);
- if (stat != AP_NORMAL)
- goto Error2;
- stat = ap_move_obj(Template, m, FALSE);
- if (stat != AP_NORMAL)
- goto Error2;
-
- /* The layout process begins from the left to the right,
- from the bottom to the top until it fills up the whole sheet */
-
- for (j=0; j<nrow; j++) {
- for (i=0; i<ncolumn; i++) {
- stat = ap_dup_obj(Template, &Temp);
- if (stat != AP_NORMAL)
- goto Error2;
- pt[X] = i * part_l;
- pt[Y] = j * part_w;
- pt[Z] = 0.0;
- trans_uc2wc(pt, TRUE, pd);
- stat = ap_translate(pd[X], pd[Y], pd[Z], m);
- if (stat != AP_NORMAL)
- goto Error2;
- stat = ap_move_obj(Temp, m, FALSE);
- if (stat != AP_NORMAL)
- goto Error2;
- stat = ap_post_obj(Temp, AP_POSTWIRE);
- if (stat != AP_NORMAL)
- goto Error2;
- }
- }
-
- /* Calculate the material utilization percentage */
-
- urate = 100.0 * ntotal * part_area / sheet_area;
-
- /* Print out the results */
-
- ads_printf(/*MSG30*/"\nMetal sheet area = %f", sheet_area);
- ads_printf(/*MSG31*/"\nPart area = %f", part_area);
- ads_printf(/*MSG32*/"\nTotal number of parts = %d", ntotal);
- if((urate > -1000.0) && (urate < 1000.0))
- ads_printf(/*MSG33*/"\nMaterial utilization = %8.3f %c", urate, '%');
- else
- ads_printf(/*MSG34*/"\nMaterial utilization is out of the range.");
-
- stat = ap_del_obj(Template);
- if (stat != AP_NORMAL)
- goto Error2;
-
- Error2:
- ads_redraw(chosen2, 4);
-
- Error1:
- ads_redraw(chosen1, 4);
-
- Error0:
- ads_retvoid();
- return;
- }
-
- /*************************************************************************/
- /* .doc select_region() */
- /*+
- This routine prompts the user to select a region
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/select_region (prompt, sol, ename, loc)
- char *prompt;
- ap_Objid *sol;
- ads_name ename;
- ads_point loc;
- {
- int stat;
- ap_Objtype otype;
-
- stat = ads_entsel(prompt, ename, loc);
- if(stat != RTNORM)
- return FALSE;
-
- /* Verify that the selected entity is an AME object */
-
- stat = ap_name2obj(ename, sol);
- if(stat != AP_NORMAL) {
- ads_printf(/*MSG35*/"\nThe selected entity is not a region.");
- return FALSE;
- }
-
- /* Verify that the AME object is a region */
-
- stat = ap_get_objtype(*sol, &otype);
- if((stat != AP_NORMAL) || (otype != AP_REGION)) {
- ads_printf(/*MSG36*/"\nThe selected entity is not a region.");
- return FALSE;
- }
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc define_gear_pline() */
- /*+
- This routine computes the gear profile based on the input
- arguments gear_d (pitch diameter), number_t (number of teeth)
- and alpha (pressure angle). It returns a polyline vertex array pts
- and the total number of vertices npoint contained in the polyline.
- The routine first generates an involute tooth, then rotates and
- copies the tooth to obtain a complete gear profile. The gear profile
- is defined in the xy plane of wcs and centered at the origin.
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/define_gear_pline (gear_d, number_t, alpha, pts, npoint)
- ap_Real gear_d, alpha;
- ap_Swp_pts pts[];
- int number_t, *npoint;
- {
- ap_Real angle_a, angle_b, angle_c, angle_d, angle_e, angle_f;
- ap_Real angle_h, angle_i, angle_j, angle_k;
- ap_Real angle_rot, cos_rot, sin_rot, omega, phi, temp;
- ap_Real rad_pitch, rad_base, rad_adden, rad_deden;
- int i, j, k, nt;
-
- if((gear_d <= 0.0) || (number_t <= 2) || (number_t > 50))
- return FALSE;
-
- nt = 10 * number_t + 1;
- phi = alpha * PI / 180;
-
- /* Define radius for pitch circle */
-
- rad_pitch = gear_d / 2;
-
- /* Define radius for base circle */
-
- rad_base = rad_pitch * cos (phi);
-
- /* Define radius for addendum circle */
-
- rad_adden = rad_pitch + gear_d / number_t;
-
- /* Define radius for dedendum circle */
-
- rad_deden = rad_pitch - 1.25 * gear_d / number_t;
-
- if (rad_deden > rad_base)
- rad_deden = 0.99 * rad_base;
- temp = rad_adden * rad_adden / (rad_base * rad_base) - 1;
- omega = sqrt (temp);
-
- /* Define some key angles corresponding to tooth profile */
-
- angle_i = PI/ (2 * number_t);
- angle_j = angle_i + tan (phi) - phi;
- angle_k = angle_j;
- angle_h = angle_j - omega + atan (omega);
- angle_a = angle_j - 2 * PI / number_t;
- angle_b = (angle_a - angle_j) / 2;
- angle_c = - angle_k;
- angle_d = - angle_j;
- angle_e = - angle_i;
- angle_f = - angle_h;
-
- /* Define the coordinates of the polyline vertices
- for one tooth profile that consists of line
- and arc segments */
-
- pts[0].x = rad_deden * cos (angle_a);
- pts[0].y = rad_deden * sin (angle_a);
- pts[0].type = AP_PT_LINE;
-
- pts[1].x = rad_deden * cos (angle_b);
- pts[1].y = rad_deden * sin (angle_b);
- pts[1].type = AP_PT_LINE;
-
- pts[2].x = rad_deden * cos (angle_c);
- pts[2].y = rad_deden * sin (angle_c);
- pts[2].type = AP_PT_ARCEND;
-
- pts[3].x = rad_base * cos (angle_d);
- pts[3].y = rad_base * sin (angle_d);
- pts[3].type = AP_PT_LINE;
-
- pts[4].x = rad_pitch * cos (angle_e);
- pts[4].y = rad_pitch * sin (angle_e);
- pts[4].type = AP_PT_LINE;
-
- pts[5].x = rad_adden * cos (angle_f);
- pts[5].y = rad_adden * sin (angle_f);
- pts[5].type = AP_PT_ARCEND;
-
- pts[6].x = rad_adden;
- pts[6].y = 0.0;
- pts[6].type = AP_PT_LINE;
-
- pts[7].x = pts[5].x;
- pts[7].y = -pts[5].y;
- pts[7].type = AP_PT_ARCEND;
-
- pts[8].x = pts[4].x;
- pts[8].y = -pts[4].y;
- pts[8].type = AP_PT_LINE;
-
- pts[9].x = pts[3].x;
- pts[9].y = -pts[3].y;
- pts[9].type = AP_PT_ARCEND;
-
- pts[10].x = pts[2].x;
- pts[10].y = -pts[2].y;
- pts[10].type = AP_PT_LINE;
-
- /* Rotate and copy one tooth profile to obtain
- a complete gear profile */
-
- for (i=1; i<number_t; i++) {
- angle_rot = i * 2 * PI / number_t;
- cos_rot = cos (angle_rot);
- sin_rot = sin (angle_rot);
-
- for (j=1; j<11; j++) {
- k = 10 * i + j;
- pts[k].x = cos_rot * pts[j].x - sin_rot * pts[j].y;
- pts[k].y = sin_rot * pts[j].x + cos_rot * pts[j].y;
- pts[k].type = pts[j].type;
- }
- }
-
- pts[nt-1].x = pts[0].x;
- pts[nt-1].y = pts[0].y;
- pts[nt-1].type = pts[0].type;
-
- *npoint = nt;
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc define_rectangle_pline() */
- /*+
- This routine computes the rectangle profile based on the input
- arguments length and width. It returns a polyline vertex array pts
- and the total number of vertices npoint contained in the polyline.
- The rectangle is defined in the xy plane of ucs with lts low-left
- corner at the origin.
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/define_rectangle_pline (length, width, pts, npoint)
- ap_Real length, width;
- ap_Swp_pts pts[];
- int *npoint;
- {
-
- if((length <= 0.0) || (width <= 0.0))
- return FALSE;
- pts[0].x = 0.0;
- pts[0].y = 0.0;
- pts[0].type = AP_PT_LINE;
-
- pts[1].x = length;
- pts[1].y = 0.0;
- pts[1].type = AP_PT_LINE;
-
- pts[2].x = length;
- pts[2].y = width;
- pts[2].type = AP_PT_LINE;
-
- pts[3].x = 0.0;
- pts[3].y = width;
- pts[3].type = AP_PT_LINE;
-
- pts[4].x = 0.0;
- pts[4].y = 0.0;
- pts[4].type = AP_PT_LINE;
-
- *npoint = 5;
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc trans_wc2uc() */
- /*+
- Transform a point p in wcs into point q in ucs
- If vec = TRUE, then p is a vector
- If vec = FALSE, then p is a point
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/trans_wc2uc(p,vec,q)
- ads_point p, q;
- ap_Bool vec;
- {
- struct resbuf rbfrom, rbto;
-
- rbfrom.restype = RTSHORT;
- rbto.restype = RTSHORT;
- rbfrom.resval.rint = 0; /* from world */
- rbto.resval.rint = 1; /* to ucs */
- ads_trans(p, &rbfrom, &rbto, vec, q);
- }
-
- /*************************************************************************/
- /* .doc trans_uc2wc() */
- /*+
- Transform a point p in ucs into point q in wcs
- If vec = TRUE, then p is a vector
- If vec = FALSE, then p is a point
- -*/
- /*************************************************************************/
-
- static void
- /* FCN */trans_uc2wc(p,vec,q)
- ads_point p, q;
- ap_Bool vec;
- {
- struct resbuf rbfrom, rbto;
-
- rbfrom.restype = RTSHORT;
- rbto.restype = RTSHORT;
- rbfrom.resval.rint = 1; /* from ucs */
- rbto.resval.rint = 0; /* to world */
- ads_trans(p, &rbfrom, &rbto, vec, q);
- }
-
- /*************************************************************************/
- /* .doc get_region_plane() */
- /*+
- This routine obtains the co-planar matrix of the given region.
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/get_region_plane(obj, mat)
- ap_Objid obj;
- ap_Trans3d mat;
- {
- ap_Objinfo oinfo;
- ap_Objid object;
- int stat;
-
- /* Retrieve object information and verify that it is a region */
-
- stat = ap_get_objinfo(obj, &oinfo);
- if((stat != AP_NORMAL) || (oinfo.obj != AP_REGION)) {
- ads_printf(/*MSG37*/"\nThe selected entity is not a region.");
- return FALSE;
- }
- stat = ap_identity(mat);
- if(stat != AP_NORMAL)
- return FALSE;
- stat = ap_compose(oinfo.mat, mat, mat);
- if(stat != AP_NORMAL)
- return FALSE;
-
- /* Compose matrix through CSG tree's left child branch */
-
- while (oinfo.type == AP_BOO) {
- object = oinfo.prim.boo.op1;
- stat = ap_get_objinfo(object, &oinfo);
- if(stat != AP_NORMAL)
- return FALSE;
- stat = ap_compose(oinfo.mat, mat, mat);
- if(stat != AP_NORMAL)
- return FALSE;
- }
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc verify_region_in_ucs() */
- /*+
- This routine verifies that a given region
- lies in the xy plane of current ucs.
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/verify_region_in_ucs(obj)
- ap_Objid obj;
- {
- ads_point pc1, pc2, norm1, norm2;
- ap_Trans3d mat;
- int stat;
-
- /* Retrieve the co-planar matrix of the region */
-
- stat = get_region_plane(obj, mat);
- if(stat != TRUE) {
- ads_printf(/*MSG38*/"\nUnable to retrieve region's co-planar matrix.");
- return FALSE;
- }
-
- /* Retrieve a point that lies in the same plane as the region */
-
- pc1[X] = mat[0][3];
- pc1[Y] = mat[1][3];
- pc1[Z] = mat[2][3];
-
- /* Retrieve the normal to the region plane */
-
- norm1[X] = mat[0][2];
- norm1[Y] = mat[1][2];
- norm1[Z] = mat[2][2];
-
- /* Retrieve the current ucs matrix */
-
- stat = ap_get_ucsmat(mat);
- if (stat != AP_NORMAL)
- return FALSE;
-
- /* Retrieve the origin of current ucs */
-
- pc2[X] = mat[0][3];
- pc2[Y] = mat[1][3];
- pc2[Z] = mat[2][3];
-
- /* Retrieve the normal of current ucs plane */
-
- norm2[X] = mat[0][2];
- norm2[Y] = mat[1][2];
- norm2[Z] = mat[2][2];
-
- /* Verify that region plane and ucs plane are coincident */
-
- stat = verify_planes_equal(pc1, norm1, pc2, norm2);
- if (stat == TRUE)
- return TRUE;
- else
- return FALSE;
- }
-
- /*************************************************************************/
- /* .doc verify_planes_equal() */
- /*+
- This routine verify whether two planes are coincident.
- The plane is defined by its normal and a through point.
- -*/
- /*************************************************************************/
- static ap_Bool
- /*FCN*/verify_planes_equal (org1, norm1, org2, norm2)
- ads_point org1, norm1, org2, norm2;
- {
- ads_point dir;
- ads_real dx, dy, dz, du, dv;
-
- if (((fabs (norm1[X]) < EPSILON) &&
- (fabs (norm1[Y]) < EPSILON) &&
- (fabs (norm1[Z]) < EPSILON)) ||
- ((fabs (norm2[X]) < EPSILON) &&
- (fabs (norm2[Y]) < EPSILON) &&
- (fabs (norm2[Z]) < EPSILON)))
- return FALSE;
-
- dx = norm1[Y]*norm2[Z] - norm1[Z]*norm2[Y];
- dy = norm1[Z]*norm2[X] - norm1[X]*norm2[Z];
- dz = norm1[X]*norm2[Y] - norm1[Y]*norm2[X];
-
- dir[X] = org2[X] - org1[X];
- dir[Y] = org2[Y] - org1[Y];
- dir[Z] = org2[Z] - org1[Z];
- du = dir[X]*norm1[X] + dir[Y]*norm1[Y] + dir[Z]*norm1[Z];
- dv = dir[X]*norm2[X] + dir[Y]*norm2[Y] + dir[Z]*norm2[Z];
-
- if ((fabs (dx) < EPSILON) && (fabs (dy) < EPSILON) &&
- (fabs (dz) < EPSILON) && (fabs (du) < EPSILON) &&
- (fabs (dv) < EPSILON))
- return TRUE;
- else
- return FALSE;
- }
-
- /*************************************************************************/
- /* .doc verify_region_rectangular() */
- /*+
- This routine verify that a selected region is a rectangle
- which satisfies the following criteria:
-
- 1. It contains no holes (flaws) in it.
- 2. It consists of four line edges and four vertices.
- 3. All the edges are either horizontal or vertical.
-
- If all the criteria are satisfied, it returns TRUE as well as
- the low_left and top_right corners of the rectangle in ucs.
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/verify_region_rectangular(obj, pmin, pmax)
- ap_Objid obj;
- ads_point pmin, pmax;
- {
- ap_Featid *llist;
- ap_Edgelist *elist, *seg;
- ads_point pt1, pt2;
- ads_real xa[PMAX], ya[PMAX];
- int nloop, nedge, nvertex, index, stat, stat1, stat2, find_curve;
-
- /* Retrieve all the loops contained in the region */
-
- stat = ap_obj2loops(obj, &llist);
- if (stat != AP_NORMAL)
- goto Error1;
-
- nloop = 0;
- while (llist[nloop] != (ap_Featid)NULL)
- nloop++;
-
- /* Verify that there are no inside loops (holes)
- contained in the region */
-
- if(nloop != 1) {
- ads_printf(/*MSG39*/"\nThe selected sheet may have holes in it");
- goto Error1;
- }
-
- /* Retrieve all the edges contained in the loop */
-
- stat = ap_loop2edges(obj, llist[0], TRUE, &elist);
- if (stat != AP_NORMAL) {
- ads_printf (/*MSG40*/"\nUnable to retrieve edges from loop.");
- goto Error2;
- }
-
- /* Count the total number of edges contained in the loop
- and check whether there are any curve edges */
-
- nedge = 0;
- find_curve = FALSE;
- seg = elist;
- while (seg != NULL) {
- if (seg->edge->ctype != AP_LINE)
- find_curve = TRUE;
-
- seg = seg->edgenext;
- nedge++;
- }
-
- /* Verify that the region consists of 4 edges */
-
- if(nedge != 4) {
- ads_printf(/*MSG41*/"\nThe selected sheet has %d edges. ", nedge);
- ads_printf(/*MSG42*/"It is not a rectangle.");
- goto Error2;
- }
-
- /* Verify that all the edges are line segments */
-
- if(find_curve == TRUE) {
- ads_printf(/*MSG43*/"\nThe selected sheet contains curve edges. ");
- ads_printf(/*MSG44*/"It is not a rectangle.");
- goto Error2;
- }
-
- /* Verify that all the edges are either horizontal or vertical */
-
- seg = elist;
- while (seg != NULL) {
-
- trans_wc2uc(seg->edge->s_pt, FALSE, pt1);
- trans_wc2uc(seg->edge->e_pt, FALSE, pt2);
- stat1 = verify_line_horizontal(pt1, pt2);
- stat2 = verify_line_vertical(pt1, pt2);
- if((stat1 == FALSE) && (stat2 == FALSE)) {
- ads_printf(/*MSG45*/"\nThe selected region is not horizontal.");
- goto Error2;
- }
- seg = seg->edgenext;
- }
-
- /* Retrieve all the vertices contained in the region */
-
- nvertex = 0;
- seg = elist;
- while (seg != NULL) {
- trans_wc2uc(seg->edge->s_pt, FALSE, pt1);
- stat = insert_pt_to_array(pt1, xa, ya, nvertex);
- if (stat == TRUE)
- nvertex = nvertex + 1;
- trans_wc2uc(seg->edge->e_pt, FALSE, pt2);
- stat = insert_pt_to_array(pt2, xa, ya, nvertex);
- if (stat == TRUE)
- nvertex = nvertex + 1;
- seg = seg->edgenext;
- }
-
- /* Verify that the region contains only 4 vertices */
-
- if(nvertex != 4) {
- ads_printf(/*MSG46*/"\nThe selected sheet has %d vertex. ",nvertex);
- ads_printf(/*MSG47*/"It is not a rectangle.");
- goto Error2;
- }
-
- /* Find the bounding box of the rectangle.
- Pmin is the low-left corner,
- Pmax is the top-right corner of the rectangle */
-
- pmin[X] = find_minimum(xa, nvertex, &index);
- pmin[Y] = find_minimum(ya, nvertex, &index);
- pmin[Z] = 0.0;
- pmax[X] = find_maximum(xa, nvertex, &index);
- pmax[Y] = find_maximum(ya, nvertex, &index);
- pmax[Z] = 0.0;
-
- free(llist);
- ap_free_edgelist(elist);
- ads_retvoid();
- return TRUE;
-
- Error2:
- ap_free_edgelist(elist);
-
- Error1:
- free(llist);
- ads_retvoid();
- return FALSE;
-
- }
-
- /*************************************************************************/
- /* .doc verify_line_horizontal() */
- /*+
- This routine verify that a line defined by points pt1 & pt2
- is a horizontal line in ucs. The endpoints of the line must
- not be coincident. pt1 and pt2 are in ucs coordinates.
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/verify_line_horizontal(pt1, pt2)
- ads_point pt1, pt2;
- {
- ads_real dy;
- int stat;
-
- stat = verify_2pts_equal (pt1, pt2);
- if(stat == TRUE)
- return FALSE;
-
- dy = pt2[Y] - pt1[Y];
- if(fabs(dy) < EPSILON)
- return TRUE;
- else
- return FALSE;
- }
-
- /*************************************************************************/
- /* .doc verify_line_vertical() */
- /*+
- This routine verify that a line defined by points pt1 & pt2
- is a vertical line in ucs. The endpoints of the line must
- not be coincident. pt1 and pt2 are in ucs coordinates.
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/verify_line_vertical(pt1, pt2)
- ads_point pt1, pt2;
- {
- ads_real dx;
- int stat;
-
- stat = verify_2pts_equal (pt1, pt2);
- if(stat == TRUE)
- return FALSE;
-
- dx = pt2[X] - pt1[X];
- if(fabs(dx) < EPSILON)
- return TRUE;
- else
- return FALSE;
- }
-
- /*************************************************************************/
- /* .doc insert_pt_to_array() */
- /*+
- This routine insert the x-coordinate and y-coordinate of
- a given point pt into arrays xa[] and ya[] respectively.
- Coincident points are merged into one point only.
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /* FCN */insert_pt_to_array (pt, xa, ya, np)
- ads_point pt;
- ads_real xa[], ya[];
- int np;
- {
- int i;
-
- if(np <= 0) {
- xa[0] = pt[X];
- ya[0] = pt[Y];
- return TRUE;
- }
-
- for(i = 0; i < np; i++) {
- if ((fabs(pt[X] - xa[i]) < EPSILON) &&
- (fabs(pt[Y] - ya[i]) < EPSILON))
- return FALSE;
- }
-
- xa[np] = pt[X];
- ya[np] = pt[Y];
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc verify_2pts_equal() */
- /*+
- Verify whether two points p1 & p2 are coincident or not.
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /* FCN */verify_2pts_equal (p1, p2)
- ads_point p1, p2;
- {
- ads_real dx, dy, dz;
-
- dx = fabs (p2[X] - p1[X]);
- dy = fabs (p2[Y] - p1[Y]);
- dz = fabs (p2[Z] - p1[Z]);
-
- if ((dx < EPSILON) && (dy < EPSILON) && (dz < EPSILON))
- return TRUE;
- else
- return FALSE;
- }
-
- /*************************************************************************/
- /* .doc find_maximum() */
- /*+
- Find the maximum value among nt elements contained in array[].
- Return the maximum and the index associated with the maximum.
- -*/
- /*************************************************************************/
- static ads_real
- /*FCN*/find_maximum (array, nt, index)
- ads_real array[];
- int nt, *index;
- {
- ads_real maximum;
- int i;
-
- maximum = array[0];
- *index = 0;
- for (i=0; i<nt; i++)
- {
- if (array[i] > maximum)
- {
- maximum = array[i];
- *index = i;
- }
- }
- return (maximum);
- }
-
- /*************************************************************************/
- /* .doc find_minimum() */
- /*+
- Find the minimum value among nt elements contained in array[].
- Return the minimum and the index associated with the minimum.
- -*/
- /*************************************************************************/
- static ads_real
- /*FCN*/find_minimum (array, nt, index)
- ads_real array[];
- int nt, *index;
- {
- ads_real minimum;
- int i;
-
- minimum = array[0];
- *index = 0;
- for (i=0; i<nt; i++)
- {
- if (array[i] < minimum)
- {
- minimum = array[i];
- *index = i;
- }
- }
- return (minimum);
- }
-
-
- /* EOF */
-