home *** CD-ROM | disk | FTP | other *** search
- /* Next available MSG number is 34 */
-
- /************************************************************************
- Name: drill.c. AME2_APLIB_SAMP_drill.c
-
- Description: AME/API sample program for drilling hole
-
- 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. *
- * *
- * *
- * This program allows the user to drill hole on the selected face *
- * of a given object at the specified center, diameter, and depth. *
- * *
- * The command syntax is shown as follows: *
- * *
- * Command: soldrill *
- * Select a face: Pick a face *
- * Center: Pick a point *
- * Diameter <1.0>: Enter a value *
- * Depth <through>: Enter a value or RETURN for through hole *
- * *
- * If user enters a value for a known depth, the hole will be drilled *
- * from the selected face, along the face normal direction and *
- * terminating at the specified depth. If user selects through *
- * option, the minimum depth required for drilling a through hole *
- * will be determined by the program automatically. If any free face *
- * is detected before through hole can be completed, user will be *
- * notified and prompted for whether to stop drilling at the first *
- * encountered free face. *
- * *
- * In current implementation, only plane faces and normal drilling *
- * are supported. Users can easily extend or tailor this sample *
- * program to fit his or her own need. *
- * *
- * To run the program, You have to xload the executable code "drill" *
- * Then enter the command "soldrill" at regular AutoCAD prompt *
- * *
- * command: soldrill *
- * *
- **************************************************************************
-
-
- 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 OFF 0
- #define ON 1
- #define ORIGIN 2
- #define NO 0
- #define YES 1
- #define CANCEL -1
- #define NRAY 17
-
- #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 command_echo_off();
- void command_echo_on();
- void drill_hole_func();
- ap_Bool get_hole_data();
- void turn_ucsicon();
- ap_Bool get_pts_from_face();
- void copy_point();
- ap_Bool verify_2pts_equal();
- void get_current_ucs();
- ap_Bool set_current_ucs();
- void trans_wc2uc();
- void trans_uc2wc();
- void add_vector();
- void sub_vector();
- void cross_vector();
- ads_real dot_vector();
- ap_Bool normalize_vector();
- ap_Bool find_through_hole_depth();
- ap_Real find_maximum();
- ap_Real find_minimum();
- void get_model_extend();
- int get_yesno_from_user();
- ap_Bool verify_planes_equal();
-
-
- struct resbuf Echo1, Echo2;
-
- /* Command definition and dispatch table. */
-
- struct ads_comm {
- char *cmdname;
- void (*cmdfunc) ();
- };
-
- struct ads_comm cmdtab[] = {
-
- {/*MSG1*/"C:SOLDRILL", drill_hole_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(/*MSG2*/"DRILL: 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 (/*MSG3*/"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(/*MSG4*/"\nNew loaded command: SOLDRILL\n");
- }
-
-
- /*************************************************************************/
- /* .doc command_echo_off() */
- /*+
- Suppress command echo
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/command_echo_off()
- {
- ads_getvar (/*MSG0*/"CMDECHO", &Echo1);
- Echo2.restype = RTSHORT;
- Echo2.resval.rint = FALSE;
- ads_setvar (/*MSG0*/"CMDECHO", &Echo2);
- }
-
- /*************************************************************************/
- /* .doc command_echo_on() */
- /*+
- Resume command echo
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/command_echo_on()
- {
- ads_setvar (/*MSG0*/"CMDECHO", &Echo1);
- }
-
- /*************************************************************************/
- /* .doc drill_hole_func() */
- /*+
- This routine performs the following tasks:
-
- 1. Prompt the user to select a face from existing object.
- Only plane face will be accepted.
- 2. Verify whether the selected face lies in current ucs plane.
- 3. If "NO", store current ucs in matrix and set new ucs to
- align with the selected face.
- 4. Prompt user to select center, diameter and depth for the hole.
- 5. If the picked center point doesn't locate on the selected face,
- project it onto the face.
- 6. If through hole is desired, calculate the minimum depth
- required for drilling a through hole.
- 7. Create a cylindrical drilling tool and align it with
- the desired hole's position and orientation.
- 8. Subtract cylinder from the selected object to create a hole
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/drill_hole_func()
- {
- ap_Real diameter, depth, radius;
- ap_Trans3d m;
- ap_Objid object, cyl, result;
- ap_Featid face;
- ads_point p1, p2, p3, pc, pt;
- ads_point porg, px, py, xdir, ydir, zdir;
- ads_point pts[3], pnorm, normal;
- ap_Class pclass;
- int stat;
- ap_Bool reset_ucs = FALSE, through_hole = FALSE;
-
- /* Initialize API */
-
- stat = ap_init();
- if (stat != AP_NORMAL)
- goto Error1;
-
- /* Prompt user to select a face */
-
- stat = ap_sel_face (/*MSG5*/"\nSelect a planar face to drill the hole:\n",
- &object, &face);
- if (stat != AP_NORMAL) {
- ads_printf(/*MSG6*/"\nUnable to get the face.");
- goto Error1;
- }
-
- /* Retrieve three points p1, p2, p3 on the face and
- inward normal vector to the plane */
-
- stat = get_pts_from_face (object, face, p1, p2, p3, normal);
- if (stat == FALSE)
- goto Error1;
-
- /* Retrieve current ucs's origin, x-direction & y-direction */
-
- get_current_ucs (porg, xdir, ydir);
- cross_vector(xdir, ydir, zdir);
- normalize_vector(zdir, pnorm);
-
- /* Verify whether selected face lies in current ucs plane.
- If not, set new ucs to align with the selected face
- and move the ucsicon to new origin */
-
- stat = verify_planes_equal(porg, pnorm, p1, normal);
- if(stat == FALSE) {
- set_current_ucs (p1, p2, p3);
- turn_ucsicon(ORIGIN);
- reset_ucs = TRUE;
- }
-
- /* Prompt user for selection of center, diameter and depth */
-
- stat = get_hole_data(pt, &diameter, &depth);
- if (stat == FALSE) {
- goto Error2;
- } else if (depth < 0.0) {
- through_hole = TRUE;
- }
-
- radius = diameter / 2.0;
-
- /* Project point pt to the ucs plane of the selected face */
-
- pt[Z] = 0.0;
-
- /* Transform point pt from ucs to wcs coordinate */
-
- trans_uc2wc(pt, FALSE, pc);
-
- /* Check whether point pc locate inside the object */
-
- stat = ap_class_pt (object, pc, &pclass);
- if ((stat != AP_NORMAL) || (pclass == AP_INOBJECT)) {
- ads_printf(/*MSG7*/"\nInvalid center point.\n");
- goto Error2;
- }
-
- /* Compute the through hole depth */
-
- if (through_hole == TRUE) {
- stat=find_through_hole_depth(object, normal, pc, radius, &depth);
- if (stat == FALSE) {
- ads_printf(/*MSG8*/"\nUnable to find through hole depth.\n");
- goto Error2;
- }
- }
-
- /* Create a cylindrical tool to drill the hole */
-
- stat = ap_cylinder (radius, radius, depth, &cyl);
- if (stat != AP_NORMAL) {
- ads_printf(/*MSG9*/"\nUnable to create cylinder to drill hole.\n");
- goto Error2;
- }
-
- /* Move the tool and align it with the planed hole location */
-
- copy_point(pc, pts[0]);
- add_vector(pts[0], normal, pts[1]);
- ap_pts2xfm(pts, 2, m);
- ap_move_obj (cyl, m, TRUE);
-
- /* Subtract cylinder tool from the selected object */
-
- stat = ap_subtract (object, cyl, &result);
- if (stat != AP_NORMAL) {
- ads_printf(/*MSG10*/"\nUnable to drill hole.\n");
- goto Error2;
- }
-
- /* Display the result object on the screen */
-
- ap_post_obj (result, AP_POSTWIRE);
-
- /* Restore ucs back to original location before drilling */
-
- Error2:
- if(reset_ucs == TRUE) {
- add_vector(porg, xdir, px);
- add_vector(porg, ydir, py);
- set_current_ucs (porg, px, py);
- }
- Error1:
- ads_retvoid();
- return;
- }
-
- /*************************************************************************/
- /* .doc get_hole_data() */
- /*+
- This routine prompts the user to enter hole data.
- -*/
- /*************************************************************************/
- static ap_Bool
- /*FCN*/get_hole_data (pc, dia, depth)
- ads_point pc;
- ads_real *dia, *depth;
- {
- int stat;
-
- /* Initialization of wheel data for default input */
-
- pc[X] = 0.0;
- pc[Y] = 0.0;
- pc[Z] = 0.0;
- *dia = 1.0;
- *depth = 1.0;
-
- /* Acquire values of parameters associated with hole
- from the user and verify the validity of input data */
-
- stat = ads_getpoint (NULL, /*MSG11*/"\nCenter <0,0,0>: ", pc);
- if (stat == RTCAN) {
- return FALSE;
- }
-
- stat = ads_getreal (/*MSG12*/"\nDiameter <1.0>: ", dia);
- if (stat == RTCAN) {
- return FALSE;
- } else if (*dia <= 0.0) {
- ads_printf(/*MSG13*/"\nValue must be positive and nonzero.");
- return FALSE;
- }
-
- stat = ads_getreal (/*MSG14*/"\nDepth <through>: ", depth);
- if (stat == RTCAN) {
- return FALSE;
- } else if (stat == RTNONE) {
- *depth = -1.0;
- } else if (*depth <= 0.0) {
- ads_printf(/*MSG15*/"\nValue must be positive and nonzero.");
- return FALSE;
- }
-
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc turn_ucsicon() */
- /*+
- This routine will turn ucsicon on, off or move it to new origin
- -*/
- /*************************************************************************/
-
- static void
- /* FCN */turn_ucsicon(action)
- int action;
- {
- command_echo_off ();
- if (action == ON)
- ads_command (RTSTR, /*MSG16*/"_.UCSICON", RTSTR, /*MSG17*/"_ON", NULL);
- else if(action == ORIGIN)
- ads_command (RTSTR, /*MSG18*/"_.UCSICON", RTSTR, /*MSG19*/"_ORIGIN", NULL);
- else
- ads_command (RTSTR, /*MSG20*/"_.UCSICON", RTSTR, /*MSG21*/"_OFF", NULL);
-
- command_echo_on ();
- }
-
- /*************************************************************************/
- /* .doc get_pts_from_face() */
- /*+
- This routine performs the following tasks:
-
- 1. Verify that the selected face is a planar face.
- 2. Retrieve the origin of the face coordinate system (pt1).
- 3. Retrieve the x-direction of the face coordinate system.
- 4. Retrieve the y-direction of the face coordinate system.
- 5. Retrieve the inward face normal direction (norm).
- 6. Compute pt2 and pt3.
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/get_pts_from_face(object, face, pt1, pt2, pt3, norm)
- ap_Objid object;
- ap_Featid face;
- ads_point pt1, pt2, pt3, norm;
- {
- ads_point px, py;
- ap_Faceinfo *finfo;
- int stat;
-
- /* Retrieve face type and verify whether it is planar */
-
- stat = ap_get_faceinfo(object, face, &finfo);
- if (stat != AP_NORMAL) {
- ads_printf (/*MSG22*/"\nUnable to retrieve face information.");
- ads_retvoid();
- return FALSE;
- }
- if (finfo->stype != AP_PLANAR) {
- ads_printf (/*MSG23*/"\nThe selected face must be planar.");
- ads_retvoid();
- return FALSE;
- }
-
- /* Retrieve the origin of the face coordinate system */
-
- pt1[X] = finfo->face_rm[0][3];
- pt1[Y] = finfo->face_rm[1][3];
- pt1[Z] = finfo->face_rm[2][3];
-
- /* Retrieve x-direction of the face coordinate system */
-
- px[X] = finfo->face_rm[0][0];
- px[Y] = finfo->face_rm[1][0];
- px[Z] = finfo->face_rm[2][0];
-
- /* Retrieve y-direction of the face coordinate system */
-
- py[X] = finfo->face_rm[0][1];
- py[Y] = finfo->face_rm[1][1];
- py[Z] = finfo->face_rm[2][1];
-
- /* Retrieve inward face normal direction */
-
- norm[X] = - finfo->surf.pla.norm[X];
- norm[Y] = - finfo->surf.pla.norm[Y];
- norm[Z] = - finfo->surf.pla.norm[Z];
- add_vector(pt1, px, pt2);
- add_vector(pt1, py, pt3);
- ap_free_faceinfo(finfo);
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc copy_point() */
- /*+
- Duplicate a point, that is pt2 = pt1
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/copy_point (pt1, pt2)
- ads_point pt1, pt2;
- {
- pt2[X] = pt1[X];
- pt2[Y] = pt1[Y];
- pt2[Z] = pt1[Z];
- }
-
- /*************************************************************************/
- /* .doc verify_2pts_equal() */
- /*+
- Verify whether two points p1 & p2 are equal
- that is, within tolerance EPSILON
- -*/
- /*************************************************************************/
-
- 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 get_current_ucs() */
- /*+
- Retrieve current ucs's origin, x-direction & y-direction.
- Return them through arguments po, px & py respectively.
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/get_current_ucs(po, px, py)
- ads_point po, px, py;
-
- {
- struct resbuf ucso, ucsx, ucsy;
-
- ads_getvar (/*MSG0*/"UCSORG", &ucso);
- ads_getvar (/*MSG0*/"UCSXDIR", &ucsx);
- ads_getvar (/*MSG0*/"UCSYDIR", &ucsy);
-
- copy_point(ucso.resval.rpoint, po);
- copy_point(ucsx.resval.rpoint, px);
- copy_point(ucsy.resval.rpoint, py);
- }
- /*************************************************************************/
- /* .doc set_current_ucs() */
- /*+
- Reset current ucs by using three points p1, p2 & p3, where
- p1 = new origin
- p1p2 = new x-direction
- p1p2 x p1p3 = new z-direction
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/set_current_ucs(p1, p2, p3)
- ads_point p1, p2, p3;
- {
- ads_point pt1, pt2, pt3;
- int stat1, stat2, stat3, stat;
-
- stat1 = verify_2pts_equal (p1, p2);
- stat2 = verify_2pts_equal (p2, p3);
- stat3 = verify_2pts_equal (p3, p1);
- if ((stat1 == TRUE) || (stat2 == TRUE) || (stat3 == TRUE))
- return FALSE;
-
- trans_wc2uc(p1, FALSE, pt1);
- trans_wc2uc(p2, FALSE, pt2);
- trans_wc2uc(p3, FALSE, pt3);
-
- command_echo_off ();
- stat = ads_command(RTSTR, /*MSG24*/"_.ucs", RTSTR, /*MSG25*/"_3", RT3DPOINT,
- pt1, RT3DPOINT, pt2, RT3DPOINT, pt3, NULL);
-
- if (stat != RTNORM)
- {
- command_echo_on ();
- return FALSE;
- }
- command_echo_on ();
- 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 add_vector() */
- /*+
- Add two vectors cp = ap + bp
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/add_vector( ap, bp, cp)
- ads_point ap, bp, cp;
- {
- cp[X] = ap[X] + bp[X];
- cp[Y] = ap[Y] + bp[Y];
- cp[Z] = ap[Z] + bp[Z];
- }
-
- /*************************************************************************/
- /* .doc sub_vector() */
- /*+
- Subtract vector bp from vector ap with result cp = ap - bp
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/sub_vector(ap, bp, cp)
- ads_point ap, bp, cp;
- {
- cp[X] = ap[X] - bp[X];
- cp[Y] = ap[Y] - bp[Y];
- cp[Z] = ap[Z] - bp[Z];
- }
-
- /*************************************************************************/
- /* .doc cross_vector() */
- /*+
- Cross product of two vectors, cp = ap X bp.
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/cross_vector(ap, bp, cp)
- ads_point ap, bp, cp;
- {
- ads_point result;
-
- result[X] = ap[Y] * bp[Z] - ap[Z] * bp[Y];
- result[Y] = ap[Z] * bp[X] - ap[X] * bp[Z];
- result[Z] = ap[X] * bp[Y] - ap[Y] * bp[X];
- copy_point (result, cp);
- }
-
- /*************************************************************************/
- /* .doc dot_vector() */
- /*+
- Dot product of two vectors, The result = ap.bp
- -*/
- /*************************************************************************/
-
- static ads_real
- /*FCN*/dot_vector(ap, bp)
- ads_point ap, bp;
- {
- ads_real result;
-
- result = ap[X] * bp[X] + ap[Y] * bp[Y] + ap[Z] * bp[Z];
- return result;
- }
-
- /*************************************************************************/
- /* .doc normalize_vector() */
- /*+
- Normalize a vector, that is q = p/||p||
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/normalize_vector (p, q)
- ads_point p, q;
- {
- ap_Real temp, dis;
-
- temp = p[X]*p[X] + p[Y]*p[Y] + p[Z]*p[Z];
- if (temp < EPSILON * EPSILON)
- return FALSE;
-
- dis = sqrt (temp);
- q[X] = p[X] / dis;
- q[Y] = p[Y] / dis;
- q[Z] = p[Z] / dis;
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc find_through_hole_depth() */
- /*+
- This routine performs the following tasks:
-
- 1. Retrieve the diagonal corners of bounding box of current
- ACAD model space.
- 2. Initialize two arrays hmin[] = 0 & hmax[] = diagonal length.
- 3. Generate NRAY (17) number of sample rays of equal length (diagonal),
- starting from the selected face, toward the inside of the object,
- and ending at the outside of the object.
- 4. Place one ray at the center and the rest of them equally-spaced
- along the perimeter of the circle at the desired hole location.
- 5. For each ray, classify it against the selected object and
- break the ray into subsegments consisting of either inside, on or
- outside the object.
- 6. If none of the sample rays contains inside subsegment, we may
- conclude that the selected center point pc is an invalid
- location for drilling a hole. So set intersection = FALSE.
- 7. For each ray, if it contains more than one inside subsegment,
- then, the ray must have hit some free faces before it can
- completely penetrate through the object. If all the sample rays
- hit free faces before through the object, one may conclude that the
- drilling tool will encounter free faces before penetration.
- If this is the case, set seperation = TRUE, otherwise,
- seperation = FALSE.
- 8. For each ray, compute the length of first inside subsegment and
- store the length in array element hmin[i]. Similarly, compute
- the length from selected face to the beginning of the second
- inside subsegment and store the result in array element hmax[i].
- 9. Obtain h1 = max {hmin[i]} and h2 = min {hmax[i]}.
- 10. If seperation = TRUE, prompt the user whether to stop drilling
- at next free face.
- 11. If choice = YES, return either depth = h1 or depth = h2,
- depending on whether interfering with other free faces or not.
- 12. If separation = FALSE, return depth = diagonal length.
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/find_through_hole_depth(obj, norm, pc, rad, depth)
- ap_Objid obj;
- ads_point norm, pc; /* in wcs */
- ap_Real rad, *depth;
- {
- ap_Edgeinfo einfo;
- ap_Seglist *slist, *seg;
- ap_Real diagonal, angle, h1, h2, hmin[NRAY], hmax[NRAY];
- ads_point pmin, pmax, pd, ps, pe, pt, pq;
- int stat, choice, i, index, ndiv;
- ap_Bool separation, intersection;
-
- /* Retrieve the diagonal corners of bounding box
- for current ACAD model space */
-
- stat = ap_obj2extents (obj, TRUE, pmin, pmax);
- if (stat != AP_NORMAL) {
- ads_printf (/*MSG33*/"\nUnable to get bounding box for the object.");
- ads_retvoid();
- return FALSE;
- }
-
- /* Compute the length of the diagonal of the bounding box */
-
- diagonal = ads_distance(pmin, pmax);
-
- /* Initialization of arrays hmin[] & hmax[] */
-
- separation = TRUE;
- intersection = FALSE;
- for (i=0; i < NRAY; i++) {
- hmin[i] = 0.0;
- hmax[i] = diagonal;
- }
-
- /* Initialization of edge structure einfo which will
- be used to hold ray data for line classification */
-
- einfo.ctype = AP_LINE;
- einfo.edge_len = diagonal;
- einfo.s_parm = 0.0;
- einfo.e_parm = diagonal;
- ap_identity(einfo.edge_rm);
- copy_point(pc, ps);
- normalize_vector(norm, pd);
- ndiv = NRAY - 1;
-
- /* Generate a ray of diagonal length,
- starting from the hole center on the selected face,
- point toward inside of the object and,
- ending at outside of the object */
-
- pe[X] = ps[X] + pd[X] * diagonal;
- pe[Y] = ps[Y] + pd[Y] * diagonal;
- pe[Z] = ps[Z] + pd[Z] * diagonal;
-
- copy_point(ps, einfo.s_pt);
- copy_point(pe, einfo.e_pt);
-
- /* Classify the ray against the object */
-
- stat = ap_class_edge(obj, &einfo, &slist);
- if (stat != AP_NORMAL) {
- ads_printf (/*MSG26*/"\nUnable to classify center ray.");
- ads_retvoid();
- return FALSE;
- }
-
- /* Find the length of the first subsegment which is completely
- inside the object and store this length in hmin[0] */
-
- seg = slist;
- if (seg->seg.edge_class == AP_INOBJECT) {
- intersection = TRUE;
- hmin[0] = seg->seg.e_parm;
- seg = seg->segnext;
- }
-
- /* Find the length of the ray from the selected face to the beginning
- of the second inside subsegment and store it in hmax[0] */
-
- if (seg->seg.edge_class == AP_INOBJECT)
- hmax[0] = seg->seg.s_parm;
- else
- separation = FALSE;
-
- /* Transform the point pc in wcs into pq in ucs, remember
- that current ucs aligns with the selected face */
-
- trans_wc2uc(pc, FALSE, pq);
-
- /* Generate NRAY-1 number of sample rays of diagonal length,
- starting from the circle perimeter on the selected face,
- point toward inside of the object */
-
- for(i=1; i < NRAY; i++) {
- angle = 2.0 * (i - 1) * PI / ndiv;
- pt[X] = pq[X] + rad * cos(angle);
- pt[Y] = pq[Y] + rad * sin(angle);
- pt[Z] = 0.0;
- trans_uc2wc(pt, FALSE, ps);
-
- pe[X] = ps[X] + pd[X] * diagonal;
- pe[Y] = ps[Y] + pd[Y] * diagonal;
- pe[Z] = ps[Z] + pd[Z] * diagonal;
-
- copy_point(ps, einfo.s_pt);
- copy_point(pe, einfo.e_pt);
-
- /* Classify the ray against the object */
-
- stat = ap_class_edge(obj, &einfo, &slist);
- if (stat != AP_NORMAL) {
- ads_printf (/*MSG27*/"\nUnable to classify center ray.");
- return FALSE;
- }
-
- /* For each ray, obtain the length of the first subsegment
- that is completely inside the object and store
- this length in hmin[i] */
-
- seg = slist;
- if (seg->seg.edge_class == AP_INOBJECT) {
- intersection = TRUE;
- hmin[i] = seg->seg.e_parm;
- seg = seg->segnext;
- }
-
- /* For each ray, find the length of the ray from the selected
- face to the beginning of the second inside subsegment and
- store it in hmax[i] */
-
- if (seg->seg.edge_class == AP_INOBJECT)
- hmax[i] = seg->seg.s_parm;
- else
- separation = FALSE;
- }
-
- if(intersection == FALSE)
- return FALSE;
-
- h1 = find_maximum(hmin, NRAY, &index);
- h2 = find_minimum(hmax, NRAY, &index);
-
- if (separation == TRUE) {
- ads_printf(/*MSG28*/"\nStop drilling at next free face, Yes/<No>: ");
- choice = get_yesno_from_user(NO);
- if ((choice == YES) && (h2 >= h1)) {
- *depth = h1;
- return TRUE;
- } else if ((choice == YES) && (h2 < h1)) {
- ads_printf(/*MSG29*/"\nInterference drilling.");
- *depth = h2;
- return TRUE;
- } else if (choice == NO) {
- *depth = diagonal;
- return TRUE;
- } else {
- *depth = 0.0;
- return FALSE;
- }
- } else {
- *depth = diagonal;
- return TRUE;
- }
- }
-
- /*************************************************************************/
- /* .doc find_maximum() */
- /*+
- Find the maximum value among nt elements 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 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;
- }
-
- /*************************************************************************/
- /* .doc get_model_extend() */
- /*+
- Obtain the diagonal corners of bounding box of
- current AutoCAD model space.
- -*/
- /*************************************************************************/
- static void
- /*FNC*/get_model_extend (pmin, pmax)
- ads_point pmin, pmax;
- {
- struct resbuf Emax, Emin;
-
- ads_getvar (/*MSG0*/"EXTMAX", &Emax);
- ads_getvar (/*MSG0*/"EXTMIN", &Emin);
-
- copy_point(Emin.resval.rpoint, pmin);
- copy_point(Emax.resval.rpoint, pmax);
- }
-
- /*************************************************************************/
- /* .doc get_yesno_from_user() */
- /*+
- Prompt user to choice "Yes" or "No".
- The function return "YES", "NO" or "CANCEL" depending on
- user's action and the setup for default_choice.
- -*/
- /*************************************************************************/
- static int
- /*FNC*/get_yesno_from_user (default_choice)
- ap_Bool default_choice;
- {
- char inbuf[132];
- int status;
-
- ads_initget(0, /*MSG30*/"Yes No");
- strcpy(inbuf, "");
-
- status = ads_getkword (NULL, inbuf);
-
- if (status == RTCAN)
- {
- ads_retvoid ();
- return CANCEL;
- }
-
- else if ((default_choice == YES) && (status == RTNONE))
- {
- ads_retvoid ();
- return YES;
- }
-
- else if ((default_choice == NO) && (status == RTNONE))
- {
- ads_retvoid ();
- return NO;
- }
-
- else if (status == RTNORM)
- {
- if (strcmp (/*MSG31*/"Yes", inbuf) == 0)
- {
- ads_retvoid ();
- return YES;
- }
-
- else if (strcmp (/*MSG32*/"No", inbuf) == 0)
- {
- ads_retvoid ();
- return NO;
- }
-
- else
- {
- ads_retvoid ();
- return CANCEL;
- }
- }
-
- else
- return CANCEL;
- }
-
- /*************************************************************************/
- /* .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];
-
- sub_vector(org2, org1, dir);
- du = dot_vector (dir, norm1);
- dv = dot_vector (dir, norm2);
-
- if ((fabs (dx) < EPSILON) && (fabs (dy) < EPSILON) &&
- (fabs (dz) < EPSILON) && (fabs (du) < EPSILON) &&
- (fabs (dv) < EPSILON))
- return TRUE;
- else
- return FALSE;
- }
-
- /* EOF */
-