home *** CD-ROM | disk | FTP | other *** search
- /* Next available MSG number is 40 */
-
- /* SYMMETRY.C
-
- 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.
-
- ----------------------------------------------------------------------------
-
- DESCRIPTION:
-
- A sample API application.
-
- symmetry.c finds out if a region is circularly (radially) symmetric and/or
- symmetric with respect to its X-axis and/or Y-axis. X-axis and Y-axis are
- I and J components of the principal directions respectively. For circularly
- symmetric objects, the output is a "repetition factor".
-
-
- Command: symmetry
- Select a region: Pick the region
- Enter precision (1 to 8) <3>: 1
-
- "Precision" adjusts the level of calculations (similar to SOLSUBDIV
- variable used in mass property calculations). If the object has relatively
- small features, it is better to use a higher precision.
-
- Circular/X/Y/ <All>: x
-
- To check if the object is circularly symmetric, you select "Circular"
- option, and so on. The default option "All" lists all the symmetry
- information of the object.
-
- For "Circular" symmetry, you need to enter an upper limit for
- the calculations:
-
- Enter upper limit for circular symmetry (3 to 360) <20>: 90
-
- A repetition factor is searched between 3 and this upper limit.
- If the object has a repetition factor above this upper limit,
- it can not be found, and the object gets classified as "not circularly
- symmetric".
-
- A sample output is as follows:
-
- Region is circularly symmetric. Repetition factor is 5.
- Region is symmetric about X-axis (red).
- Region is not symmetric about Y-axis (blue).
-
- The X direction of the principal axis is shown in red, Y direction in
- blue.
-
-
- THEORY:
-
- Steps to find if a region has symmetry or not are as follows:
-
- 1) The region is tranformed so that its centroid coincides with the
- origin of WCS, I component of its principal directions lines up with
- the X axis of WCS, and J component of its principal directions lines
- up with the Y axis of WCS. These transformations are
- performed on a duplicate region, which is deleted at the end.
-
- 2) Rays are fired radially from origin and with "theta" degrees apart.
- The number of rays is determined by the "precision", i.e.
- # of rays = p * 12. Theta is 360 / (# of rays). A master array is formed
- from the edge classifications of these rays wrt the region.
-
- 3) The region is considered to be symmetric about X axis if a ray above
- X axis has the same classification as its counterpart below X axis. If the
- ray has been fired by an angle "alpha" its counterpart is the ray that's
- been fired by "360 - alpha" or "-alpha".
-
- 4) The region is considered to be symmetric about Y axis if a ray on the left
- of Y axis has the same classification as its counterpart on the right of Y axis.
- If the angle of the ray is "beta", its counterpart is the ray with angle
- "180 - beta".
-
- 5) To check if the region has a circular symmetry of factor n, an
- angle, "gamma = 360 / n" is defined. Then each ray in the master array is
- compared to the ray "gamma" degrees away (which gets classified),
- i.e. ray at "alpha" is compared to ray at "alpha + gamma". If all
- the rays pass the comparison test, then the region is considered to be
- circularly symmetric with a repetition factor of n. A range of numbers
- between 3 and "the upper limit" are input for n.
-
- */
-
- /***************************************************************************/
- /* INCLUDES */
- /***************************************************************************/
-
- #include <stdio.h>
- #include <time.h>
- #include <math.h>
- #include <string.h>
- #include "adslib.h"
- #include "aplib.h"
-
- /***************************************************************************/
- /* DEFINES */
- /***************************************************************************/
-
- #define DEFAULT_PRECISION 3
- #define DEFAULT_LIMIT 20
- #define PI 3.14159265358927
- #define EPS 1.0e-5
- #define EQUAL 1
- #define NOT_EQUAL 0
- #define TRUE 1
- #define FALSE 0
- #define NELEM(a) (sizeof a / sizeof a[0])
-
- /*************************************************************************/
- /* FUNCTION DECLARATIONS */
- /*************************************************************************/
-
- void find_sym();
- ap_Bool funcload();
- ap_Bool adjust();
- ap_Bool get_wcs_align();
- ap_Bool look_for_sym();
- ap_Bool create_list();
- ap_Bool get_ray_length();
- int circular();
- int x_axis();
- int y_axis();
- int not_equal();
- ap_Bool draw_axis();
- void trans_pt();
- void set_ucs();
- void set_wcs();
- void command_echo_off();
- void command_echo_on();
-
- struct resbuf echo1, echo2;
- ap_Real ray_length;
-
- struct ads_comm
- {
- char *cstring;
- void (*cfunc) ();
- };
-
- struct ads_comm asolid_comm[] =
- {
- {/*MSG1*/"C:SYMMETRY", find_sym},
- };
-
- /*************************************************************************/
- /* .doc main() */
- /*+
- -*/
- /*************************************************************************/
-
- void
- /*FCN*/main(argc, argv)
- int argc;
- char **argv;
- {
- int stat;
- int scode = RSRSLT;
-
- ads_init(argc, argv);
- for (;;)
- {
- if ((stat = ads_link(scode)) < 0)
- {
- ads_printf(/*MSG2*/"TEST: bad status from ads_link() = %d\n", stat);
- fflush(stdout);
- exit(1);
- }
- scode = RSRSLT; /* default return code */
-
- switch (stat)
- {
- case RQXLOAD: /* Load & register functions */
- scode = funcload() ? RSRSLT : RSERR;
- break;
-
- case RQXUNLD: /* Unloading */
- break;
-
- case RQSUBR: /* Evaluate external lisp function */
- if ((stat = ads_getfuncode()) < 0)
- {
- ads_printf(/*MSG3*/"\nUnrecognized command.\n");
- ads_retvoid();
- break;
- }
- if (asolid_comm[stat].cfunc != (void(*)())NULL)
- {
- (*asolid_comm[stat].cfunc)();
- ads_retvoid();
- }
- break;
-
- default:
- break;
- }
- }
- }
-
-
- /*************************************************************************/
- /* .doc funcload() */
- /*+
- Load external functions into AutoCAD system
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/funcload()
- {
- int i;
-
- for (i = 0; i < NELEM( asolid_comm ); i++)
- {
- if (ads_defun(asolid_comm[i].cstring, i) != RTNORM)
- {
- ads_printf(/*MSG4*/"Unable to register %s command.\n",
- asolid_comm[i].cstring);
- return FALSE;
- }
- }
-
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc find_sym() */
- /*+
- Find symmetry
- -*/
- /*************************************************************************/
-
- void
- /*FCN*/find_sym()
- {
- ads_name name;
- ap_Objid obj, region;
- ads_point pt;
- int flag, stat, p, csym = 0, xsym = 0, ysym = 0, asym = 0, limit;
- char op[20];
- ap_Objtype type;
-
- if(ap_init() != AP_NORMAL)
- return;
- command_echo_off();
- set_wcs();
-
- /* Prompt user to select the region */
-
- if(ads_entsel(/*MSG5*/"Select a region: ", name, pt) != RTNORM){
- ads_printf(/*MSG6*/"Selection failed.\n");
- goto Error1;
- }
- ads_printf("\n");
-
- /* Check if the entity is an object */
-
- if(ap_name2obj(name, &obj) != AP_NORMAL){
- ads_printf(/*MSG7*/"Selected entity is not an object.\n");
- goto Error1;
- }
-
- /* Check if the object is a region */
-
- if(ap_get_objtype(obj, &type) != AP_NORMAL){
- ads_printf(/*MSG8*/"API error: can not get the type of the object.\n");
- goto Error1;
- }
- if(type == AP_SOLID){
- ads_printf(/*MSG9*/"Selected entity is not a region.\n");
- goto Error1;
- }
-
- /* Prompt user for input parameters */
-
- p = DEFAULT_PRECISION;
- do{
- flag = FALSE;
- ads_initget(2 + 4, NULL);
- if ((stat = ads_getint(/*MSG10*/"Enter precision (1 to 8) <3>: ", &p)) == RTNORM){
- if(p > 8){
- ads_printf(/*MSG11*/"Precision should be less than 8.\n");
- flag = TRUE;
- }
- }
- if(stat == RTCAN)
- goto Error1;
- }while(flag);
-
- do{
- flag = FALSE;
- ads_initget(0, /*MSG12*/"Circular C X Y All A");
- strcpy(op, "");
- if (ads_getkword(/*MSG13*/"Circular/X/Y/ <All>: ", op) < 0)
- goto Error1;
- if (strlen(op) == 0)
- strcpy(op, /*MSG14*/"All");
-
- if(!strcmp(op, /*MSG15*/"Circular") || !strcmp(op, /*MSG16*/"C"))
- csym = 1;
- else if(!strcmp(op, /*MSG17*/"X"))
- xsym = 2;
- else if(!strcmp(op, /*MSG18*/"Y"))
- ysym = 3;
- else if(!strcmp(op, /*MSG19*/"All") || !strcmp(op, /*MSG20*/"A"))
- asym = 4;
- else{
- ads_printf(/*MSG21*/"Invalid operation. Please try again.\n");
- flag = TRUE;
- }
- }while(flag);
-
- if(csym || asym){
- limit = DEFAULT_LIMIT;
- do{
- flag = FALSE;
- ads_initget(2 + 4, NULL);
- if ((stat = ads_getint
- (/*MSG22*/"Enter upper limit for circular symmetry (3 to 360) <20>: ", &limit))
- == RTNORM){
- if(limit > 360 || limit < 3){
- ads_printf(/*MSG23*/"Upper limit should be between 3 and 360.\n");
- flag = TRUE;
- }
- }
- if(stat == RTCAN)
- goto Error1;
- }while(flag);
- }
-
- /* Position the region for symmetry calculations */
-
- if(adjust(obj, ®ion) != TRUE)
- goto Error;
-
- /* Find if the region is symmetric or not */
-
- if(look_for_sym(region, csym + xsym + ysym + asym, p, limit) != TRUE)
- goto Error;
-
- /* Delete the duplicate region */
-
- ap_del_obj(region);
-
- Error1:
- set_ucs();
- command_echo_on();
- ads_retvoid();
- return;
-
- Error:
- ap_del_obj(region);
- set_ucs();
- command_echo_on();
- ads_printf(/*MSG24*/"API error is encountered.\n");
- ads_retvoid();
- return;
- }
-
- /*************************************************************************/
- /* .doc adjust() */
- /*+
- This function duplicates the region, and positions it so that its centroid
- is at the origin of WCS and the principal directions are lined up with X
- and Y axis.
- -*/
- /*************************************************************************/
-
- ap_Bool
- /*FCN*/adjust(obj, region)
- ap_Objid obj, *region;
- {
- ap_Objid dup_region;
- ap_Trans3d forward, mat, al_wcs, trans;
- ap_Massprop mp;
- ap_Real angle;
-
- /* Duplicate the region */
-
- if(ap_dup_obj(obj, &dup_region) != AP_NORMAL)
- return FALSE;
- *region = dup_region;
-
- /* Get the matrix necessary to align region with XY plane of WCS */
-
- if(get_wcs_align(*region, forward, al_wcs) != TRUE)
- return FALSE;
-
- /* Align the region */
-
- if(ap_move_obj(*region, al_wcs, 1) != AP_NORMAL)
- return FALSE;
-
- /* Draw pricipal axis */
-
- if(draw_axis(*region, forward) != TRUE)
- return FALSE;
-
- /* Position the region so that its centroid coincides with the origin */
-
- if(ap_get_massprop(*region, &mp)!= AP_NORMAL)
- return FALSE;
- if(ap_translate(-mp.centroid.x, -mp.centroid.y, -mp.centroid.z, trans)!= AP_NORMAL)
- return FALSE;
- if(ap_move_obj(*region, trans, 0)!= AP_NORMAL)
- return FALSE;
-
- /* Rotate the region so that principal dir. line up with X and Y axes */
-
- angle = acos(mp.prindir[0][0]);
- if(mp.prindir[0][1] > 0)
- angle = -angle;
- if(ap_rotate_z(angle, mat)!= AP_NORMAL)
- return FALSE;
- if(ap_move_obj(*region, mat, 0)!= AP_NORMAL)
- return FALSE;
-
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc look_for_sym() */
- /*+
- Calls symmetry functions according to user input
- -*/
- /*************************************************************************/
-
- ap_Bool
- /*FCN*/look_for_sym(region, sym, p, limit)
- ap_Objid region;
- int sym, p, limit;
- {
- register i;
- int no, factor;
- ap_Seglist *slist[100];
-
- no = p * 12;
- ads_printf(/*MSG25*/"Looking for symmetry...\n");
-
- /* Create the classification array */
-
- if(create_list(region, slist, no) != TRUE)
- return FALSE;
-
- /* Circular Symmetry */
-
- if(sym == 1 || sym == 4){
- factor = circular(region, slist, no, limit);
- if(!factor)
- return FALSE;
- else if(factor > 0)
- ads_printf(/*MSG26*/"Region is circularly symmetric. Repetition factor is %d.\n", factor);
- else ads_printf(/*MSG27*/"Region is not circularly symmetric.\n");
- }
-
- /* X-axis Symmetry */
-
- if(sym == 2 || sym == 4){
- if(x_axis(slist, no))
- ads_printf(/*MSG28*/"Region is symmetric about X-axis (red).\n");
- else ads_printf(/*MSG29*/"Region is not symmetric about X-axis (red).\n");
- }
-
- /* Y-axis Symmetry */
-
- if(sym == 3 || sym == 4){
- if(y_axis(slist, no))
- ads_printf(/*MSG30*/"Region is symmetric about Y-axis (blue).\n");
- else ads_printf(/*MSG31*/"Region is not symmetric about Y-axis (blue).\n");
- }
-
- /* Free the classification list */
-
- for(i = no - 1; i >= 0; i--)
- free(slist[i]);
-
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc create_list() */
- /*+
- This function throws rays radially, classifies them, and stores the
- classifications in a list.
- -*/
- /*************************************************************************/
-
- ap_Bool
- /*FCN*/create_list(region, slist, no)
- ap_Objid region;
- ap_Seglist *slist[];
- int no;
- {
- register j;
- ap_Edgeinfo einfo;
- ap_Real theta = 0.0, tplus;
-
- if(get_ray_length(region) != TRUE)
- return FALSE;
-
- /* Define the edge to be classified */
-
- einfo.ctype = AP_LINE;
- einfo.edge_len = ray_length;
- einfo.s_parm = 0.0;
- einfo.e_parm = ray_length;
- einfo.s_pt[0] = einfo.s_pt[1] = einfo.s_pt[2] = 0.0;
- einfo.e_pt[2] = 0.0;
-
- /* Rotate and classify the edge wrt to the region */
-
- tplus = 2 * PI / no;
- for(j = 0; j < no; j++){
- if(ap_rotate_z(theta, einfo.edge_rm) != AP_NORMAL)
- return FALSE;
- einfo.e_pt[0] = ray_length * einfo.edge_rm[0][0];
- einfo.e_pt[1] = ray_length * einfo.edge_rm[0][1];
- if(ap_class_edge(region, &einfo, &slist[j]) != AP_NORMAL)
- return FALSE;
- theta += tplus;
- }
-
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc circular() */
- /*+
- Looks for circular symmetry
- -*/
- /*************************************************************************/
-
- int
- /*FCN*/circular(region, slist, no, limit)
- ap_Objid region;
- ap_Seglist *slist[];
- int no, limit;
- {
- int flag, factor = -1;
- register j, k;
- ap_Edgeinfo einfo;
- ap_Real div, theta, theta2, tplus;
- ap_Seglist *list2;
-
- /* Define the edge to be classified */
-
- einfo.ctype = AP_LINE;
- einfo.edge_len = ray_length;
- einfo.s_parm = 0.0;
- einfo.e_parm = ray_length;
- einfo.s_pt[0] = einfo.s_pt[1] = einfo.s_pt[2] = 0.0;
- einfo.e_pt[2] = 0.0;
- tplus = 2 * PI / no;
-
- /* For every possible factor less than or equal to limit */
-
- for(k = limit; k > 2; k--){
- div = 6.283185307 / k;
- flag = EQUAL;
- theta = 0.0;
- for(j = 0; j < no; j++){
-
- /* Rotate and classify the edge wrt to the region */
-
- theta2 = theta + div;
- if(ap_rotate_z(theta2, einfo.edge_rm) != AP_NORMAL)
- return FALSE;
- einfo.e_pt[0] = ray_length * einfo.edge_rm[0][0];
- einfo.e_pt[1] = ray_length * einfo.edge_rm[0][1];
- if(ap_class_edge(region, &einfo, &list2) != AP_NORMAL)
- return FALSE;
-
- /* Compare the classification to the one in the classification list */
-
- if(not_equal(slist[j], list2)){
- flag = NOT_EQUAL;
- break;
- }
- ap_free_seglist(list2);
- theta += tplus;
- }
- if(flag) {
- factor = k;
- break;
- }
- }
- return factor;
- }
-
- /*************************************************************************/
- /* .doc x_axis() */
- /*+
- Looks for symmetry about X axis
- -*/
- /*************************************************************************/
-
- int
- /*FCN*/x_axis(slist, no)
- ap_Seglist *slist[];
- {
- register j, k;
- int flag = TRUE;
-
- /* Compare the classifications on both sides of the X axis */
-
- for(j = 1, k = no - 1; j != k; j++, k--)
- if(not_equal(slist[j], slist[k])){
- flag = FALSE;
- break;
- }
-
- return flag;
- }
-
- /*************************************************************************/
- /* .doc y_axis() */
- /*+
- Looks for symmetry about Y axis
- -*/
- /*************************************************************************/
-
- int
- /*FCN*/y_axis(slist, no)
- ap_Seglist *slist[];
- {
- register j, k;
- int flag = TRUE;
-
- /* Compare the classifications on both sides of the Y axis */
-
- for(j = no / 4 + 1, k = no / 4 - 1; j != k; j++, k--){
- if(k < 0) k = no - 1;
- if(not_equal(slist[j], slist[k])){
- flag = FALSE;
- break;
- }
- }
-
- return flag;
- }
-
- /*************************************************************************/
- /* .doc not_equal() */
- /*+
- Compares two segments returned from edge classification
- -*/
- /*************************************************************************/
-
- int
- /*FCN*/not_equal(seg1, seg2)
- ap_Seglist *seg1, *seg2;
- {
- ap_Real t1a, t2a, t1b, t2b;
- ap_Class class1, class2;
-
-
- for(;;){
- if(!seg1 && !seg2)
- return FALSE;
- if((seg1 && !seg2) || (!seg1 && seg2))
- return TRUE;
- t1a = seg1->seg.s_parm;
- t1b = seg1->seg.e_parm;
- class1 = seg1->seg.edge_class;
- t2a = seg2->seg.s_parm;
- t2b = seg2->seg.e_parm;
- class2 = seg2->seg.edge_class;
- if(class1 != class2 || fabs(t1a - t2a) > EPS || fabs(t1b - t2b) > EPS)
- return TRUE;
- seg1 = seg1->segnext;
- seg2 = seg2->segnext;
- }
- }
-
- /*************************************************************************/
- /* .doc draw_axis() */
- /*+
- Gets the principal directions and draws them at the centroid
- of the region.
- -*/
- /*************************************************************************/
-
- ap_Bool
- /*FCN*/draw_axis(region, forward)
- ap_Objid region;
- ap_Trans3d forward;
- {
-
- ap_Massprop mp;
- ads_point c, p0, p1;
- ap_Trans3d backward;
- struct resbuf rb;
- ap_Real vsize, scale;
-
-
- /* Get its principal directions */
-
- if(ap_get_massprop(region, &mp) != AP_NORMAL)
- return FALSE;
- c[0] = mp.centroid.x;
- c[1] = mp.centroid.y;
- c[2] = mp.centroid.z;
-
- /* Scale lines wrt current viewsize */
-
- ads_getvar(/*MSG0*/"VIEWSIZE", &rb);
- vsize = rb.resval.rreal;
- scale = 0.2 * vsize;
-
- p0[0] = mp.prindir[0][0] * scale + c[0];
- p0[1] = mp.prindir[0][1] * scale + c[1];
- p0[2] = mp.prindir[0][2] * scale + c[2];
- p1[0] = mp.prindir[1][0] * scale + c[0];
- p1[1] = mp.prindir[1][1] * scale + c[1];
- p1[2] = mp.prindir[1][2] * scale + c[2];
-
- /* Transform the vectors onto the original region */
-
- if(ap_invert(forward, backward) != AP_NORMAL)
- return FALSE;
- trans_pt(p0, backward);
- trans_pt(p1, backward);
- trans_pt(c, backward);
-
- /* Draw X direction in red */
-
- ads_grdraw(c, p0, 1, 0);
-
-
- /* Draw Y direction in blue */
-
- ads_grdraw(c, p1, 5, 0);
-
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc trans_pt() */
- /*+
- Tranforms a given point by a given matrix
- -*/
- /*************************************************************************/
-
- void
- /*FCN*/trans_pt(pt, m)
- ads_point pt;
- ap_Trans3d m;
- {
- ap_Real x, y, z;
-
- x = pt[0]; y = pt[1]; z = pt[2];
-
- pt[0] = x * m[0][0] + y * m[0][1] + z * m[0][2] + m[0][3];
- pt[1] = x * m[1][0] + y * m[1][1] + z * m[1][2] + m[1][3];
- pt[2] = x * m[2][0] + y * m[2][1] + z * m[2][2] + m[2][3];
- }
-
- /*************************************************************************/
- /* .doc set_ucs() */
- /*+
- Reset current ucs by "prev" option of UCS command
- -*/
- /*************************************************************************/
-
- void
- /*FCN*/set_ucs()
- {
- ads_command(RTSTR, /*MSG32*/"_.ucs", RTSTR, /*MSG33*/"_prev", NULL);
- ads_command (RTSTR, /*MSG34*/"_.UCSICON", RTSTR, /*MSG35*/"_ON", NULL);
- }
-
- /*************************************************************************/
- /* .doc set_wcs() */
- /*+
- Set wcs by "WCS" option of UCS command
- -*/
- /*************************************************************************/
-
- void
- /*FCN*/set_wcs()
- {
- ads_command (RTSTR, /*MSG36*/"_.UCSICON", RTSTR, /*MSG37*/"_OFF", NULL);
- ads_command(RTSTR, /*MSG38*/"_.ucs", RTSTR, /*MSG39*/"_world", NULL);
- }
-
- /*************************************************************************/
- /* .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 get_wcs_align() */
- /*+
- Aligns the region with the XY plane of WCS.
- -*/
- /*************************************************************************/
-
- ap_Bool
- /*FCN*/get_wcs_align(region, forward, al_wcs)
- ap_Objid region;
- ap_Trans3d forward, al_wcs;
- {
- ap_Edgeinfo *einfo;
- ap_Featid eid = 1;
- ap_Objinfo info;
-
- /* Get any edge rigid motion matrix . This matrix defines the plane */
- /* the region is on. */
-
- if(ap_get_edgeinfo(region, eid, &einfo) != AP_NORMAL)
- return FALSE;
- if(ap_invert(einfo->edge_rm, forward) != AP_NORMAL)
- return FALSE;
-
- /* Form the destination matrix */
-
- if(ap_get_objinfo(region, &info) != AP_NORMAL)
- return FALSE;
- if(ap_compose(forward, info.mat, al_wcs) != AP_NORMAL)
- return FALSE;
-
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc get_ray_length() */
- /*+
- Calculates the extents of the region and assigns a suitable ray length
- for classification.
- -*/
- /*************************************************************************/
-
- ap_Bool
- /*FCN*/get_ray_length(region)
- ap_Objid region;
- {
- ads_point min, max;
-
- if(ap_obj2extents(region, FALSE, min, max) != AP_NORMAL)
- return FALSE;
- ray_length = ads_distance(min, max);
-
- return TRUE;
- }
-
- /*EOF*/
-