home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- UTIL.C
- ¬⌐┼v (C) 1988-1992 Autodesk ñ╜Ñq
-
- Ñ╗╡{ªíñwÑ╤ Autodesk ñ╜Ñq╡∙ÑU¬⌐┼v, ╢╚⌐≤ñU¡z▒í¬pñUÑi▒┬╗P▒zíu│\ÑiívíC
- ╗╒ñUñú▒oÑHÑ⌠ª≤º╬ªí╡oªµ⌐╬ÑX¬⌐ª╣╡{ªí¬║íu¡∞⌐l╜Xív; ª²ñ╣│\▒zªb»S⌐w¡lÑ═
- ¬║ñuº@ñW╡▓ªXª╣╡{ªí¬║íuÑ╪¬║╜Xív¿╧Ñ╬íCª│├÷│o├■¡lÑ═ñuº@¬║▒°Ñ≤ªpñU:
-
- ( i) │]¡pñW╗Pñuº@ñW¼╥»┬║Θ░w╣∩ Autodesk ñ╜Ñq¬║▓ú½~íC
- (ii) ╕ⁿª│íu¬⌐┼v (C) 1988-1992 Autodesk ñ╜Ñqív¬║¬⌐┼v│qºiíC
-
-
-
- AUTODESKñ╜Ñq┤ú¿╤ª╣╡{ªí╢╚¿╤º@íu├■ªⁿív¬║░╤ª╥, ª╙ÑBñú▒╞░úª│Ñ⌠ª≤┐∙╗~¬║
- Ñi»αíCAUTODESKñ╜Ñq»Sª╣º_╗{Ñ⌠ª≤»S⌐wÑ╬│~ñº╛A║┘⌐╩, ÑHñ╬░╙╖~╛P░Γ⌐╥┴⌠ºt
- ÑX¿π¬║½O├╥íCAUTODESKñ╜ÑqªP«╔ÑτñúÑX¿πª╣╡{ªí░⌡ªµ«╔ñ@⌐wñú╖|íuññ┬_ív⌐╬
- íuº╣Ñ■╡L╗~ív¬║½O├╥íC
-
-
- Description: Library of various utility functions. This is not a well
- organized library, just a rather random collection of
- functions. But you might find some of the functions useful.
-
- *****************************************************************************/
-
-
- /****************************************************************************/
- /* INCLUDES */
- /****************************************************************************/
-
- #include <stdio.h>
- #include <math.h>
- #include <string.h>
- #include "adslib.h"
- #include "util.h"
-
-
- /****************************************************************************/
- /* DEFINES */
- /****************************************************************************/
-
- #define ARBBOUND 0.015625 /* Bound for arbitrary matrix alg. */
- #define ZERO_BULGE 1e-7 /* Bulge which is considered zero */
-
-
- /****************************************************************************/
- /* STATIC VARIABLES */
- /****************************************************************************/
-
- /* Save area for various AutoCAD system variables */
-
- static struct resbuf cmdecho, blipmode, highlight, ucsicon, aunits, lunits,
- orthomode, osmode, snapmode, thickness, elevation,
- angdir;
-
- static struct resbuf cmde, sortents;
-
-
- /****************************************************************************/
- /* STATIC FUNCTIONS */
- /****************************************************************************/
-
- static void sa_make_pickbox_equal_to_aperture _((int do_it));
- static int sa_e2u _((ads_point p1, ads_name ent_name, int tested,
- ads_point m[4], ads_point normal, ads_point p2));
-
-
- /****************************************************************************/
- /*.doc sa_save_acad_vars(external) */
- /*+
- Saves AutoCAD system variables which may negatively influence the
- ads_command() function.
- -*/
- /****************************************************************************/
-
-
- void
- /*FCN*/sa_save_acad_vars()
- {
- struct resbuf rb;
-
- ads_getvar("CMDECHO", &cmdecho );
- ads_getvar("BLIPMODE", &blipmode );
- ads_getvar("HIGHLIGHT", &highlight);
- ads_getvar("UCSICON", &ucsicon );
- ads_getvar("AUNITS", &aunits );
- ads_getvar("LUNITS", &lunits );
- ads_getvar("ORTHOMODE", &orthomode);
- ads_getvar("OSMODE", &osmode );
- ads_getvar("SNAPMODE", &snapmode );
- ads_getvar("THICKNESS", &thickness);
- ads_getvar("ELEVATION", &elevation);
- ads_getvar("ANGDIR", &angdir );
-
- rb.rbnext = NULL;
- rb.restype = RTSHORT;
- rb.resval.rint = 0;
-
- ads_setvar("CMDECHO", &rb);
- ads_setvar("BLIPMODE", &rb);
- ads_setvar("HIGHLIGHT",&rb);
- ads_setvar("UCSICON", &rb);
- ads_setvar("AUNITS", &rb);
- ads_setvar("ORTHOMODE",&rb);
- ads_setvar("OSMODE", &rb);
- ads_setvar("SNAPMODE", &rb);
- ads_setvar("ANGDIR", &rb);
-
- rb.resval.rint = 1;
- ads_setvar("LUNITS", &rb);
-
- rb.restype = RTREAL;
- rb.resval.rreal = 0.0;
- ads_setvar("THICKNESS", &rb);
- ads_setvar("ELEVATION", &rb);
- } /*sa_save_acad_vars*/
-
-
- /****************************************************************************/
- /*.doc sa_restore_acad_vars(external) */
- /*+
- Restores the system variables which were saved by save_acad_vars().
- -*/
- /****************************************************************************/
-
-
- void
- /*FCN*/sa_restore_acad_vars()
- {
- ads_setvar("BLIPMODE", &blipmode );
- ads_setvar("HIGHLIGHT", &highlight);
- ads_setvar("UCSICON", &ucsicon );
- ads_setvar("AUNITS", &aunits );
- ads_setvar("LUNITS", &lunits );
- ads_setvar("ORTHOMODE", &orthomode);
- ads_setvar("OSMODE", &osmode );
- ads_setvar("SNAPMODE", &snapmode );
- ads_setvar("CMDECHO", &cmdecho );
- ads_setvar("THICKNESS", &thickness);
- ads_setvar("ELEVATION", &elevation);
- ads_setvar("ANGDIR", &angdir );
- } /*sa_restore_acad_vars*/
-
-
- /****************************************************************************/
- /*.doc sa_cmdecho_off(external) */
- /*+
- Saves the value of the CMDECHO variable and sets it to 0.
- -*/
- /****************************************************************************/
-
-
- void
- /*FCN*/sa_cmdecho_off()
- {
- struct resbuf rb;
-
- ads_getvar("CMDECHO", &cmde);
-
- rb.restype = RTSHORT;
- rb.resval.rint = 0;
-
- ads_setvar("CMDECHO", &rb);
- } /*sa_cmdecho_off*/
-
-
- /****************************************************************************/
- /*.doc sa_cmdecho_back(external) */
- /*+
- Restores the original value of the CMDECHO variable.
- -*/
- /****************************************************************************/
-
-
- void
- /*FCN*/sa_cmdecho_back()
- {
- ads_setvar("CMDECHO", &cmde);
- } /*sa_cmdecho_back*/
-
-
- /****************************************************************************/
- /*.doc sa_undo_group(external) */
- /*+
- Begins an undo group.
- -*/
- /****************************************************************************/
-
-
- void
- /*FCN*/sa_undo_group()
- {
- sa_cmdecho_off();
- ads_command(RTSTR, /* NT */"_.UNDO", RTSTR, /* NT */"_GROUP", 0);
- sa_cmdecho_back();
- } /*sa_undo_group*/
-
-
- /****************************************************************************/
- /*.doc sa_undo_end(external) */
- /*+
- Ends the undo group.
- -*/
- /****************************************************************************/
-
-
- void
- /*FCN*/sa_undo_end()
- {
- sa_cmdecho_off();
- ads_command(RTSTR, /* NT */"_.UNDO", RTSTR, /* NT */"_END", 0);
- sa_cmdecho_back();
- } /*sa_undo_end*/
-
-
- /****************************************************************************/
- /*.doc sa_set_sortents(external) */
- /*+
- Sets the mode of picking. When entities overlap, the method of
- disambiguating is controlled by the AutoCAD SORTENTS variable.
- See the description for SORTENTS for full meaning of the pick modes.
- -*/
- /****************************************************************************/
-
-
- void
- /*FCN*/sa_set_sortents(pick_mode)
- int pick_mode;
- {
- struct resbuf rb_mode;
-
- rb_mode.rbnext = NULL;
- rb_mode.restype = RTSHORT;
- rb_mode.resval.rint = pick_mode;
- ads_setvar("SORTENTS",&rb_mode);
- } /*sa_set_sortents*/
-
-
- /****************************************************************************/
- /*.doc sa_save_sortents(external) */
- /*+
- Saves the value of the SORTENTS system variable. This function is
- typically called if the value of SORTENTS is to be restored by calling
- sa_restore_sortents() later.
- NOTE: There is no stack of values maintain. Calling the function
- overwrites the previous value in sortents.
- -*/
- /****************************************************************************/
-
-
- void
- /*FCN*/sa_save_sortents()
- {
- ads_getvar("SORTENTS", &sortents);
- } /*sa_save_sortents*/
-
-
- /****************************************************************************/
- /*.doc sa_restore_sortents(external) */
- /*+
- Restores the value of the AutoCAD variable SORTENTS to the value that
- was obtained by a previous call to sa_save_sortents().
- NOTE: This function must be called only if there was a previous call
- to sa_save_sortents().
- -*/
- /****************************************************************************/
-
-
- void
- /*FCN*/sa_restore_sortents()
- {
- ads_setvar("SORTENTS", &sortents);
- } /*sa_restore_sortents*/
-
-
- /****************************************************************************/
- /*.doc sa_make_pickbox_equal_to_aperture(external) */
- /*+
- TRUE => Makes the value of PICKBOX variable equal to APERTURE variable.
- FALSE=> Returns value of PICKBOX variable back.
- -*/
- /****************************************************************************/
-
-
- static void
- /*FCN*/sa_make_pickbox_equal_to_aperture(do_it)
-
- int do_it;
- {
- static struct resbuf pickbox;
- struct resbuf aperture;
-
- if (do_it) {
- ads_getvar("PICKBOX", &pickbox );
- ads_getvar("APERTURE", &aperture);
- ads_setvar("PICKBOX", &aperture);
- } else { /*Return it back*/
- ads_setvar("PICKBOX", &pickbox );
- }
- } /*sa_make_pickbox_equal_to_aperture*/
-
-
- /****************************************************************************/
- /*.doc sa_points_are_collinear(external) */
- /*+
- Returns TRUE if the three given points are collinear.
- -*/
- /****************************************************************************/
-
-
- int
- /*FCN*/sa_points_are_collinear(p1, p2, p3)
-
- ads_point p1, p2, p3;
- {
- ads_point v1, v2;
- int ok1, ok2;
-
- SUB_PNT(v1, p2, p1);
- SUB_PNT(v2, p3, p1);
-
- ok1 = sa_normalize(v1);
- ok2 = sa_normalize(v2);
-
- if (!ok1 || !ok2)
- return(TRUE);
-
- return(fabs(DOTPROD(v1, v2)) > EPS_COS);
- } /*sa_points_are_collinear*/
-
-
- /****************************************************************************/
- /*.doc sa_cross(external) */
- /*+
- Cross product of two vectors.
- -*/
- /****************************************************************************/
-
-
- void
- /*FCN*/sa_cross(v, v1, v2)
-
- ads_point v, v1, v2;
- {
- v[X] = v1[Y] * v2[Z] - v1[Z] * v2[Y];
- v[Y] = v1[Z] * v2[X] - v1[X] * v2[Z];
- v[Z] = v1[X] * v2[Y] - v1[Y] * v2[X];
- } /*sa_cross*/
-
-
- /****************************************************************************/
- /*.doc sa_det(external) */
- /*+
- Evaluates the determinant of 3x3 matrix. The given vectors a, b and c
- are the rows of the matrix.
- -*/
- /****************************************************************************/
-
-
- double
- /*FCN*/sa_det(a, b, c)
-
- ads_point a, b, c;
- {
- return(a[X] * (b[Y] * c[Z] - b[Z] * c[Y]) +
- a[Y] * (b[Z] * c[X] - b[X] * c[Z]) +
- a[Z] * (b[X] * c[Y] - b[Y] * c[X]));
- } /*sa_det*/
-
-
- /****************************************************************************/
- /*.doc sa_plane_from_point_and_normal(external) */
- /*+
- Takes point on plane 'origin' and point on plane normal 'zaxis' and
- returns two additional points 'xaxis' and 'yaxis' lying on the plane.
- The points 'xaxis' and 'yaxis' are calculated based on the arbitrary axis
- algorithm.
-
- Function returns one of the standard ADS result codes.
- -*/
- /****************************************************************************/
-
-
- int
- /*FCN*/sa_plane_from_point_and_normal(origin, zaxis, xaxis, yaxis)
-
- ads_point origin,zaxis; /* Two input points */
- ads_point xaxis,yaxis; /* Two calculated points */
- {
- int success;
- ads_point normal;
- ads_point m[3];
-
- SUB_PNT(normal, zaxis, origin);
-
- success = sa_make_arb_matrix(normal, m);
- if (success != RTNORM)
- return(RTERROR);
-
- ADD_PNT(xaxis, origin, m[X]);
- ADD_PNT(yaxis, origin, m[Y]);
-
- return(RTNORM);
- } /*sa_plane_from_point_and_normal*/
-
-
- /****************************************************************************/
- /*.doc sa_3d_angle(external) */
- /*+
- Returns the angle of triangle (apex,p1,p2). All points are considered
- threedimensional, the resulting angle is within interval <0;PI>.
- -*/
- /****************************************************************************/
-
-
- double
- /*FCN*/sa_3d_angle(apex, p1, p2)
-
- ads_point apex, p1, p2;
- {
- ads_point v1, v2;
- double l1, l2;
- double cosa;
- double angle;
-
- SUB_PNT(v1, p1, apex); l1 = LENGTH(v1);
- SUB_PNT(v2, p2, apex); l2 = LENGTH(v2);
-
- if ((l1 < EPS) || (l2 < EPS))
- return(0.0);
-
- cosa = DOTPROD(v1, v2) / (l1 * l2);
- if (cosa > 1.0)
- cosa = 1.0;
- if (cosa < -1.0)
- cosa = -1.0;
-
- angle = acos(cosa);
-
- return(angle);
- } /*sa_3d_angle*/
-
-
- /****************************************************************************/
- /*.docsa_ rotate_point_around_axis(external) */
- /*+
- Rotates point 'pp' around axis (p1,p2) through angle 'angle'. The axis
- is oriented from 'p1' to 'p2'.
-
- Function returns one of the standard ADS result codes.
- -*/
- /****************************************************************************/
-
-
- int
- /*FCN*/sa_rotate_point_around_axis(pp, angle, p1, p2)
-
- ads_point pp;
- double angle;
- ads_point p1, p2;
- {
- ads_point p;
- ads_point n;
- double cosa, sina, cosb, sinb, cosc, sinc;
- double lenxy,len;
- double px,pz;
-
- if (sa_points_are_collinear(pp, p1, p2))
- return(RTREJ);
-
- SUB_PNT(n, p2, p1);
-
- lenxy = sqrt(SQR(n[X]) + SQR(n[Y]));
-
- if (lenxy > EPS) {
- cosa = n[X] / lenxy;
- sina = n[Y] / lenxy;
- } else {
- cosa = 1.0;
- sina = 0.0;
- }
-
- len = LENGTH(n);
- cosb = n[Z] / len;
- sinb = lenxy / len;
-
- cosc = cos(angle);
- sinc = sin(angle);
-
- SUB_PNT(p, pp, p1);
-
- px = cosa * p[X] + sina * p[Y];
- p[Y] = -sina * p[X] + cosa * p[Y];
- p[X] = px;
-
- pz = cosb * p[Z] + sinb * p[X];
- p[X] = -sinb * p[Z] + cosb * p[X];
- p[Z] = pz;
-
- px = cosc * p[X] - sinc * p[Y];
- p[Y] = sinc * p[X] + cosc * p[Y];
- p[X] = px;
-
- pz = cosb * p[Z] - sinb * p[X];
- p[X] = sinb * p[Z] + cosb * p[X];
- p[Z] = pz;
-
- px = cosa * p[X] - sina * p[Y];
- p[Y] = sina * p[X] + cosa * p[Y];
- p[X] = px;
-
- ADD_PNT(pp, p, p1);
-
- return(RTNORM);
- } /*sa_rotate_point_around_axis*/
-
-
- /****************************************************************************/
- /*.doc sa_angle_around_axis(external) */
- /*+
- Returns angle between points 'from' and 'to' measured around axis (p1,p2).
- The axis is oriented from p1 to p2.
- -*/
- /****************************************************************************/
-
-
- double
- /*FCN*/sa_angle_around_axis(p1, p2, from, to)
-
- ads_point p1, p2;
- ads_point from, to;
- {
- ads_point nor1, nor2;
- ads_point v, v1, v2;
- double l1, l2;
- double angle;
- double cosa;
-
- if (sa_points_are_collinear(p1, p2, from) ||
- sa_points_are_collinear(p1, p2, to)) {
- return(0.0);
- }
-
- SUB_PNT(v, p2, p1);
-
- SUB_PNT(v1, from, p1);
- SUB_PNT(v2, to , p1);
-
- sa_cross(nor1, v1, v); l1 = LENGTH(nor1);
- sa_cross(nor2, v2, v); l2 = LENGTH(nor2);
-
- cosa = DOTPROD(nor1, nor2) / (l1 * l2);
- angle = acos(cosa);
-
- if (sa_det(v, v1, v2) < 0.0)
- angle = -angle;
-
- if (angle < 0.0)
- angle += 2*PI;
- if (angle > 2*PI)
- angle -= 2*PI;
-
- return(angle);
- } /*sa_angle_around_axis*/
-
-
- /****************************************************************************/
- /*.doc sa_orientate_cs_upwards(external) */
- /*+
- Orientates the given coordinate system, defined by four points (origin,
- xaxis, yaxis and zaxis), so that its z-axis (from origin to point zaxis)
- goes upwards, that is in the direction of the Z-axis of the current UCS.
-
- If the z-axis of the given coordinates system lies in the XY plane of the
- current UCS, then the orientation is determined according to either the X
- or Y axis of the current UCS, depending on to which axis is the given
- z-axis more parallel.
- -*/
- /****************************************************************************/
-
-
- void
- /*FCN*/sa_orientate_cs_upwards(origin, xaxis, yaxis, zaxis)
-
- ads_point origin; /* Point at origin */
- ads_point xaxis, yaxis, zaxis; /* Point on X, Y and Z axis */
- {
- double len;
- int reverse;
- ads_point p;
-
- len = DISTANCE(origin, zaxis);
-
- if (fabs(origin[Z] - zaxis[Z]) / len >= ARBBOUND)
- reverse = (origin[Z] > zaxis[Z]);
- else
- if (fabs(origin[X] - zaxis[X]) >= fabs(origin[Y] - zaxis[Y]))
- reverse = (origin[X] > zaxis[X]);
- else
- reverse = (origin[Y] > zaxis[Y]);
-
- if (reverse) {
- CPY_PNT(p, origin);
- CPY_PNT(origin, zaxis);
- CPY_PNT(zaxis, p);
-
- CPY_PNT(p, xaxis);
- CPY_PNT(xaxis, yaxis);
- CPY_PNT(yaxis, p);
- }
- } /*sa_orientate_cs_upwards*/
-
-
- /****************************************************************************/
- /*.doc sa_is_planar_pline(external) */
- /*+
- Retruns TRUE if the pline having the given vertex is a planar 2D polyline,
- otherwise returns FALSE. The output argument 'normal' will contain the
- entity normal vector.
- -*/
- /****************************************************************************/
-
-
- int
- /*FCN*/sa_is_planar_pline(vertex_name, normal)
-
- ads_name vertex_name;
- ads_point normal;
- {
- ads_name pline_name;
- int flags = 8; /* Just in case that group 70 is not found */
- int success;
- struct resbuf *rb, *rb_rel;
-
- normal[X] = normal[Y] = normal[Z] = 0.0;
-
- success = sa_pline_name_from_vertex_name(vertex_name, pline_name);
- if (success != RTNORM)
- return(FALSE);
-
- rb = rb_rel = ads_entget(pline_name);
-
- while (rb != NULL) {
- if (rb->restype == 70) {
- flags = rb->resval.rint;
- } else if (rb ->restype == 210) {
- CPY_PNT(normal, rb->resval.rpoint);
- }
- rb = rb->rbnext;
- }
-
- ads_relrb(rb_rel);
-
- return((flags & (8 + 16 + 64)) == 0);
- } /*sa_is_planar_pline*/
-
-
- /****************************************************************************/
- /*.doc sa_get_pline_segment_data(external) */
- /*+
- Returns the endpoints p1 and p2, center, radius and normal vector of
- a polyline segment, given by its name (name of VERTEX entity) and by vertex
- entity data list of result buffers.
-
- If the pline segment is straight, then center contains the midpoint of
- the segment and radius is 0.0.
-
- All the returned coordinates are expressed in ECS.
-
- Function returns one of the standard ADS result codes.
- -*/
- /****************************************************************************/
-
-
- int
- /*FCN*/sa_get_pline_segment_data(plseg_name, plseg_rb, p1, p2,
- center, radius, normal)
-
- ads_name plseg_name; /* Name of pline segment (vertex) */
- struct resbuf *plseg_rb; /* Vertex data as a list of result buffers */
-
- ads_point p1, p2; /* Returned endpoints of the segment */
- ads_point center; /* Returned center of arc segment */
- double *radius; /* Returned radius of arc segment */
- ads_point normal; /* Entity normal vector */
- {
- int success;
- double bulge;
- struct resbuf *rb;
- struct resbuf *next_rb, *first_rb;
- ads_name next_name, first_name;
- ads_name pline_name;
- double f, dist;
-
- success = RTNORM;
- next_rb = first_rb = NULL;
-
- /* Check whether it is realy a planar non-splined 2D polyline */
-
- if (!sa_is_planar_pline(plseg_name, normal))
- return(RTREJ);
-
- /* Get the first point and bulge */
-
- bulge = 0.0;
- rb = plseg_rb;
-
- while (rb != NULL) {
- if (rb->restype == 42) {
- bulge = rb->resval.rreal;
- } else if (rb->restype == 10) {
- CPY_PNT(p1, rb->resval.rpoint);
- }
- rb = rb->rbnext;
- } /*while*/
-
- /* Go to the next vertex */
-
- success = ads_entnext(plseg_name, next_name);
- if (success != RTNORM)
- return(RTERROR);
-
- next_rb = ads_entget(next_name);
- if (next_rb == NULL)
- return(RTERROR);
-
- rb = next_rb->rbnext;
- if (rb->restype != 0) {
- success = RTERROR;
- goto Cleanup;
- }
-
- /* If it is the last segment of closed entity then go to first segment */
-
- if (strcmp(rb->resval.rstring, /* NT */"SEQEND") == 0) {
-
- while ((rb != NULL) && (rb->restype != -2))
- rb = rb->rbnext;
-
- if (rb == NULL) {
- success = RTERROR;
- goto Cleanup;
- }
-
- pline_name[0] = rb->resval.rlname[0];
- pline_name[1] = rb->resval.rlname[1];
-
- success = ads_entnext(pline_name, first_name);
- if (success != RTNORM) {
- success = RTERROR;
- goto Cleanup;
- }
-
- first_rb = ads_entget(first_name);
- if (first_rb == NULL) {
- success = RTERROR;
- goto Cleanup;
- }
-
- rb = first_rb->rbnext;
- if (rb->restype != 0) {
- success = RTERROR;
- goto Cleanup;
- }
- } else if (strcmp(rb->resval.rstring, "VERTEX") != 0) {
- success = RTERROR;
- goto Cleanup;
- }
-
- /* Get second point of either the next or the first vertex */
-
- while ((rb != NULL) && (rb->restype != 10))
- rb = rb->rbnext;
-
- if (rb == NULL) {
- success = RTERROR;
- goto Cleanup;
- }
-
- CPY_PNT(p2, rb->resval.rpoint);
-
-
- /* Calculate center and radius of the pline arc segment */
-
- if (fabs(bulge) < ZERO_BULGE) {
- *radius = 0.0;
- ADD_PNT(center, p1, p2);
- center[X] /= 2.0;
- center[Y] /= 2.0;
- center[Z] /= 2.0;
- } else {
- dist = DISTANCE(p1, p2);
- *radius = fabs(0.25 * dist * (bulge + 1.0 / bulge));
-
- f = -0.25 * (bulge - 1/bulge);
- center[X] = (p1[X] + p2[X])/2 + f*(p1[Y] - p2[Y]);
- center[Y] = (p1[Y] + p2[Y])/2 + f*(p2[X] - p1[X]);
- center[Z] = (p1[Z] + p2[Z])/2;
- }
- success = RTNORM;
-
- Cleanup:
-
- if (next_rb != NULL)
- ads_relrb(next_rb);
- if (first_rb != NULL)
- ads_relrb(first_rb);
-
- return(success);
- } /*sa_get_pline_segment_data*/
-
-
- /****************************************************************************/
- /*.doc sa_pline_name_from_vertex_name(external) */
- /*+
- Gives polyline name from a given name of a polyline segment (VERTEX).
-
- Function returns one of the standard ADS result codes.
- -*/
- /****************************************************************************/
-
-
- int
- /*FCN*/sa_pline_name_from_vertex_name(vertex_name, pline_name)
-
- ads_name vertex_name; /* Name of polyline segment (VERTEX) */
- ads_name pline_name; /* Returned name of the polyline */
- {
- ads_name name;
- struct resbuf *rb;
- int success;
-
- ads_name_set(vertex_name, name);
-
- for (;;) {
- success = ads_entnext(name, name);
- if (success != RTNORM)
- return(RTERROR);
-
- rb = ads_entget(name);
- if ((rb == NULL) || (rb->rbnext == NULL) ||
- (rb->rbnext->restype != 0)) {
- ads_relrb(rb);
- return(RTERROR);
- }
-
- if (strcmp(rb->rbnext->resval.rstring, /* NT */"SEQEND") == 0) {
- struct resbuf *rel_rb;
-
- rel_rb = rb;
- rb = rb->rbnext->rbnext;
-
- while (rb->restype != -2)
- rb = rb->rbnext;
-
- ads_name_set(rb->resval.rlname, pline_name);
-
- ads_relrb(rel_rb);
- return(RTNORM);
- } /*if*/
-
- ads_relrb(rb);
- if (success != RTNORM)
- return(RTERROR);
- } /*forever*/
- } /*sa_pline_name_from_vertex_name*/
-
-
- /****************************************************************************/
- /*.doc sa_tranform_pt(external) */
- /*+
- Transforms given point p1 by 3x4 matrix 'm'. Transformed point is returned
- in point p2.
- -*/
- /****************************************************************************/
-
-
- void
- /*FCN*/sa_transform_pt(m, p1, p2)
-
- ads_point m[4];
- ads_point p1,p2;
- {
- ads_point p;
-
- CPY_PNT(p, p1);
-
- p2[X] = m[X][X] * p[X] + m[Y][X] * p[Y] + m[Z][X] * p[Z] + m[3][X];
- p2[Y] = m[X][Y] * p[X] + m[Y][Y] * p[Y] + m[Z][Y] * p[Z] + m[3][Y];
- p2[Z] = m[X][Z] * p[X] + m[Y][Z] * p[Y] + m[Z][Z] * p[Z] + m[3][Z];
-
- } /*sa_transform_pt*/
-
-
- /****************************************************************************/
- /*.doc sa_normalize(external) */
- /*+
- Normalizes given vector v. Returns FALSE is the vector is nearly zero.
- -*/
- /****************************************************************************/
-
-
- int
- /*FCN*/sa_normalize(v)
-
- ads_point v;
- {
- double len;
-
- len = LENGTH(v);
-
- if (len < EPS)
- return(FALSE);
-
- v[X] /= len;
- v[Y] /= len;
- v[Z] /= len;
-
- return(TRUE);
- } /*sa_normalize*/
-
-
- /****************************************************************************/
- /*.doc sa_make_arb_matrix(external) */
- /*+
- Makes arbitrary matrix 'm' for direction of z-axis 'zaxis'.
-
- Function returns one of the standard ADS result codes.
- -*/
- /****************************************************************************/
-
-
- int
- /*FCN*/sa_make_arb_matrix(zaxis, m)
-
- ads_point zaxis; /* Given direction of z-axis */
- ads_point m[4]; /* Returned arbitrary matrix */
- {
- static ads_point unitmat[3] = {{1.0, 0.0, 0.0},
- {0.0, 1.0, 0.0},
- {0.0, 0.0, 1.0}};
- int ok;
-
- CPY_PNT(m[Z], zaxis);
- ok = sa_normalize(m[Z]);
-
- if (!ok)
- return(RTERROR);
-
- if ((fabs(m[Z][X]) < ARBBOUND) && (fabs(m[Z][Y]) < ARBBOUND))
- sa_cross(m[X], unitmat[Y], m[Z]);
- else
- sa_cross(m[X], unitmat[Z], m[Z]);
-
- sa_normalize(m[X]);
-
- sa_cross(m[Y], m[Z], m[X]);
- sa_normalize(m[Y]);
-
- m[3][X] = m[3][Y] = m[3][Z] = 0.0; /* No translation */
-
- return(RTNORM);
- } /*sa_make_arb_matrix*/
-
-
- /****************************************************************************/
- /*.doc sa_get_cs_of_picked_entity(external) */
- /*+
- Function prompts to pick an entity (line, arc, circle, 2D pline segment)
- and returns its axis or plane.
-
- axis_required: TRUE => returns axis in two points origin and zaxis.
- FALSE => returns plane in three points origin, xaxis and yaxis
-
- The plane may also be considered a coordinates system:
-
- origin ... Point at the origin.
- xaxis ... Point on the positive portion of the X-axis.
- yaxis ... Point in the halfplane of the positive Y-axis.
-
- The axis or plane is obtained from the entity picked as follows:
-
- Axis:
- ----
- LINE ... The endpoints of the line.
- ARC, CIRCLE ... The axis of the arc or circle (perpendicular to the plane
- of the arc).
- PLINE ... Handled either as an arc or as a line depending on the
- type of the picked pline segment.
-
- Plane:
- -----
- ARC, CIRCLE ... The plane of the arc or circle, origin at the center.
- PLINE ... arc segment -> handled as an arc,
- straight segment -> plane of the polyline, origin at the
- endpoint closer to the picked point.
-
- The points xaxis and yaxix are calculated based on the arbitrary
- axis algorithm.
-
- All returned points are expressed in the current UCS. Picking nested
- entities is properly handled and the returned axis/plane is the axis/plane
- of the nexted entity itself, not of the enclosing block.
-
- Function returns one of the standard ADS result codes.
- -*/
- /****************************************************************************/
-
-
- int
- /*FCN*/sa_get_cs_of_picked_entity(prompt, axis_required,
- origin, xaxis, yaxis, zaxis)
-
- char *prompt; /* Prompt (optional) */
- int axis_required; /* TRUE==Axis, FALSE==Plane */
- ads_point origin, xaxis, yaxis, zaxis; /* Returned points */
- {
- int success;
- ads_name ent_name;
- struct resbuf *ent_rb;
- ads_point m[4];
- struct resbuf *blocks;
- struct resbuf *rb;
- ads_point pick_pt;
- int ent_type;
- int nested_entity;
- ads_point normal;
-
- success = RTNORM;
- ent_rb = blocks = NULL;
-
- normal[X] = normal[Y] = normal[Z] = 0.0;
-
- /* Pick an entity */
-
- Pick:
-
- if (prompt != NULL) {
- success = ads_nentsel(prompt, ent_name, pick_pt, m, &blocks);
- } else if (axis_required) {
- success = ads_nentsel("\n¼D┐∩ñ@íu╜uívíBíu╢ΩívíBíu⌐tív⌐╬íu2D╗EªX╜uív▓╒¼q:\n",
- ent_name, pick_pt, m, &blocks);
- } else {
- success = ads_nentsel("\n¼D┐∩ñ@íu╢ΩívíBíu⌐tív⌐╬íu2D╗EªX╜uív▓╒¼q:\n",
- ent_name, pick_pt, m, &blocks);
- }
-
- if ((success == RTCAN) || (success == RTREJ))
- return(success);
-
- if (success != RTNORM) {
- ads_printf("\n¿S┐∩¿∞╣╧ñ╕íC\n\n");
- goto Pick;
- }
-
- /* Set nested_entity variable, erase list of enclosing blocks */
-
- nested_entity = (blocks != NULL);
- if (nested_entity)
- ads_relrb(blocks);
-
- /* Get the list of result buffers for the picked entity */
-
- ent_rb = ads_entget(ent_name);
- if (ent_rb == NULL) {
- success = RTERROR;
- goto Cleanup;
- }
-
- rb = ent_rb->rbnext;
- if (rb->restype != 0) {
- success = RTERROR;
- goto Cleanup;
- }
-
- /* Find out which type of entity has been picked */
-
- if (strcmp(rb->resval.rstring, /* NT */"LINE") == 0)
- ent_type = 1;
- else
- if (strcmp(rb->resval.rstring, /* NT */"CIRCLE") == 0)
- ent_type = 2;
- else
- if (strcmp(rb->resval.rstring, /* NT */"ARC") == 0)
- ent_type = 3;
- else
- if (strcmp(rb->resval.rstring, "VERTEX") == 0)
- ent_type = 4;
- else {
-
- Improper_entity:
-
- ads_printf("\n┐∩⌐w¬║íu╣╧ñ╕├■ºOívñúÑ┐╜TíC\n\n");
- ads_relrb(ent_rb);
- goto Pick;
- }
-
- if ((ent_type == 1) && (!axis_required))
- goto Improper_entity;
-
- /* Get points origin, xaxis, yaxis, zaxis from the picked entity */
-
- if (ent_type == 1 /*line*/) {
-
- while (rb != NULL) {
- if (rb->restype == 10)
- CPY_PNT(origin,rb->resval.rpoint);
- else if (rb->restype == 11)
- CPY_PNT(zaxis,rb->resval.rpoint);
- rb = rb->rbnext;
- } /*while*/
-
- CPY_PNT(xaxis, origin);
- CPY_PNT(yaxis, origin);
-
- } else if ((ent_type == 2 /*circle*/) || (ent_type == 3 /*arc*/)) {
-
- while (rb != NULL) {
- if (rb->restype == 10)
- CPY_PNT(origin, rb->resval.rpoint);
- else if (rb->restype == 210)
- CPY_PNT(normal, rb->resval.rpoint);
- rb = rb->rbnext;
- } /*while*/
-
- CPY_PNT(xaxis, origin); xaxis[X] += 1.0;
- CPY_PNT(yaxis, origin); yaxis[Y] += 1.0;
- CPY_PNT(zaxis, origin); zaxis[Z] += 1.0;
-
- } else {
-
- /* Polyline */
-
- ads_point p1, p2;
- double radius;
-
- success = sa_get_pline_segment_data(ent_name, ent_rb, p1, p2,
- origin, &radius, normal);
- if (success == RTREJ) {
- ads_printf("\nÑ▓╢╖¼░íu2D╗EªX╜uívíC\n\n");
- ads_relrb(ent_rb);
- goto Pick;
- } else if (success != RTNORM) {
- success = RTERROR;
- goto Cleanup;
- }
-
- /* Exchange 'p1' and 'p2' to make 'p1' visually closer to
- the picked point 'pick_pt' */
-
- {
- ads_point pd1,pd2;
-
- sa_e2u(p1, ent_name, nested_entity, m, normal, pd1);
- sa_e2u(p2, ent_name, nested_entity, m, normal, pd2);
-
- if (sa_visual_distance(pd1, pick_pt) >
- sa_visual_distance(pd2, pick_pt)) {
- ads_point p;
- CPY_PNT(p, p1);
- CPY_PNT(p1, p2);
- CPY_PNT(p2, p );
- }
- }
-
- if (radius == 0.0) /*straight segment*/ {
-
- if (axis_required) {
- CPY_PNT(origin,p1);
- CPY_PNT(zaxis, p2);
- CPY_PNT(xaxis, origin);
- CPY_PNT(yaxis, origin);
- } else /*plane required*/ {
- CPY_PNT(origin,p1 );
- CPY_PNT(xaxis, origin); xaxis[X] += 1.0;
- CPY_PNT(yaxis, origin); yaxis[Y] += 1.0;
- CPY_PNT(zaxis, origin); zaxis[Z] += 1.0;
- }
- } else /*arc segment*/ {
- CPY_PNT(xaxis, origin); xaxis[X] += 1.0;
- CPY_PNT(yaxis, origin); yaxis[Y] += 1.0;
- CPY_PNT(zaxis, origin); zaxis[Z] += 1.0;
- }
- } /*else pline*/
-
-
- if (DISTANCE(origin, zaxis) < EPS) {
- ads_printf("\n┐∩¿∞íuºφ¿ε▓úÑ═ív¬║╣╧ñ╕íC\n\n");
- ads_relrb(ent_rb);
- goto Pick;
- }
-
- /* Transform 'origin', 'xaxis', 'yaxis', 'zaxis' from ECS to UCS */
-
- sa_e2u(origin, ent_name, nested_entity, m, normal, origin);
- sa_e2u(xaxis, ent_name, nested_entity, m, normal, xaxis );
- sa_e2u(yaxis, ent_name, nested_entity, m, normal, yaxis );
- sa_e2u(zaxis, ent_name, nested_entity, m, normal, zaxis );
-
- success = RTNORM;
-
- Cleanup:
-
- /* Erase the list of result buffers */
-
- if (ent_rb != NULL)
- ads_relrb(ent_rb);
-
- return(success);
- } /*sa_get_cs_of_picked_entity*/
-
-
- /****************************************************************************/
- /*.doc sa_snap(external) */
- /*+
- Prompts to pick an entity and gives its snap point.
-
- Function returns one of the standard ADS result codes.
- -*/
- /****************************************************************************/
-
-
- int
- /*FCN*/sa_snap(prompt, mode, p)
-
- char *prompt; /* Prompt (optional) */
- char *mode; /* "END", "MID", "CEN" etc.*/
- ads_point p; /* Returned snap point */
- {
- int success;
- ads_name ent_name;
-
- Pick:
-
- sa_make_pickbox_equal_to_aperture(TRUE);
- success = ads_entsel(prompt, ent_name, p);
- sa_make_pickbox_equal_to_aperture(FALSE);
-
- if ((success == RTCAN) || (success == RTREJ)) {
- return(success);
- }
- if (success != RTNORM) {
- ads_printf("\nÑ╝┐∩¿∞╣╧ñ╕íC\n\n");
- goto Pick;
- }
-
- success = ads_osnap(p, mode, p);
- if (success != RTNORM) {
- ads_printf("\n¼D┐∩¬║íu╣╧ñ╕├■ºOívñúÑ┐╜TíC\n\n");
- goto Pick;
- }
-
- return(RTNORM);
- } /*sa_snap*/
-
-
- /****************************************************************************/
- /*.doc sa_uniform_scaling_factor(external) */
- /*+
- Function extracts the scaling factor from matrix 'm'. If
- this matrix represents uniform scaling (the same scaling in
- all directions) then it returns this (positive) scaling factor.
- Otherwise it returns value -1.0.
- -*/
- /****************************************************************************/
-
-
- double
- /*FCN*/sa_uniform_scaling_factor(m)
-
- ads_point m[4];
- {
- double sx,sy,sz,s;
-
- sx = sqrt(SQR(m[X][X]) + SQR(m[X][Y]) + SQR(m[X][Z]));
- sy = sqrt(SQR(m[Y][X]) + SQR(m[Y][Y]) + SQR(m[Y][Z]));
- sz = sqrt(SQR(m[Z][X]) + SQR(m[Z][Y]) + SQR(m[Z][Z]));
- s = (sx + sy + sz) / 3;
-
- if ((fabs(s) < EPS) ||
- (fabs(s-sx)/s + fabs(s-sy)/s + fabs(s-sy)/s > 1e-5))
- return(-1.0);
- else
- return(s);
-
- } /*sa_uniform_scaling_factor*/
-
-
- /****************************************************************************/
- /*.doc sa_plane_equation(external) */
- /*+
- Function calcuates the plane eqation from:
-
- - 3 points p1, p2, p3 (pts3 == TRUE)
- - plane point p1 and point on normal p2 (pts3 == FALSE)
-
- The unit normal vector to the plane is returned in 'n' and the
- constant coefficient is returned in 'd', according to the implicit
- plane equation:
-
- n[X]*x + n[Y]*y + n[Z]*z + d == 0.0
-
- Function returns one of the standard ADS result codes.
- -*/
- /****************************************************************************/
-
-
- int
- /*FCN*/sa_plane_equation(pts3, p1, p2, p3, n, d)
-
- int pts3; /* TRUE==3 points, FALSE==pt & normal pt */
- ads_point p1, p2, p3;
- ads_point n; /* Returned unit normal vector */
- double *d; /* Returned constant coefficient */
- {
- ads_point v1, v2, nn;
- double dd;
- int ok;
-
- if (pts3) /*3 points*/ {
- SUB_PNT(v1, p2, p1);
- SUB_PNT(v2, p3, p1);
- sa_cross(nn, v1, v2);
- ok = sa_normalize(nn);
- if (!ok)
- return(RTERROR);
- dd = -(DOTPROD(nn, p1) + DOTPROD(nn, p2) + DOTPROD(nn, p3)) / 3;
- } else /*2 points*/ {
- SUB_PNT(nn, p2, p1);
- ok = sa_normalize(nn);
- if (!ok)
- return(RTERROR);
- dd = -DOTPROD(nn, p1);
- }
-
- CPY_PNT(n, nn);
- *d = dd;
- return(RTNORM);
- } /*sa_plane_equation*/
-
-
- /****************************************************************************/
- /*.doc sa_u2w(external) */
- /*+
- Transforms a given point from UCS to WCS.
-
- Function returns one of the standard ADS result codes.
- -*/
- /****************************************************************************/
-
-
- int
- /*FCN*/sa_u2w(p1, p2)
-
- ads_point p1,p2;
- {
- int success;
- struct resbuf wcs,ucs;
-
- wcs.restype = RTSHORT;
- wcs.resval.rint = 0;
- ucs.restype = RTSHORT;
- ucs.resval.rint = 1;
-
- success = ads_trans(p1, &ucs, &wcs, 0, p2);
-
- return(success);
- } /*sa_u2w*/
-
-
- /****************************************************************************/
- /*.doc sa_w2u(external) */
- /*+
- Transforms a given point from WCS to UCS.
-
- Function returns one of the standard ADS result codes.
- -*/
- /****************************************************************************/
-
-
- int
- /*FCN*/sa_w2u(p1, p2)
-
- ads_point p1,p2;
- {
- int success;
- struct resbuf wcs,ucs;
-
- wcs.restype = RTSHORT;
- wcs.resval.rint = 0;
- ucs.restype = RTSHORT;
- ucs.resval.rint = 1;
-
- success = ads_trans(p1, &wcs, &ucs, 0, p2);
-
- return(success);
- } /*sa_w2u*/
-
-
- /****************************************************************************/
- /*.doc sa_get_radius_of_picked_entity(external) */
- /*+
- Returns radius of a picked entity (arc, circle or 2D polyline segment).
- Nested entities are properly handled, that is you may pick an entity
- nested inside a block.
-
- Function returns one of the standard ADS result codes.
- -*/
- /****************************************************************************/
-
-
- int
- /*FCN*/sa_get_radius_of_picked_entity(prompt, radius)
-
- char *prompt; /* Prompt (optional) */
- double *radius; /* Returned radius */
- {
- int success;
- int entity_type;
- ads_name ent_name;
- struct resbuf *ent_rb, *rb, *blocks;
- double matrix[4][3];
- double scale,rad;
- ads_point pick_pt;
- ads_point normal;
-
- /* Pick an entity */
-
- Pick:
- success = ads_nentsel(prompt, ent_name, pick_pt, matrix, &blocks);
-
- if ((success == RTCAN) || (success == RTREJ)) {
- return(success);
- }
- if (success != RTNORM) {
- ads_printf("\nÑ╝┐∩¿∞╣╧ñ╕íC\n\n");
- goto Pick;
- }
-
- if (blocks != NULL) {
- ads_relrb(blocks);
-
- if ((scale = sa_uniform_scaling_factor(matrix)) < 0) {
- ads_printf("\n╣╧╕s¬║íuñ±¿╥ívñúñ@¡P, Ñb«|ñúªsªbíC\n\n");
- goto Pick;
- }
- } else {
- scale = 1.0;
- }
-
- /* Find out which type of entity has been picked */
-
- ent_rb = ads_entget(ent_name);
- if (ent_rb == NULL)
- return(RTERROR);
-
- rb = ent_rb->rbnext;
- if (rb->restype != 0) {
- ads_relrb(ent_rb);
- return(RTERROR);
- }
-
- if (strcmp(rb->resval.rstring, /* NT */"CIRCLE") == 0)
- entity_type = 1;
- else if (strcmp(rb->resval.rstring, /* NT */"ARC") == 0)
- entity_type = 2;
- else if (strcmp(rb->resval.rstring, /* NT */"VERTEX") == 0)
- entity_type = 3;
- else {
- ads_relrb(ent_rb);
- ads_printf("\n¼D┐∩¬║íu╣╧ñ╕├■ºOívñúÑ┐╜TíC\n\n");
- goto Pick;
- }
-
- /* Get the entity radius from the entity data */
-
- switch (entity_type) {
-
- case 1: /*circle*/
- case 2: /*arc*/
- while ((rb != NULL) && (rb->restype != 40))
- rb = rb->rbnext;
- if (rb == NULL) {
- ads_relrb(ent_rb);
- return(RTERROR);
- }
-
- rad = rb->resval.rreal;
- break;
-
- case 3: /*polyline*/
- {
- ads_point p1, p2, cen;
-
- success = sa_get_pline_segment_data(ent_name, ent_rb, p1, p2,
- cen, &rad, normal);
- if (success == RTREJ) { /*Mesh, etc.*/
- ads_relrb(ent_rb);
- ads_printf("\nÑ▓╢╖¼░íu2D╗EªX╜uívíC\n\n");
- goto Pick;
- } else if (success != RTNORM) {
- ads_relrb(ent_rb);
- return(RTERROR);
- }
- if (rad == 0.0) {
- ads_relrb(ent_rb);
- ads_printf("\nÑ▓╢╖¼D┐∩íu╗EªX╜uí╨⌐╖¼qívíC\n\n");
- goto Pick;
- }
- }
- break;
- } /*switch*/
-
- *radius = scale * rad;
- return(RTNORM);
-
- } /*sa_get_radius_of_picked_entity*/
-
-
- /****************************************************************************/
- /*.doc sa_visual_distance(external) */
- /*+
- Returns visual distance (in display coordinate system) of two given
- points p1 and p2, expressed in current UCS.
- -*/
- /****************************************************************************/
-
-
- double
- /*FCN*/sa_visual_distance(p1, p2)
-
- ads_point p1,p2;
- {
- ads_point pd1, pd2;
- struct resbuf ucs, dcs;
- double dist;
-
- ucs.restype = RTSHORT;
- ucs.resval.rint = 1;
- dcs.restype = RTSHORT;
- dcs.resval.rint = 2;
-
- ads_trans(p1, &ucs, &dcs, FALSE, pd1);
- ads_trans(p2, &ucs, &dcs, FALSE, pd2);
- pd1[Z] = pd2[Z] = 0.0;
- dist = DISTANCE(pd1, pd2);
-
- return(dist);
- } /*sa_visual_distance*/
-
-
- /****************************************************************************/
- /*.doc sa_e2u(external) */
- /*+
- Transform point from ECS to UCS (supports nested entities).
-
- Function returns one of the standard ADS result codes.
- -*/
- /****************************************************************************/
-
-
- static int
- /*FCN*/sa_e2u(p1, ent_name, nested, m, normal, p2)
-
- ads_point p1; /* Point in ECS to be transformed */
- ads_name ent_name; /* Entity name */
- int nested; /* Is entity nested ? */
- ads_point m[4]; /* Matrix from ads_nentsel() */
- ads_point normal; /* Entity normal (for arc, circle), (0,0,0) otherwise */
- ads_point p2; /* Resulting point in UCS */
- {
- ads_point arbm[4];
- struct resbuf ecs, ucs;
- int success;
- ads_point p;
-
- ecs.restype = RTENAME;
- ecs.resval.rlname[0] = ent_name[0];
- ecs.resval.rlname[1] = ent_name[1];
-
- ucs.restype = RTSHORT;
- ucs.resval.rint = 1;
-
- arbm[X][X] = 1.0; arbm[X][Y] = 0.0; arbm[X][Z] = 0.0;
- arbm[Y][X] = 0.0; arbm[Y][Y] = 1.0; arbm[Y][Z] = 0.0;
- arbm[Z][X] = 0.0; arbm[Z][Y] = 0.0; arbm[Z][Z] = 1.0;
- arbm[3][X] = 0.0; arbm[3][Y] = 0.0; arbm[3][Z] = 0.0;
-
- /* If normal is provided (for arc & circle), make arbitrary matrix */
-
- if (nested && (normal != NULL) && (LENGTH(normal) > EPS)) {
- sa_make_arb_matrix(normal, arbm);
- }
-
- if (!nested) {
- success = ads_trans(p1, &ecs, &ucs, 0, p);
- } else {
- /*ECS->MCS*/
-
- sa_transform_pt(arbm, p1, p);
-
- /*MCS->WCS*/
-
- sa_transform_pt(m, p, p);
-
- /*WCS->UCS*/
-
- success = sa_w2u(p, p);
- }
- CPY_PNT(p2, p);
-
- return(success);
- } /*sa_e2u*/
-
-
- /****************************************************************************/
- /*.doc sa_normalize_angle(external) */
- /*+
- Normalizes angle (in radians) to interval <0;2*PI).
- -*/
- /****************************************************************************/
-
-
- void
- /*FCN*/sa_normalize_angle(angle)
-
- double *angle;
- {
- *angle = fmod(*angle, 2*PI);
- if (*angle < 0.0)
- *angle += 2*PI;
- } /*sa_normalize_angle*/
-
-