home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-06-17 | 77.1 KB | 2,626 lines |
- /* Next available MSG number is 115 */
-
- /************************************************************************
- Name: tutor.c
-
- Description: AME/API sample program for API tutorial.
-
- 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. *
- * *
- * *
- * The objective of this tutorial program is to illustrate the *
- * fundamental concepts, data structure and 3D solid modelling power *
- * of AME/API application programming interface. The program uses a *
- * wide variety of API functions to build practical utility and *
- * applications. It is designed specifically for beginners aiming *
- * at ease of understanding, self-learning and full coverage of the *
- * the API scope. The tutorial program encompasses the following key *
- * API features: *
- * *
- * *
- * Object creation and manipulation *
- * Interrogation of topological relationships *
- * Object information data structure *
- * Face information data structure *
- * Edge information data structure *
- * Entity membership classification *
- * Mass properties application *
- * *
- * *
- * Seven new commands are available in this program to illustrate *
- * the principle and technique associated with the above seven key *
- * API features respectively. The commands set and the corresponding *
- * function calls are shown as follows: *
- * *
- * SOLPIPE - create_pipe() *
- * SOLTOPOL - query_topology_relations() *
- * SOLTRACE - trace_object_history() *
- * SOLNORM - query_face_normal *
- * SOLTAN - query_edge_tangent() *
- * SOLCLASS - classify_entity_membership() *
- * SOLUCSPD - set_ucs_to_prindir() *
- * *
- * *
- * The command "SOLPIPE" illustrates a typical example for object *
- * creation, manipulation and display. It allows the user to create *
- * a geometric model of pipe by specifying inner and outer diameters, *
- * start and end points of the pipe. In API, the geometry of a simple *
- * object can be created in several different ways. These include *
- * primitive (cylinder, cone, sphere, torus, wedge), extruding and *
- * revolving a 2D polyline or region. After solid models of simple *
- * objects are created, they can be combined into complex solid *
- * (called composite solid) by Boolean operations such as union, *
- * intersection and subtraction. They can be edited by scaling *
- * cutting, separation and deletion. Objects can be moved and rotated *
- * as rigid motion by matrix transformation. API provides various *
- * methods for user to obtain the desired 4X4 transformation matrix *
- * by translation, rotating about X, Y, Z and arbitrary axis *
- * respectively, axial alignment, 3-points locating and access to *
- * current ucs matrix etc. In API environment, all new objects are *
- * created in world coordinate system and are always invisible until *
- * you actually post them on the screen. *
- * *
- * Command: solpipe *
- * Enter inner diameter <0.8>: *
- * Enter outer diameter <1.0>: *
- * Start point <0,0,0>: *
- * End point <0,0,1>: *
- * *
- * *
- * The command "SOLTOPOL" illustrates an example for querying *
- * topological relationship. It counts the total number of faces, *
- * edges and vertices associated with a selected object. *
- * Solid models are established on the basis of complete geometric *
- * information and sound topological relationship. The topological *
- * elements of an object consist of bodys, faces, edges and vertices. *
- * The object's topology deals with the structure and adjacency of *
- * the topological elements such as finding all edges surrounding a *
- * given vertex, finding the two faces sharing the given edge, *
- * finding all edges associated with a given face etc. ap_Facelist *
- * and ap_Edgelist are the data structures that can support these *
- * applications. *
- * *
- * Command: SOLTOPOL *
- * Select an object: *
- * *
- * *
- * The command "SOLTRACE illustrates how to traverse CSG tree and *
- * retrieve object information data structure from a given object. *
- * The object information data structure ap_Objinfo contains *
- * object_type, sizes, material, color, transformation matrix, *
- * parent, left child and right child. The object type may include *
- * box, cylinder,cone, sphere, torus, wedge, composite, extrusion, *
- * revolution, fillet and chamfer. Each object type is defined by *
- * the associated parameters such as length, width and height with *
- * respect to world coordinate system at its own initial position. *
- * THe transformation matrix reflects the current location and *
- * orientation of the object in the world coordinate system. Parent, *
- * left child and right child are created to form CSG binary tree *
- * structure for boolean operations. *
- * *
- * Command: SOLTRACE *
- * Select an object: *
- * *
- * *
- * The command "SOLNORM" illustrates how to retrieve and use face *
- * information data structure to verify whether a specified point *
- * is on a selected face or not. It calculates the unit normal to *
- * the selected face at specified point or its projection on the face. *
- * Face information data structure ap_Faceinfo contains surface_type, *
- * surface_parameters, transformation matrix, and perimeter. *
- * Currently, API supports five types of surfaces: planar, cylinder, *
- * conical, spherical, and toroidal. Each type of surface is defined *
- * by the associated parameters such as x_radius and y_radius at *
- * initial position with respect to wcs. The transformation matrix *
- * represents the current location and orientation of the surface *
- * in the global world coordinate system. *
- * *
- * Command: SOLNORM *
- * Select a face: *
- * Point on the face: *
- * *
- * *
- * The command "SOLTAN" illustrates how to retrieve and use edge *
- * information to project a specified point onto a selected edge. *
- * It calculates the unit tangent of the selected edge at the *
- * specified point or its projection on the edge. The edge *
- * information data structure ap_Edgeinfo contains curve_type, *
- * parameters, transformation matrix, endpoints and length. *
- * In this release, API supports six types of curve: line, ellipse, *
- * parabola, hyperbola, cylcyl and concon. Each type of curve is *
- * defined by the associated parameters such as x_radius and y_radius *
- * at initial position with respect to world coordinate system. The *
- * transformation matrix stores the current location and orientation *
- * of the curve in the world coordinate system. *
- * *
- * Command: SOLTAN *
- * Select an edge: *
- * Point on the edge: *
- * *
- * *
- * The command "SOLCLASS" illustrates how to use API functions *
- * to classify a point or a line against a selected object. *
- * Entity membership classification is the fundamentals of any solid *
- * modeling system. It classifies point, lines or curves with *
- * respect to a solid as either on, in or out of the object. *
- * In the case of partially in and partially out, it breaks the *
- * curve into segments and classifies them as either on, in *
- * or out of a given object. The data structures relating to the *
- * membership classification are ap_Seglist, ap_Edgeseg and *
- * ap_Class. *
- * *
- * Command: SOLCLASS *
- * Line/<Point>: P *
- * Point <0,0,0>: *
- * Select an object: *
- * *
- * Command: SOLCLASS *
- * Line/<Point>: L *
- * From <0,0,0>: *
- * To <0,0,1>: *
- * Select an object: *
- * *
- * The command "SOLUCSPD" uses mass property data structure to obtain *
- * centroid and principal moment directions from a given object. *
- * It then uses these information to reset the current ucs to locate *
- * at the centroid and align it to the principal moment directions *
- * of the selected object. The mass properties data structure *
- * ap_Massprop contains information such as mass, volume, area *
- * centroid, moment of inertia, product of inertia, radii of gyration *
- * and principal mement directions. *
- * *
- * Command: SOLUCSPD *
- * Select an object: *
- * *
- * *
- * To use these new commands, you have to compile the program and *
- * xload the executable code (after loading AME) into AutoCAD system. *
- * *
- **************************************************************************
-
-
- Modification history:
- Refer to the RCS section at the end of this file.
-
- Bugs and restrictions on use:
-
- Notes:
-
- **************************************************************************/
-
-
- /*************************************************************************/
- /* Includes */
- /*************************************************************************/
-
- #include <stdio.h>
- #include <math.h>
- #include <adslib.h>
- #include <aplib.h>
-
- /*************************************************************************/
- /* Defines */
- /*************************************************************************/
-
- #define PI 3.141596
- #define EPSILON 1.0e-6
- #define POINT 0
- #define LINE 1
- #define RED 1
- #define YELLOW 2
- #define BLUE 3
- #define PMAX 16
- #define OFF 0
- #define ON 1
- #define ORIGIN 2
-
- #define MALLOC(x) ((x *) malloc ((unsigned long)sizeof (x)))
- #define CALLOC(n, x) ((x *) calloc (n, (unsigned long)sizeof(x)))
- #define REALLOC(p, n, x) ((x *) realloc (p, n*(unsigned long) \
- sizeof(x)))
-
- #ifndef ELEMENTS
- #define ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
- #endif
-
- struct resbuf Echo1, Echo2;
-
- /*************************************************************************/
- /* Typedefs */
- /*************************************************************************/
-
- typedef struct vertex_table {
- unsigned long nv;
- unsigned long size;
- ads_point *fv;
- } v_table;
-
- /*************************************************************************/
- /* Global variables */
- /*************************************************************************/
-
- struct resbuf Echo1, Echo2;
- int table_size = 50;
- int step = 10;
- int gap = 2;
- int screen_pagelen = 24;
- int screen_lineno = 0;
-
- /*************************************************************************/
- /* Function type declaration */
- /*************************************************************************/
-
- /* main & ads support functions */
-
- void main();
- int funcload();
- void print_new_command_set();
- void command_echo_off();
- void command_echo_on();
-
- /* Functions for solpipe command */
-
- void create_pipe ();
- ap_Bool get_pipe_data();
-
- /* Functions for soltopol command */
-
- void query_topology_relations();
- ap_Bool count_vertices_of_obj();
- v_table *init_vtable();
- ap_Bool insert_pt_to_vtable();
- void free_vtable();
-
- /* Functions for soltrace command */
-
- void trace_object_history();
- ap_Bool select_object();
- ap_Bool traverse_and_dump_tree();
- ap_Bool linechk();
- void print_obj_info();
- void print_trans_matrix();
- void print_pline_vertex();
-
- /* Functions for solnorm command */
-
- void query_face_normal();
- ap_Bool verify_pt_on_surface();
- ap_Bool verify_pt_on_plane();
- ap_Bool verify_pt_on_cyl();
- ap_Bool verify_pt_on_cone();
- ap_Bool verify_pt_on_sph();
- ap_Bool verify_pt_on_tor();
-
- /* Functions for soltan command */
-
- void query_edge_tangent();
- ap_Bool proj_pt_on_curve();
- ap_Bool evalu_pt_on_curve();
-
- /* Functions for solclass command */
-
- void classify_entity_membership();
- void print_pt_class();
- ap_Bool get_line_data();
- ap_Bool make_edgeinfo_from_line();
- void print_line_class();
-
- /* Functions for solucspd command */
-
- void set_ucs_to_prindir();
- ap_Bool get_region_pts();
- ap_Bool set_current_ucs();
- void turn_ucsicon();
-
- /* Functions for graphics support */
-
- ap_Bool draw_virtual_arrow();
- ap_Bool draw_virtual_arrowhead();
- ap_Bool draw_virtual_line();
- ap_Bool draw_virtual_circle();
-
- /* Mathematic utilitity functions */
-
- ap_Bool get_xdir_from_zdir();
- void copy_point();
- void set_point();
- ap_Bool verify_2pts_equal();
- void combine_vector();
- ap_Bool normalize_vector();
- void cross_vector();
- void trans_pt_by_matrix();
- void trans_uc2wc();
- void trans_wc2uc();
- ads_real find_minimum();
-
-
- /*************************************************************************/
- /* Commands definition and dispatch table */
- /*************************************************************************/
-
- struct ads_comm {
- char *cmdname;
- void (*cmdfunc) ();
- };
-
- struct ads_comm cmdtab[] = {
- {/*MSG1*/"C:SOLPIPE", create_pipe},
- {/*MSG2*/"C:SOLTOPOL", query_topology_relations},
- {/*MSG3*/"C:SOLTRACE", trace_object_history},
- {/*MSG4*/"C:SOLNORM", query_face_normal},
- {/*MSG5*/"C:SOLTAN", query_edge_tangent},
- {/*MSG6*/"C:SOLCLASS",classify_entity_membership},
- {/*MSG7*/"C:SOLUCSPD",set_ucs_to_prindir},
- };
-
-
- /*************************************************************************/
- /* .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(/*MSG8*/"TUTOR: 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 (/*MSG9*/"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() */
- /*+
- Print new commands on the screen when the program is loaded
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/print_new_command_set()
- {
- ads_printf(/*MSG10*/"\nNew loaded commands:");
- ads_printf(/*MSG11*/"\nSOLPIPE, SOLTOPOL, SOLTRACE, SOLNORM, ");
- ads_printf(/*MSG12*/"SOLTAN, SOLCLASS, SOLUCSPD\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 create_pipe() */
- /*+
- This routine executes SOLPIPE command and creates a pipe
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/create_pipe()
-
- {
- ap_Real pipe_d1 = 0.8;
- ap_Real pipe_d2 = 1.0;
- ap_Real rad1, rad2, pipe_l;
- static ads_point pts[3], pt1, pt2;
- ap_Trans3d matrix;
- ap_Objid Cyl1, Cyl2, Pipe;
- int stat;
-
- /* Initialize API */
-
- stat = ap_init();
- if (stat != AP_NORMAL)
- goto Error;
-
- /* Prompt pipe data from the user */
-
- stat = get_pipe_data(&pipe_d1, &pipe_d2, pt1, pt2);
- if (stat == FALSE)
- goto Error;
-
- /* Convert pipe diameter to radius and calculate pipe length */
-
- rad1 = pipe_d1 / 2.0;
- rad2 = pipe_d2 / 2.0;
- pipe_l = ads_distance(pt1, pt2);
-
- /* Create inner cylinder */
-
- stat = ap_cylinder (rad1, rad1, pipe_l, &Cyl1);
- if (stat != AP_NORMAL) {
- ads_printf(/*MSG13*/"\nUnable to create cylinder.");
- goto Error;
- }
-
- /* Create outer cylinder */
-
- stat = ap_cylinder (rad2, rad2, pipe_l, &Cyl2);
- if (stat != AP_NORMAL) {
- ads_printf(/*MSG14*/"\nUnable to create cylinder.");
- goto Error;
- }
-
- /* Subtract inner from outer cylinder to produce a pipe */
-
- stat = ap_subtract (Cyl2, Cyl1, &Pipe);
- if (stat != AP_NORMAL) {
- ads_printf(/*MSG15*/"\nUnable to create pipe.\n");
- goto Error;
- }
-
- /* Transform points pt1 & pt2 from UCS into WCS */
-
- trans_uc2wc(pt1, FALSE, pts[0]);
- trans_uc2wc(pt2, FALSE, pts[1]);
-
- /* Setup transformation matrix to align pipe's center line
- from Z-axis to new direction specified by pt1 & pt2 */
-
- ap_pts2xfm(pts, 2, matrix);
-
- /* Move pipe to new location by the matrix */
-
- ap_move_obj (Pipe, matrix, TRUE);
-
- /* Display the pipe on the screen */
-
- ap_post_obj (Pipe, AP_POSTWIRE);
-
- Error:
- ads_retvoid();
- return;
- }
-
- /*************************************************************************/
- /* .doc get_pipe_data() */
- /*+
- This routine prompts the user to enter pipe's data of
- inner and outer diameters, start and end points.
- -*/
- /*************************************************************************/
- static ap_Bool
- /*FCN*/get_pipe_data(dia1, dia2, pc1, pc2)
- ads_real *dia1, *dia2;
- ads_point pc1, pc2;
- {
- int stat;
-
- /* Initialization of data for default */
-
- *dia1 = 0.8;
- *dia2 = 1.0;
- set_point(0.0, 0.0, 0.0, pc1);
- set_point(0.0, 0.0, 1.0, pc2);
-
- stat = ads_getreal (/*MSG16*/"\nEnter inner diameter <0.8>: ", dia1);
- if (stat == RTCAN)
- return FALSE;
-
- /* Verify positive pipe inner diameter */
-
- if (*dia1 <= 0.0) {
- ads_printf(/*MSG17*/"\nInvalid pipe diameter.");
- return FALSE;
- }
-
- stat = ads_getreal (/*MSG18*/"\nEnter outer diameter <1.0>: ", dia2);
- if (stat == RTCAN)
- return FALSE;
-
- /* Verify positive pipe outer diameter */
-
- if ((*dia2 <= 0.0) || (*dia2 <= *dia1)) {
- ads_printf(/*MSG19*/"\nInvalid pipe diameter.");
- return FALSE;
- }
-
- /* Prompt the user to select the start point for the pipe */
-
- stat = ads_getpoint (NULL, /*MSG20*/"\nStart point <0,0,0>: ", pc1);
- if ((stat == RTCAN) || (stat == RTERROR))
- return FALSE;
-
- /* Prompt the user to select the end point for the pipe */
-
- stat = ads_getpoint (pc1, /*MSG21*/"\nEnd point <0,0,1>: ", pc2);
- if ((stat == RTCAN) || (stat == RTERROR))
- return FALSE;
-
- /* Verify that the selected two points are not coincident */
-
- stat = verify_2pts_equal(pc1, pc2);
- if(stat == TRUE) {
- ads_printf (/*MSG22*/"\nInvalid pipe length.\n");
- return FALSE;
- }
-
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc query_topology_relations() */
- /*+
- This routine counts and outputs the total number of faces,
- edges and verticies of a given solid
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/query_topology_relations()
- {
- ap_Objid Object;
- ap_Edgelist *elist, *el;
- ap_Facelist *flist, *sl;
- ads_name chosen;
- int stat;
- long nface, nedge, nvertex;
- ads_point loc;
-
- /* Initialize API */
-
- stat = ap_init();
- if (stat != AP_NORMAL)
- goto Error0;
-
- stat = select_object(&Object, chosen, loc);
- if(stat == FALSE)
- goto Error0;
-
- /* Highlight the selected solid */
-
- ads_redraw(chosen, 3);
-
- stat = ap_obj2faces(Object, FALSE, &flist);
- if (stat != AP_NORMAL) {
- ads_printf (/*MSG23*/"\nUnable to retrieve face list.");
- goto Error1;
- }
-
- /* count the faces */
-
- nface = 0;
- for(sl=flist; sl != NULL; sl=sl->facenext)
- nface++;
- ap_free_facelist(flist);
-
- stat = ap_obj2edges(Object, FALSE, &elist);
- if (stat != AP_NORMAL) {
- ads_printf (/*MSG24*/"\nUnable to retrieve edge list.");
- goto Error1;
- }
-
- /* count the edges */
-
- nedge = 0;
- for(el=elist; el != NULL; el=el->edgenext)
- nedge++;
- ap_free_edgelist(elist);
-
- /* count the vertices */
-
- stat = count_vertices_of_obj(Object, &nvertex);
-
- ads_printf (/*MSG25*/"\nNumber of faces = %d", nface);
- ads_printf (/*MSG26*/"\nNumber of edges = %d", nedge);
- ads_printf (/*MSG27*/"\nNumber of vertices = %d", nvertex);
-
- /* Dehighlight the selected solid */
-
- Error1:
- ads_redraw(chosen, 4);
-
- Error0:
- ads_retvoid();
- return;
- }
-
- /*************************************************************************/
- /* .doc count_vertices_of_obj() */
- /*+
- This routine counts the total number of verticies
- of a given solid
- -*/
- /*************************************************************************/
- static ap_Bool
- /*FCN*/count_vertices_of_obj(sol, nv)
- ap_Objid sol;
- long *nv;
- {
- v_table *vtb;
- ap_Edgelist *elist, *el;
- ads_point p1, p2;
- int stat;
-
- stat = ap_obj2edges(sol, TRUE, &elist);
- if (stat != AP_NORMAL) {
- ads_printf (/*MSG28*/"\nUnable to retrieve edge list.");
- return FALSE;
- }
-
- vtb = init_vtable();
- if (vtb == NULL) {
- ads_printf (/*MSG29*/"\nUnable to open vertex table.");
- return FALSE;
- }
-
- for(el=elist; el != NULL; el=el->edgenext) {
- copy_point(el->edge->s_pt, p1);
- copy_point(el->edge->e_pt, p2);
- insert_pt_to_vtable(p1, vtb);
- insert_pt_to_vtable(p2, vtb);
- }
-
- *nv = vtb->nv;
- ap_free_edgelist(elist);
- free_vtable(vtb);
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc init_vtable() */
- /*+
- This routine initializes a table for storing vertices (points)
- -*/
- /*************************************************************************/
- static v_table *
- /*FCN*/init_vtable ()
- {
- v_table *p;
- ads_point *q;
-
- if ((p = MALLOC (v_table)) == NULL)
- {
- ads_printf(/*MSG30*/"\n\nCan't allocate memory for vertex table.");
- ads_retvoid();
- return NULL;
- }
- else
- {
- if ((q = CALLOC (table_size, ads_point)) == NULL)
- {
- ads_printf(/*MSG31*/"\n\nCan't allocate memory for vertex table!\n");
- free (p);
- return NULL;
- }
-
- p->nv = 0;
- p->size = table_size;
- p->fv = q;
- return p ;
- }
- }
-
- /*************************************************************************/
- /* .doc insert_pt_to_vtable() */
- /*+
- This routine inserts a 3D point into vertex table
- The point will be rejected if it already exists
- in the table
- -*/
- /*************************************************************************/
- static ap_Bool
- /*FCN*/insert_pt_to_vtable (pt, vb)
- ads_point pt;
- v_table *vb;
- {
- ads_point *q;
- int i, index, tablesize;
- ads_point pq;
- ap_Bool stat;
-
- index = vb->nv;
- tablesize = vb->size;
- q = vb->fv;
-
- if (index >= 1)
- {
- for (i=0; i<index; i++)
- {
- pq[X] = q[i][X];
- pq[Y] = q[i][Y];
- pq[Z] = q[i][Z];
-
- stat = verify_2pts_equal (pt, pq);
- if (stat == TRUE)
- return FALSE;
- }
- }
-
- if (index == (tablesize - gap))
- {
- tablesize = tablesize + step;
-
- if ((q = REALLOC(q, tablesize, ads_point)) == NULL)
- {
- ads_printf
- (/*MSG32*/"\n\nCan't allocate memory for vertex\n");
- return FALSE;
-
- }
- }
-
- q[index][X] = pt[X];
- q[index][Y] = pt[Y];
- q[index][Z] = pt[Z];
-
- vb->nv = index + 1;
- vb->size = tablesize;
- vb->fv = q;
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc free_vtable() */
- /*+
- This routine cleans the vertex table to free the membery
- -*/
- /*************************************************************************/
- static void
- /*FCN*/free_vtable (p)
- v_table *p;
- {
- ads_point *q;
-
- if ( p == NULL)
- return;
-
- q = p->fv;
- if(q != NULL)
- free (q);
- free(p);
- }
-
- /*************************************************************************/
- /* .doc trace_object_history() */
- /*+
- This routine executes command SOLTRACE
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/trace_object_history ()
- {
- ap_Objid Object;
- ads_name chosen;
- ads_point loc;
- int stat;
-
- /* Initialize API */
-
- stat = ap_init();
- if (stat != AP_NORMAL)
- goto Error;
-
- stat = select_object(&Object, chosen, loc);
- if(stat == FALSE)
- goto Error;
-
- /* Highlight the selected object */
-
- ads_redraw(chosen, 3);
-
- ads_textpage();
- screen_lineno = 0;
- linechk(3);
- ads_printf
- (/*MSG33*/"\n\n--- CSG HISTORY FOR OBJECT ID = %d ---\n", Object);
- traverse_and_dump_tree(Object);
-
- /* Dehighlight the object */
-
- ads_redraw(chosen, 4);
-
- Error:
- ads_retvoid();
- return;
- }
-
- /*************************************************************************/
- /* .doc select_object() */
- /*+
- This routine prompts the user to select an object
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/select_object (sol, ename, loc)
- ap_Objid *sol;
- ads_name ename;
- ads_point loc;
- {
- int stat;
-
- stat = ads_entsel(/*MSG34*/"Select an object:", ename, loc);
- if(stat != RTNORM) {
- ads_retvoid();
- return FALSE;
- }
-
- /* Verify that the selected entity is an AME object */
-
- stat = ap_name2obj(ename, sol);
- if(stat == AP_NORMAL) {
- ads_retvoid();
- return TRUE;
- } else {
- ads_retvoid();
- return FALSE;
- }
- }
-
- /*************************************************************************/
- /* .doc traverse_and_dump_tree() */
- /*+
- This routine traverses the CSG tree recursively in
- postorder: left child, right child, and root
- -*/
- /*************************************************************************/
- static ap_Bool
- /*FCN*/traverse_and_dump_tree(obj)
- ap_Objid obj;
- {
- int stat;
- ap_Objinfo oinfo;
-
- /* Retrieve object information */
-
- stat = ap_get_objinfo(obj, &oinfo);
- if(stat != AP_NORMAL) {
- ads_printf(/*MSG35*/"\nCan't retrieve solid information.");
- return FALSE;
- }
-
- if(oinfo.type == AP_BOO) {
-
- /* Left child */
-
- traverse_and_dump_tree(oinfo.prim.boo.op1);
-
- /* Right child */
-
- traverse_and_dump_tree(oinfo.prim.boo.op2);
- }
-
- /* Dump object information */
-
- print_obj_info(obj, oinfo);
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc print_obj_info() */
- /*+
- This routine outputs object information
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/print_obj_info(sid, sol)
- ap_Objid sid;
- ap_Objinfo sol;
- {
- ads_real dx, dy, dz, da;
- ap_Objid c1, c2;
- long np;
-
- linechk(2);
- switch(sol.type) {
- case AP_BOX:
- dx = sol.prim.box.x;
- dy = sol.prim.box.y;
- dz = sol.prim.box.z;
- ads_printf(/*MSG36*/"\nCreate: %lu = BOX (%f, %f, %f)\n", sid,dx,dy,dz);
- print_trans_matrix(sol.mat);
- break;
-
- case AP_CON:
- dx = sol.prim.con.rx;
- dy = sol.prim.con.ry;
- dz = sol.prim.con.h;
- ads_printf(/*MSG37*/"\nCreate: %lu = CONE (%f, %f, %f)\n", sid,dx,dy,dz);
- print_trans_matrix(sol.mat);
- break;
-
- case AP_CYL:
- dx = sol.prim.cyl.rx;
- dy = sol.prim.cyl.ry;
- dz = sol.prim.cyl.h;
- ads_printf(/*MSG38*/"\nCreate: %lu = CYLINDER (%f, %f, %f)\n", sid,dx,dy,dz);
- print_trans_matrix(sol.mat);
- break;
-
- case AP_SPH:
- dx = sol.prim.sph.r;
- ads_printf(/*MSG39*/"\nCreate: %lu = SPHERE (%f)\n", sid, dx);
- print_trans_matrix(sol.mat);
- break;
-
- case AP_TOR:
- dx = sol.prim.tor.rmaj;
- dy = sol.prim.tor.rmin;
- ads_printf(/*MSG40*/"\nCreate: %lu = TORUS (%f, %f)\n", sid, dx, dy);
- print_trans_matrix(sol.mat);
- break;
-
- case AP_WED:
- dx = sol.prim.wed.x;
- dy = sol.prim.wed.y;
- dz = sol.prim.wed.z;
- ads_printf(/*MSG41*/"\nCreate: %lu = WEDGE (%f, %f, %f)\n", sid,dx,dy,dz);
- print_trans_matrix(sol.mat);
- break;
-
- case AP_BOO:
- c1 = sol.prim.boo.op1;
- c2 = sol.prim.boo.op2;
- if(sol.prim.boo.op == AP_SUBTRACT)
- ads_printf(/*MSG42*/"\nBoolean: %lu = %lu subtract by %lu\n", sid,c1,c2);
- else if(sol.prim.boo.op == AP_INT)
- ads_printf(/*MSG43*/"\nBoolean: %lu = %lu intersect %lu\n", sid,c1,c2);
- else if(sol.prim.boo.op == AP_UNION)
- ads_printf(/*MSG44*/"\nBoolean: %lu = %lu join %lu\n", sid,c1,c2);
- else
- ads_printf(/*MSG45*/"\nUnknown Solid\n");
-
- print_trans_matrix(sol.mat);
- break;
-
- case AP_EXT:
- np = sol.prim.ext.n;
- dz = sol.prim.ext.h;
- da = sol.prim.ext.taper;
- ads_printf(/*MSG46*/"\nCreate: %lu = EXTRUSION (%lu, %f, %f)\n",sid,np,dz,da);
- if(dz < 0)
- print_pline_vertex(np, sol.prim.ext.pts, TRUE);
- else
- print_pline_vertex(np, sol.prim.ext.pts, FALSE);
-
- print_trans_matrix(sol.mat);
- break;
-
- case AP_REV:
- np = sol.prim.rev.n;
- da = sol.prim.rev.angle;
- ads_printf(/*MSG47*/"\nCreate: %lu = REVOLUTION (%d, %f)\n", sid,np,da);
- print_pline_vertex(np, sol.prim.rev.pts, FALSE);
- print_trans_matrix(sol.mat);
- break;
-
- case AP_FIL:
- dx = sol.prim.fil.r;
- ads_printf(/*MSG48*/"\nCreate: %lu = FILLET (%f) ", sid, dx);
- if(sol.prim.fil.type == AP_STRAIGHT)
- ads_printf(/*MSG49*/"Straignt_Edge\n");
- else if(sol.prim.fil.type == AP_CIRCULAR)
- ads_printf(/*MSG50*/"Circular_Edge\n");
- else
- ads_printf(/*MSG51*/"Undefined_Edge\n");
-
- print_trans_matrix(sol.mat);
- break;
-
- case AP_CHA:
- dx = sol.prim.cha.d1;
- dy = sol.prim.cha.d2;
- ads_printf(/*MSG52*/"\nCreate: %lu = CHAMFER (%f %f) ", sid,dx,dy);
- if(sol.prim.fil.type == AP_STRAIGHT)
- ads_printf(/*MSG53*/"Straignt_Edge\n");
- else if(sol.prim.fil.type == AP_CIRCULAR)
- ads_printf(/*MSG54*/"Circular_Edge\n");
- else
- ads_printf(/*MSG55*/"Undefined_Edge\n");
-
- print_trans_matrix(sol.mat);
- break;
-
- case AP_CIR:
- dx = sol.prim.cir.r;
- ads_printf(/*MSG56*/"\nCreate: %lu = CIRCLE (%f)\n", sid,dx);
- print_trans_matrix(sol.mat);
- break;
-
- case AP_POLY:
- np = sol.prim.poly.n;
- ads_printf(/*MSG57*/"\nCreate: %lu = POLYLINE (%d)\n", sid, np);
- print_pline_vertex(np, sol.prim.poly.pts, FALSE);
- print_trans_matrix(sol.mat);
- break;
-
- default:
- ads_printf(/*MSG58*/"\nUnknown SOLID\n");
- break;
- }
- }
-
- /*************************************************************************/
- /* .doc print_trans_matrix() */
- /*+
- This routine outputs the transformation matrix
- -*/
- /*************************************************************************/
- static void
- /*FCN*/print_trans_matrix(m)
- ap_Trans3d m;
- {
- int i;
-
- linechk(5);
- ads_printf(/*MSG59*/"Transformation Matrix:\n");
- for(i=0; i<4; i++)
- ads_printf(" %+f %+f %+f %+f\n",
- m[i][0], m[i][1], m[i][2], m[i][3]);
- }
-
- /*************************************************************************/
- /* .doc print_pline_vertex() */
- /*+
- This routine outputs the coordinates of vertices in polyline
- -*/
- /*************************************************************************/
- static void
- /*FCN*/print_pline_vertex(np, pts, xmirror)
- long np;
- ap_Swp_pts *pts;
- ap_Bool xmirror;
- {
- long i;
- ap_Real xt;
-
- linechk((int)(np+1));
- ads_printf(/*MSG60*/"Polyline vertices and type:\n");
- for(i=0; i<np; i++) {
- xt = xmirror ? -pts[i].x : pts[i].x;
- if(pts[i].type == AP_PT_ARCEND)
- ads_printf(/*MSG61*/" (%+f %+f) Arc_Edge\n", xt, pts[i].y);
- else if(pts[i].type == AP_PT_LINE)
- ads_printf(/*MSG62*/" (%+f %+f) Line_Edge\n", xt, pts[i].y);
- else
- ;
- }
- }
-
- /*************************************************************************/
- /*.doc linechk() */
- /*+
- This routine determines if we've printed a whole screen's worth of
- data, and if so, will put the prompt "Hit Enter for more ..."
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/linechk(n)
- int n;
- {
- char buf[128];
-
- if (screen_pagelen == 0)
- return TRUE;
-
- screen_lineno = screen_lineno + n;
-
- if (screen_lineno >= screen_pagelen) {
- if (ads_getstring(0, /*MSG63*/"Hit Enter for more ...", buf) < 0) {
- screen_lineno = (screen_lineno - screen_pagelen) + 1;
- return FALSE;
- }
- screen_lineno = (screen_lineno - screen_pagelen) + 1;
- ads_printf("\r \r");
- }
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc query_face_normal() */
- /*+
- This routine executes command SOLNORM and calculates
- the unit normal to a given face at the specified point
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/query_face_normal()
- {
- ap_Objid Object;
- ap_Featid face;
- ads_point pc, pd, pe, pt, ps;
- int stat, stat_pt;
-
- /* Initialize API */
-
- stat = ap_init();
- if (stat != AP_NORMAL)
- goto Error;
-
- stat = ap_sel_face ("", &Object, &face);
- if (stat != AP_NORMAL)
- {
- ads_printf(/*MSG64*/"\nUnable to get the face");
- goto Error;
- }
-
- stat = ads_getpoint(NULL, /*MSG65*/"\nPoint on the face:", pt);
- if ((stat == RTCAN) || (stat == RTERROR))
- goto Error;
-
- trans_uc2wc(pt, FALSE, pc);
-
- stat_pt = verify_pt_on_surface(Object, face, pc);
- if(stat_pt == TRUE) {
- stat = ap_pt_norm2face(Object, face, pc, TRUE, pd);
- if (stat != AP_NORMAL)
- {
- ads_printf(/*MSG66*/"\nUnable to obtain face normal.");
- goto Error;
- }
- copy_point(pc, ps);
- } else {
- stat = ap_pt2face(Object, face, pc, ps);
- if ((stat != AP_NORMAL) && (stat != AP_SINGULARITY))
- {
- ads_printf(/*MSG67*/"\nUnable to obtain projection point.");
- goto Error;
- }
-
- stat = ap_pt_norm2face(Object, face, ps, TRUE, pd);
- if (stat != AP_NORMAL)
- {
- ads_printf(/*MSG68*/"\nUnable to obtain face normal.");
- goto Error;
- }
- }
-
- /* Draw the unit normal vector on the screen */
-
- combine_vector(1.0, ps, 1.0, pd, pe);
- draw_virtual_arrow(ps, pe, YELLOW, FALSE);
-
- /* Convert points from wcs to ucs for printput */
-
- trans_wc2uc(pc, FALSE, pc);
- trans_wc2uc(pd, TRUE, pd);
-
- if(stat_pt == TRUE) {
- ads_printf(/*MSG69*/"\nSelected point = (%+f, %+f, %+f)", pc[X],pc[Y],pc[Z]);
- ads_printf(/*MSG70*/"\nUnit normal = (%+f, %+f, %+f)", pd[X],pd[Y],pd[Z]);
- } else {
- trans_wc2uc(ps, FALSE, ps);
- ads_printf(/*MSG71*/"\nSelected point = (%+f, %+f, %+f)", pc[X],pc[Y],pc[Z]);
- ads_printf(/*MSG72*/"\nProjection pt = (%+f, %+f, %+f)", ps[X],ps[Y],ps[Z]);
- ads_printf(/*MSG73*/"\nUnit normal = (%+f, %+f, %+f)", pd[X],pd[Y],pd[Z]);
- }
-
- Error:
- ads_retvoid();
- return;
-
- }
-
- /*************************************************************************/
- /* .doc verify_pt_on_surface() */
- /*+
- This routine verifies a point with a given surface
- It returns TRUE if the point lies on the surface
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/verify_pt_on_surface(sol, fe, pt)
- ap_Objid sol;
- ap_Featid fe;
- ads_point pt;
- {
- ap_Faceinfo *finfo;
- int stat, status;
-
- stat = ap_get_faceinfo(sol, fe, &finfo);
- if (stat != AP_NORMAL) {
- ads_printf (/*MSG74*/"\nUnable to retrieve face information");
- return FALSE;
- }
-
- switch(finfo->stype) {
- case AP_PLANAR:
- status = verify_pt_on_plane(finfo, pt);
- break;
-
- case AP_CYLINDRICAL:
- status = verify_pt_on_cyl(finfo, pt);
- break;
-
- case AP_CONICAL:
- status = verify_pt_on_cone(finfo, pt);
- break;
-
- case AP_SPHERICAL:
- status = verify_pt_on_sph(finfo, pt);
- break;
-
- case AP_TOROIDAL:
- status = verify_pt_on_tor(finfo, pt);
- break;
-
- default:
- status = FALSE;
- break;
- }
-
- ap_free_faceinfo(finfo);
- return status;
- }
-
- /*************************************************************************/
- /* .doc verify_pt_on_plane() */
- /*+
- This routine returns TRUE if the point lies on the given plane
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/verify_pt_on_plane(finfo, pt)
- ap_Faceinfo *finfo;
- ads_point pt;
- {
- ads_point pq;
- ap_Trans3d minv;
-
- if(finfo->stype != AP_PLANAR)
- return FALSE;
-
- ap_invert(finfo->face_rm, minv);
- trans_pt_by_matrix(minv, pt, pq);
-
- if(fabs(pq[Z]) < EPSILON)
- return TRUE;
- else
- return FALSE;
- }
-
- /*************************************************************************/
- /* .doc verify_pt_on_cyl() */
- /*+
- This routine returns TRUE if the point lies on the given cylinder
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/verify_pt_on_cyl(finfo, pt)
- ap_Faceinfo *finfo;
- ads_point pt;
- {
- ap_Trans3d minv;
- ads_point pq;
- ads_real radx, rady, tx, ty, dr;
-
- if(finfo->stype != AP_CYLINDRICAL)
- return FALSE;
-
- radx = finfo->surf.cyl.rx;
- rady = finfo->surf.cyl.ry;
-
- ap_invert(finfo->face_rm, minv);
- trans_pt_by_matrix(minv, pt, pq);
- tx = pq[X]/radx;
- ty = pq[Y]/rady;
- dr = tx * tx + ty * ty - 1.0;
-
- if(fabs(dr) < EPSILON)
- return TRUE;
- else
- return FALSE;
- }
-
- /*************************************************************************/
- /* .doc verify_pt_on_cone() */
- /*+
- This routine returns TRUE if the point lies on the given cone
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/verify_pt_on_cone(finfo, pt)
- ap_Faceinfo *finfo;
- ads_point pt;
- {
- ap_Trans3d minv;
- ads_point pq;
- ads_real radx, rady, tx, ty, dr;
-
- if(finfo->stype != AP_CONICAL)
- return FALSE;
-
- radx = finfo->surf.con.rx;
- rady = finfo->surf.con.ry;
-
- ap_invert(finfo->face_rm, minv);
- trans_pt_by_matrix(minv, pt, pq);
- tx = pq[X]/radx;
- ty = pq[Y]/rady;
- dr = tx * tx + ty * ty - pq[Z] * pq[Z];
-
- if(fabs(dr) < EPSILON)
- return TRUE;
- else
- return FALSE;
- }
-
- /*************************************************************************/
- /* .doc verify_pt_on_sph() */
- /*+
- This routine returns TRUE if the point lies on the given sphere
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/verify_pt_on_sph(finfo, pt)
- ap_Faceinfo *finfo;
- ads_point pt;
- {
- ap_Trans3d minv;
- ads_point pq;
- ads_real rad, dr;
-
- if(finfo->stype != AP_SPHERICAL)
- return FALSE;
-
- rad = finfo->surf.sph.r;
- ap_invert(finfo->face_rm, minv);
- trans_pt_by_matrix(minv, pt, pq);
- dr = pq[X]*pq[X] + pq[Y]*pq[Y]+ pq[Z]*pq[Z] - rad*rad;
-
- if(fabs(dr) < EPSILON)
- return TRUE;
- else
- return FALSE;
- }
-
- /*************************************************************************/
- /* .doc verify_pt_on_tor() */
- /*+
- This routine returns TRUE if the point lies on the given torus
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/verify_pt_on_tor(finfo, pt)
- ap_Faceinfo *finfo;
- ads_point pt;
- {
- ap_Trans3d minv;
- ads_point pq;
- ads_real rad1, rad2, dt, dr, result;
-
- if(finfo->stype != AP_TOROIDAL)
- return FALSE;
-
- rad1 = finfo->surf.tor.rmaj;
- rad2 = finfo->surf.tor.rmin;
-
- ap_invert(finfo->face_rm, minv);
- trans_pt_by_matrix(minv, pt, pq);
- dt = pq[X]*pq[X] + pq[Y]*pq[Y]+ pq[Z]*pq[Z];
- dr = dt - rad1*rad1 - rad2*rad2;
- result = dr * dr - 4*rad1*rad1*(rad2*rad2-pq[Z]*pq[Z]);
- if(fabs(result) < EPSILON)
- return TRUE;
- else
- return FALSE;
- }
-
- /*************************************************************************/
- /* .doc query_edge_tangent() */
- /*+
- This routine executes command SOLTAN.
- It calculates and displays unit tangent of a given
- curve at the selected location.
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/query_edge_tangent()
- {
- ap_Objid Object;
- ap_Featid edge;
- ads_point pc, pd, pe, pq, pt;
- ads_real parm;
- int stat;
-
- /* Initialize API */
-
- stat = ap_init();
- if (stat != AP_NORMAL)
- goto Error;
-
- stat = ap_sel_edge ("", &Object, &edge);
- if (stat != AP_NORMAL)
- {
- ads_printf(/*MSG75*/"\nUnable to get the edge");
- goto Error;
- }
-
- stat = ads_getpoint(NULL, /*MSG76*/"\nPoint on the edge:", pt);
- if ((stat == RTCAN) || (stat == RTERROR))
- goto Error;
-
- trans_uc2wc(pt, FALSE, pq);
-
- stat = ap_pt_tang2edge(Object, edge, pq, pd);
- if (stat != AP_NORMAL) {
- proj_pt_on_curve(Object, edge, pq, pc, &parm);
- stat = ap_pt_tang2edge(Object, edge, pc, pd);
- if (stat != AP_NORMAL) {
- ads_printf(/*MSG77*/"\nUnable to obtain edge tangent.");
- goto Error;
- }
- } else
- copy_point(pq, pc);
-
- /* Draw the unit tangent vector on the screen */
-
- combine_vector(1.0, pc, 1.0, pd, pe);
- draw_virtual_arrow(pc, pe, YELLOW, FALSE);
-
- /* Convert points from wcs to ucs for printout */
-
- trans_wc2uc(pc, FALSE, pc);
- trans_wc2uc(pq, FALSE, pq);
- trans_wc2uc(pd, TRUE, pd);
- stat = verify_2pts_equal(pc, pq);
- if(stat == TRUE) {
- ads_printf(/*MSG78*/"\nSelected point = (%+f, %+f, %+f)",pq[X],pq[Y],pq[Z]);
- ads_printf(/*MSG79*/"\nUnit tangent = (%+f, %+f, %+f)",pd[X],pd[Y],pd[Z]);
- } else {
- ads_printf(/*MSG80*/"\nSelected point = (%+f, %+f, %+f)",pq[X],pq[Y],pq[Z]);
- ads_printf(/*MSG81*/"\nProjection pt = (%+f, %+f, %+f)",pc[X],pc[Y],pc[Z]);
- ads_printf(/*MSG82*/"\nUnit tangent = (%+f, %+f, %+f)",pd[X],pd[Y],pd[Z]);
- }
-
- Error:
- ads_retvoid();
- return;
- }
-
- /*************************************************************************/
- /* .doc proj_pt_on_curve() */
- /*+
- This routine projects a point onto a given curve.
- It returns a pt on the curve which is nearest to the input.
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/proj_pt_on_curve(sol, edge, pin, pout, parm)
- ap_Objid sol;
- ap_Featid edge;
- ads_point pin, pout;
- ads_real *parm;
- {
- ap_Edgeinfo *einfo;
- ap_Trans3d minv;
- ads_point pc, pt;
- ads_real t, t1, t2, dt;
- ads_real len, dismin, da[101];
- ap_Bool repeat = TRUE;
- int stat, i, index, status, np = 101;
-
-
- stat = ap_get_edgeinfo(sol, edge, &einfo);
- if (stat != AP_NORMAL)
- {
- ads_printf(/*MSG83*/"\nUnable to obtain edge information.");
- return FALSE;
- }
-
- t1 = einfo->s_parm;
- t2 = einfo->e_parm;
- len = fabs(t2 - t1);
- ap_invert(einfo->edge_rm, minv);
- trans_pt_by_matrix(minv, pin, pc);
-
- while (repeat == TRUE) {
- dt = (t2 - t1) / (np - 1);
- for(i=0; i<np; i++) {
- t = t1 + i * dt;
- stat = evalu_pt_on_curve(einfo, t, pt);
- if(stat == FALSE) {
- status = FALSE;
- break;
- }
-
- da[i] = ads_distance(pt, pc);
- }
- dismin = find_minimum(da, np, &index);
- t = t1 + index * dt;
-
- if(fabs(dt) < (EPSILON * len)) {
- evalu_pt_on_curve(einfo, t, pt);
- trans_pt_by_matrix(einfo->edge_rm, pt, pout);
- *parm = t;
- status = TRUE;
- repeat = FALSE;
- } else if(index == 0) {
- t1 = t;
- t2 = t + dt;
- } else if(index == (np-1)) {
- t1 = t - dt;
- t2 = t;
- } else {
- t1 = t - dt/2;
- t2 = t + dt/2;
- }
- }
-
- ap_free_edgeinfo(einfo);
- return status;
- }
-
- /*************************************************************************/
- /* .doc evalu_pt_on_curve() */
- /*+
- This routine calculates the coordinate of a point
- on the parametric curve at the specified value.
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/evalu_pt_on_curve(einfo, u, pt)
- ap_Edgeinfo *einfo;
- ads_real u;
- ads_point pt;
-
- {
- ap_Bool status;
-
- switch(einfo->ctype) {
- case AP_LINE:
- pt[X] = 0.0;
- pt[Y] = 0.0;
- pt[Z] = u;
- status = TRUE;
- break;
-
- case AP_ELLIPSE:
- pt[X] = einfo->curve.ell.ru * cos(u);
- pt[Y] = einfo->curve.ell.rv * sin(u);
- pt[Z] = 0.0;
- status = TRUE;
- break;
-
- case AP_HYPERBOLA:
- if(fabs(u) < EPSILON)
- status = FALSE;
-
- pt[X] = einfo->curve.hyp.a * (u - 1/u) / 2.0;
- pt[Y] = einfo->curve.hyp.b * (u + 1/u) / 2.0;
- pt[Z] = 0.0;
- status = TRUE;
- break;
-
- case AP_PARABOLA:
- pt[X] = u;
- pt[Y] = u*u / einfo->curve.par.fourp;
- pt[Z] = 0.0;
- status = TRUE;
- break;
- /*
- case AP_CYLCYL:
- status = FALSE;
- break;
-
- case AP_CONCON:
- status = FALSE;
- break;
- */
-
- default:
- status = FALSE;
- break;
- }
-
- return status;
-
- }
-
- /*************************************************************************/
- /* .doc classify_entity_membership() */
- /*+
- This routine executes the command SOLCLASS
- It classifies a point or a line with respect
- to a given object.
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/classify_entity_membership ()
- {
- ap_Objid Object;
- ap_Class pclass;
- ap_Seglist *llist;
- ap_Edgeinfo einfo;
- ads_name chosen;
- ads_point pt, pc, pc1, pc2, loc;
- int stat, status, which;
- char inbuf[80];
-
- /* Initialize API */
-
- stat = ap_init();
- if (stat != AP_NORMAL)
- goto Error0;
-
- stat = select_object(&Object, chosen, loc);
- if(stat == FALSE)
- goto Error0;
-
- /* Highlight the selected entity */
-
- ads_redraw(chosen, 3);
-
-
- ads_initget(0, /*MSG84*/"Line Point");
- strcpy(inbuf, "");
-
- status = ads_getkword
- (/*MSG85*/"\nLine/<Point>: ", inbuf);
-
- if (status == RTNORM)
- {
- if (strcmp( /*MSG86*/"Line", inbuf ) == 0)
- which = LINE;
- else if (strcmp( /*MSG87*/"Point", inbuf ) == 0)
- which = POINT;
- else
- goto Error1;
- }
-
- if(status == RTNONE)
- which = POINT;
-
- if (status == RTCAN)
- goto Error1;
-
- switch (which)
- {
- case POINT:
- {
- set_point(0.0, 0.0, 0.0, pt);
- stat = ads_getpoint(NULL, /*MSG88*/"\nPoint <0,0,0>:", pt);
- if ((stat == RTCAN) || (stat == RTERROR))
- goto Error1;
-
- trans_uc2wc(pt, FALSE, pc);
- stat = ap_class_pt(Object, pc, &pclass);
- print_pt_class(pc, pclass);
- break;
- }
-
- case LINE:
- {
- stat = get_line_data(pc1, pc2);
- if(stat == FALSE) {
- ads_printf(/*MSG89*/"\nUnable to get line data.");
- goto Error1;
- }
-
- stat = make_edgeinfo_from_line(pc1, pc2, &einfo);
- if(stat == FALSE) {
- ads_printf(/*MSG90*/"\nUnable to make edgeinfo.");
- goto Error1;
- }
-
- /* Classify the line against the object */
-
- stat = ap_class_edge(Object, &einfo, &llist);
- if (stat != AP_NORMAL) {
- ads_printf (/*MSG91*/"\nUnable to classify line.");
- goto Error1;
- }
-
- print_line_class(pc1, pc2, llist);
- ap_free_seglist(llist);
- break;
- }
-
- default:
- break;
-
- }
-
- Error1:
- ads_redraw(chosen, 4);
-
- Error0:
- ads_retvoid();
- return;
- }
-
- /*************************************************************************/
- /* .doc print_pt_class() */
- /*+
- This routine outputs the membership class of a point
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/print_pt_class (pt, class)
- ads_point pt;
- ap_Class class;
- {
- ads_point pq;
-
- trans_wc2uc(pt, FALSE, pq);
- switch(class)
- {
- case AP_OFFOBJECT:
- ads_printf(/*MSG92*/"\nPoint (%f, %f, %f) is outside the solid",
- pq[X],pq[Y],pq[Z]);
- break;
-
- case AP_ONOBJECT:
- ads_printf(/*MSG93*/"\nPoint (%f, %f, %f) is on the solid",
- pq[X],pq[Y],pq[Z]);
- break;
-
- case AP_INOBJECT:
- ads_printf(/*MSG94*/"\nPoint (%f, %f, %f) is inside the solid",
- pq[X],pq[Y],pq[Z]);
- break;
-
- case AP_FAILED:
- break;
- }
- }
-
- /*************************************************************************/
- /* .doc get_line_data() */
- /*+
- This routine prompts the user to select start
- and end point for a line
- -*/
- /*************************************************************************/
- static ap_Bool
- /*FCN*/get_line_data(p1, p2)
- ads_point p1, p2;
- {
- ads_point pt1, pt2;
- int stat;
-
- set_point(0.0, 0.0, 0.0, pt1);
- set_point(0.0, 0.0, 1.0, pt2);
-
- stat = ads_getpoint(NULL, /*MSG95*/"\nFrom point <0,0,0>:", pt1);
- if ((stat == RTCAN) || (stat == RTERROR))
- return FALSE;
-
- stat = ads_getpoint(pt1, /*MSG96*/"\nTo point <0,0,1>:", pt2);
- if ((stat == RTCAN) || (stat == RTERROR))
- return FALSE;
-
- stat = verify_2pts_equal(pt1, pt2);
- if(stat == TRUE)
- return FALSE;
-
- trans_uc2wc(pt1, FALSE, p1);
- trans_uc2wc(pt2, FALSE, p2);
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc make_edgeinfo_from_line() */
- /*+
- This routine converts a line into an edge format
- -*/
- /*************************************************************************/
- static ap_Bool
- /*FCN*/make_edgeinfo_from_line(p1, p2, einfo)
- ads_point p1, p2;
- ap_Edgeinfo *einfo;
- {
- ads_real length;
-
- /* Initialization of edge structure einfo which will
- be used to hold line data for classification */
-
- length = ads_distance(p1, p2);
- if(fabs(length) < EPSILON)
- return FALSE;
-
- einfo->ctype = AP_LINE;
- einfo->edge_len = length;
- einfo->s_parm = 0.0;
- einfo->e_parm = length;
-
- ap_identity(einfo->edge_rm);
-
- copy_point(p1, einfo->s_pt);
- copy_point(p2, einfo->e_pt);
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc print_line_class() */
- /*+
- This routine outputs the membership of a line
- which is defined by two points ps and pe.
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/print_line_class(ps, pe, slist)
- ads_point ps, pe;
- ap_Seglist *slist;
- {
- ap_Seglist *seg;
- ap_Real t1, t2;
- ads_point p1, p2, pd, pt, pt1, pt2;
- int i;
-
- i = 0;
- combine_vector(1.0, pe, -1.0, ps, pt);
- normalize_vector(pt, pd);
-
- for(seg=slist; seg != NULL; seg=seg->segnext) {
-
- i++;
- t1 = seg->seg.s_parm;
- t2 = seg->seg.e_parm;
- combine_vector(1.0, ps, t1, pd, pt1);
- combine_vector(1.0, ps, t2, pd, pt2);
- trans_wc2uc(pt1, FALSE, p1);
- trans_wc2uc(pt2, FALSE, p2);
-
- switch(seg->seg.edge_class)
- {
- case AP_OFFOBJECT:
- ads_printf(/*MSG97*/"\nSeg#%d: OUT, <%f, %f, %f> - <%f, %f, %f>",
- i, p1[X],p1[Y],p1[Z],p2[X],p2[Y],p2[Z]);
- ads_grdraw(p1, p2, BLUE, 0);
- break;
-
- case AP_ONOBJECT:
- ads_printf(/*MSG98*/"\nSeg#%d: ON, <%f, %f, %f> - <%f, %f, %f>",
- i, p1[X],p1[Y],p1[Z],p2[X],p2[Y],p2[Z]);
- ads_grdraw(p1, p2, YELLOW, 0);
- break;
-
- case AP_INOBJECT:
- ads_printf(/*MSG99*/"\nSeg#%d: IN, <%f, %f, %f> - <%f, %f, %f>",
- i, p1[X],p1[Y],p1[Z],p2[X],p2[Y],p2[Z]);
- ads_grdraw(p1, p2, RED, 0);
- break;
-
- case AP_FAILED:
- break;
- }
- }
- }
-
- /*************************************************************************/
- /* .doc set_ucs_to_prindir() */
- /*+
- This routine executes command SOLPRINDIR.
- It resets current ucs to locate at the centroid and
- the principal moment directions of a given object.
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/set_ucs_to_prindir()
- {
- ap_Objid Object;
- ap_Massprop mp;
- ap_Objtype otype;
- ads_name chosen;
- ads_point loc, px, py, pc, po, p1, p2, p3, xd, yd, zd;
- int stat, region_in_ucs = FALSE;
-
- /* Initialize API */
-
- stat = ap_init();
- if (stat != AP_NORMAL)
- goto Error0;
-
- stat = select_object(&Object, chosen, loc);
- if(stat == FALSE)
- goto Error0;
-
- /* Highlight the selected entity */
-
- ads_redraw(chosen, 3);
-
- /* Verify object's type: solid or region */
-
- stat = ap_get_objtype(Object, &otype);
- if(stat != AP_NORMAL) {
- ads_printf(/*MSG100*/"\nCan't retrieve object's type.");
- goto Error1;
- }
-
- if(otype == AP_REGION) {
- stat = get_region_pts(Object, p1, p2, p3);
- if(stat == TRUE) {
- turn_ucsicon(OFF);
- set_current_ucs(p1, p2, p3);
- }
- } else {
- set_point(0.0, 0.0, 0.0, p1);
- set_point(1.0, 0.0, 0.0, p2);
- set_point(0.0, 1.0, 0.0, p3);
- turn_ucsicon(OFF);
- set_current_ucs(p1, p2, p3);
- }
-
- stat = ap_get_massprop(Object, &mp);
- if(stat != AP_NORMAL) {
- ads_printf(/*MSG101*/"\nUnable to retrieve mass properties.");
- goto Error1;
- }
-
- pc[X] = mp.centroid.x;
- pc[Y] = mp.centroid.y;
- pc[Z] = mp.centroid.z;
-
- copy_point(mp.prindir[0], p1);
- copy_point(mp.prindir[1], p2);
- cross_vector(p1, p2, p3);
- normalize_vector(p3, p3);
-
- trans_uc2wc(pc, FALSE, po);
- trans_uc2wc(p1, TRUE, xd);
- trans_uc2wc(p2, TRUE, yd);
- trans_uc2wc(p3, TRUE, zd);
-
- combine_vector(1.0, po, 1.0, xd, px);
- combine_vector(1.0, po, 1.0, yd, py);
- set_current_ucs(po, px, py);
- turn_ucsicon(ORIGIN);
- turn_ucsicon(ON);
-
- ads_printf(/*MSG102*/"\nCentroid = (%f, %f, %f)", po[X], po[Y], po[Z]);
- ads_printf(/*MSG103*/"\nNew x-dir = (%f, %f, %f)", xd[X], xd[Y], xd[Z]);
- ads_printf(/*MSG104*/"\nNew y-dir = (%f, %f, %f)", yd[X], yd[Y], yd[Z]);
- ads_printf(/*MSG105*/"\nNew z-dir = (%f, %f, %f)", zd[X], zd[Y], zd[Z]);
-
- Error1:
- ads_redraw(chosen, 4);
-
- Error0:
- ads_retvoid();
- return;
- }
-
- /*************************************************************************/
- /* .doc get_region_pts() */
- /*+
- This routine obtains three points on the given region.
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/get_region_pts(obj, po, px, py)
- ap_Objid obj;
- ads_point po, px, py;
- {
- ap_Objinfo oinfo;
- ap_Objid object;
- ap_Trans3d mat;
- ads_point p1, p2;
- 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(/*MSG106*/"\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;
- }
-
- po[X] = mat[0][3];
- po[Y] = mat[1][3];
- po[Z] = mat[2][3];
- p1[X] = mat[0][0];
- p1[Y] = mat[1][0];
- p1[Z] = mat[2][0];
- p2[X] = mat[0][1];
- p2[Y] = mat[1][1];
- p2[Z] = mat[2][1];
- combine_vector(1.0, po, 1.0, p1, px);
- combine_vector(1.0, po, 1.0, p2, py);
- return TRUE;
- }
- /*************************************************************************/
- /* .doc set_current_ucs() */
- /*+
- This routine resets current ucs by three points p1, p2 & p3.
- p1, p2 and p3 must be in WCS coordinate.
- -*/
- /*************************************************************************/
-
- static ap_Bool
- /*FCN*/set_current_ucs(p1, p2, p3)
- ads_point p1, p2, p3;
- {
- int stat1, stat2, stat3, stat;
- ads_point px, py, pz;
-
- 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, px);
- trans_wc2uc(p2, FALSE, py);
- trans_wc2uc(p3, FALSE, pz);
- command_echo_off ();
- stat = ads_command(RTSTR, /*MSG107*/"_.ucs", RTSTR, /*MSG108*/"_3",
- RT3DPOINT, px, RT3DPOINT, py, RT3DPOINT, pz, NULL);
-
- if (stat != RTNORM)
- {
- command_echo_on ();
- return FALSE;
- }
- command_echo_on ();
- 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, /*MSG109*/"_.UCSICON", RTSTR, /*MSG110*/"_ON", NULL);
- else if(action == ORIGIN)
- ads_command (RTSTR, /*MSG111*/"_.UCSICON", RTSTR, /*MSG112*/"_ORIGIN", NULL);
- else
- ads_command (RTSTR, /*MSG113*/"_.UCSICON", RTSTR, /*MSG114*/"_OFF", NULL);
-
- command_echo_on ();
- }
-
- /*************************************************************************/
- /* .doc draw_virtual_arrow() */
- /*+
- This routine draws an arrow from pt1 toward pt2 of specified color.
- The arrow consists of a center line and an arrowhead.
- If scale is set to TRUE, the length of the arrow is scaled
- automatically to be about 1/5 of viewport size.
- The arrow appears on the screen only, not in AutoCAD database.
- -*/
- /*************************************************************************/
- static ap_Bool
- /*FCN*/draw_virtual_arrow(pt1, pt2, color, scale)
- ads_point pt1, pt2;
- int color;
- ap_Bool scale;
- {
- ads_point pc1, norm;
- ads_real length, len, rad, vsize;
- struct resbuf vrb;
-
- length = ads_distance(pt1, pt2);
- if (length < EPSILON)
- return FALSE;
-
- norm[X] = (pt2[X] - pt1[X]) / length;
- norm[Y] = (pt2[Y] - pt1[Y]) / length;
- norm[Z] = (pt2[Z] - pt1[Z]) / length;
-
- if(scale == TRUE) {
- ads_getvar(/*MSG0*/"VIEWSIZE", &vrb);
- vsize = vrb.resval.rreal;
- len = 0.2 * vsize;
- } else
- len = length;
-
- rad = 0.05 * len;
-
- combine_vector(1.0, pt1, len, norm, pt2);
- combine_vector(1.0, pt1, 0.9*len, norm, pc1);
-
- draw_virtual_line(pt1, pt2, color);
- draw_virtual_arrowhead(pc1, pt2, rad, YELLOW);
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc draw_virtual_arrowhead() */
- /*+
- This routine draws an arrowhead consisting of
- a circle and 4 lines. The circle has center at pt1,
- and is normal to the direction from pt1 toward pt2.
- -*/
- /*************************************************************************/
- static ap_Bool
- /*FCN*/draw_virtual_arrowhead(pt1, pt2, radius, color)
- ads_point pt1, pt2;
- ads_real radius;
- int color;
- {
- ads_point pe, pw, ps, pn, xdir, ydir, norm, normt;
- ads_real len;
-
- len = ads_distance(pt1, pt2);
- if (len < EPSILON)
- return FALSE;
-
- norm[X] = (pt2[X] - pt1[X]) / len;
- norm[Y] = (pt2[Y] - pt1[Y]) / len;
- norm[Z] = (pt2[Z] - pt1[Z]) / len;
-
- get_xdir_from_zdir(norm, normt);
- normalize_vector(normt, xdir);
- cross_vector(norm, xdir, normt);
- normalize_vector(normt, ydir);
-
- combine_vector(1.0, pt1, radius, xdir, pe);
- combine_vector(1.0, pt1, -radius, xdir, pw);
- combine_vector(1.0, pt1, radius, ydir, pn);
- combine_vector(1.0, pt1, -radius, ydir, ps);
-
- draw_virtual_circle(pt1, radius, norm, color);
- draw_virtual_line(pt2, pe, color);
- draw_virtual_line(pt2, pn, color);
- draw_virtual_line(pt2, ps, color);
- draw_virtual_line(pt2, pw, color);
-
- return TRUE;
-
- }
-
- /*************************************************************************/
- /* .doc draw_virtual_line() */
- /*+
- This routine draw a line from point pt1 to pt2 in wcs
- using specified color. The line appears on the screen
- only, not in AutoCAD database
- -*/
- /*************************************************************************/
- static ap_Bool
- /*FCN*/draw_virtual_line( pt1, pt2, color)
- ads_point pt1, pt2;
- int color;
- {
- ads_point p1, p2;
- int status;
-
- trans_wc2uc(pt1, FALSE, p1);
- trans_wc2uc(pt2, FALSE, p2);
- status = ads_grdraw(p1, p2, color, 0);
- if (status == RTNORM)
- return TRUE;
- else
- return FALSE;
- }
-
- /*************************************************************************/
- /* .doc draw_virtual_circle() */
- /*+
- This routine draws a circle of a given color at
- specified center, radius and normal direction.
- The circle appears on the screen only, not in
- AutoCAD database.
- -*/
- /*************************************************************************/
- static ap_Bool
- /*FCN*/draw_virtual_circle(pc, radius, norm, color)
- ads_point pc, norm;
- ads_real radius;
- int color;
- {
- int np, i;
- ads_point temp, xdir, ydir, p[PMAX];
- ads_real rad, ang;
-
- if(((fabs(norm[X]) < EPSILON) &&
- (fabs(norm[Y]) < EPSILON) &&
- (fabs(norm[Z]) < EPSILON)) ||
- (fabs(radius) < EPSILON))
- return FALSE;
-
- np = 12;
- get_xdir_from_zdir(norm, temp);
- normalize_vector(temp, xdir);
- cross_vector(norm, xdir, temp);
- normalize_vector(temp, ydir);
- rad = fabs(radius);
-
- for (i=0; i<=np; i++) {
- ang = i * 2.0 * PI / np;
- temp[X] = pc[X] + rad * (cos(ang)*xdir[X] + sin(ang)*ydir[X]);
- temp[Y] = pc[Y] + rad * (cos(ang)*xdir[Y] + sin(ang)*ydir[Y]);
- temp[Z] = pc[Z] + rad * (cos(ang)*xdir[Z] + sin(ang)*ydir[Z]);
- trans_wc2uc(temp, FALSE, p[i]);
- }
-
- for (i=0; i<np; i++)
- ads_grdraw(p[i], p[i+1], color, 0);
-
- return TRUE;
- }
-
- /*************************************************************************/
- /* .doc get_xdir_from_zdir() */
- /*+
- This routine computes the x-axis direction from given
- z-axis direction based on arbitrary axis algorithm.
- -*/
- /*************************************************************************/
- static ap_Bool
- /*FCN*/get_xdir_from_zdir (zdir, xdir)
- ads_point zdir, xdir;
- {
- ads_point u, v, wydir, wzdir;
-
- set_point(0.0, 1.0, 0.0, wydir);
- set_point(0.0, 0.0, 1.0, wzdir);
-
- if ((fabs (zdir[X]) < EPSILON) &&
- (fabs (zdir[Y]) < EPSILON) &&
- (fabs (zdir[Z]) < EPSILON))
- return FALSE;
- else
- {
- normalize_vector(zdir, u);
-
- if ((fabs(u[X]) < 1.0/64.0) && (fabs (u[Y]) < 1.0/64.0))
- cross_vector (wydir, u, v);
-
- else
- cross_vector (wzdir, u, v);
-
- normalize_vector(v, xdir);
- return TRUE;
- }
- }
-
- /*************************************************************************/
- /* .doc copy_point() */
- /*+
- This routine copies a new point pt2 from old point 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 set_point() */
- /*+
- This routine assigns x, y and z coordinates to a point pt
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/set_point (x, y, z, pt)
- ads_real x, y, z;
- ads_point pt;
- {
- pt[X] = x;
- pt[Y] = y;
- pt[Z] = z;
- }
-
- /*************************************************************************/
- /* .doc verify_2pts_equal() */
- /*+
- This routine verifies whether two points p1 & p2 are equal 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 combine_vector() */
- /*+
- This routine perform linear combination of two vectors.
- p3 = a . p1 + b . p2;
- -*/
- /*************************************************************************/
-
- static void
- /*FCN*/combine_vector(a, p1, b, p2, p3)
- ads_real a, b;
- ads_point p1, p2, p3;
- {
- p3[X] = a * p1[X] + b * p2[X];
- p3[Y] = a * p1[Y] + b * p2[Y];
- p3[Z] = a * p1[Z] + b * p2[Z];
- }
-
- /*************************************************************************/
- /* .doc normalize_vector() */
- /*+
- This routine normalizes 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 cross_vector() */
- /*+
- This routine conducts the cross product of two vectors.
- -*/
- /*************************************************************************/
-
- 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 trans_pt_by_matrix() */
- /*+
- This routine transforms a point pin to pout by the matrix m.
- -*/
- /*************************************************************************/
- static void
- /*FCN*/trans_pt_by_matrix(m, pin, pout)
- ap_Trans3d m;
- ads_point pin, pout;
- {
- register i;
- ads_real sum[3];
-
- for (i = 0; i < 3; i++)
- sum[i] = m[i][0] * pin[X] +
- m[i][1] * pin[Y] +
- m[i][2] * pin[Z] +
- m[i][3];
- pout[X] = sum[0];
- pout[Y] = sum[1];
- pout[Z] = sum[2];
- }
-
- /*************************************************************************/
- /* .doc trans_uc2wc() */
- /*+
- This routine transforms a point p in ucs into a 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 trans_wc2uc() */
- /*+
- This routine transforms a point p in wcs into a 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 find_minimum() */
- /*+
- This routine finds the minimum value in array[] containing
- nt real number. It returns both the minimum value and the index.
- -*/
- /*************************************************************************/
- 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 */
-