Esempio n. 1
0
/* $Procedure      VPRJPI ( Vector projection onto plane, inverted ) */
/* Subroutine */ int vprjpi_(doublereal *vin, doublereal *projpl, doublereal *
	invpl, doublereal *vout, logical *found)
{
    /* System generated locals */
    doublereal d__1;

    /* Local variables */
    doublereal invc, invn[3];
    extern doublereal vdot_(doublereal *, doublereal *);
    doublereal mult;
    extern /* Subroutine */ int chkin_(char *, ftnlen);
    doublereal denom;
    extern doublereal dpmax_(void);
    doublereal projc, limit;
    extern /* Subroutine */ int vlcom_(doublereal *, doublereal *, doublereal 
	    *, doublereal *, doublereal *);
    doublereal numer, projn[3];
    extern /* Subroutine */ int pl2nvc_(doublereal *, doublereal *, 
	    doublereal *), chkout_(char *, ftnlen);
    extern logical return_(void);

/* $ Abstract */

/*     Find the vector in a specified plane that maps to a specified */
/*     vector in another plane under orthogonal projection. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Required_Reading */

/*     PLANES */

/* $ Keywords */

/*     GEOMETRY */
/*     MATH */
/*     PLANE */
/*     VECTOR */

/* $ Declarations */
/* $ Brief_I/O */

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     VIN        I   The projected vector. */
/*     PROJPL     I   Plane containing VIN. */
/*     INVPL      I   Plane containing inverse image of VIN. */
/*     VOUT       O   Inverse projection of VIN. */
/*     FOUND      O   Flag indicating whether VOUT could be calculated. */

/* $ Detailed_Input */

/*     VIN, */
/*     PROJPL, */
/*     INVPL          are, respectively, a 3-vector, a SPICELIB plane */
/*                    containing the vector, and a SPICELIB plane */
/*                    containing the inverse image of the vector under */
/*                    orthogonal projection onto PROJPL. */

/* $ Detailed_Output */

/*     VOUT           is the inverse orthogonal projection of VIN.  This */
/*                    is the vector lying in the plane INVPL whose */
/*                    orthogonal projection onto the plane PROJPL is */
/*                    VIN.  VOUT is valid only when FOUND (defined below) */
/*                    is .TRUE.  Otherwise, VOUT is undefined. */

/*     FOUND          indicates whether the inverse orthogonal projection */
/*                    of VIN could be computed.  FOUND is .TRUE. if so, */
/*                    .FALSE. otherwise. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1)  If the geometric planes defined by PROJPL and INVPL are */
/*         orthogonal, or nearly so, the inverse orthogonal projection */
/*         of VIN may be undefined or have magnitude too large to */
/*         represent with double precision numbers.  In either such */
/*         case, FOUND will be set to .FALSE. */

/*     2)  Even when FOUND is .TRUE., VOUT may be a vector of extremely */
/*         large magnitude, perhaps so large that it is impractical to */
/*         compute with it.  It's up to you to make sure that this */
/*         situation does not occur in your application of this routine. */

/* $ Files */

/*     None. */

/* $ Particulars */

/*     Projecting a vector orthogonally onto a plane can be thought of */
/*     as finding the closest vector in the plane to the original vector. */
/*     This `closest vector' always exists; it may be coincident with the */
/*     original vector.  Inverting an orthogonal projection means finding */
/*     the vector in a specified plane whose orthogonal projection onto */
/*     a second specified plane is a specified vector.  The vector whose */
/*     projection is the specified vector is the inverse projection of */
/*     the specified vector, also called the `inverse image under */
/*     orthogonal projection' of the specified vector.  This routine */
/*     finds the inverse orthogonal projection of a vector onto a plane. */

/*     Related routines are VPRJP, which projects a vector onto a plane */
/*     orthogonally, and VPROJ, which projects a vector onto another */
/*     vector orthogonally. */

/* $ Examples */

/*     1)   Suppose */

/*             VIN    =  ( 0.0, 1.0, 0.0 ), */

/*          and that PROJPL has normal vector */

/*             PROJN  =  ( 0.0, 0.0, 1.0 ). */

/*          Also, let's suppose that INVPL has normal vector and constant */

/*             INVN   =  ( 0.0, 2.0, 2.0 ) */
/*             INVC   =    4.0. */

/*          Then VIN lies on the y-axis in the x-y plane, and we want to */
/*          find the vector VOUT lying in INVPL such that the orthogonal */
/*          projection of VOUT the x-y plane is VIN.  Let the notation */
/*          < a, b > indicate the inner product of vectors a and b. */
/*          Since every point X in INVPL satisfies the equation */

/*             <  X,  (0.0, 2.0, 2.0)  >  =  4.0, */

/*          we can verify by inspection that the vector */

/*             ( 0.0, 1.0, 1.0 ) */

/*          is in INVPL and differs from VIN by a multiple of PROJN.  So */

/*             ( 0.0, 1.0, 1.0 ) */

/*          must be VOUT. */

/*          To find this result using SPICELIB, we can create the */
/*          SPICELIB planes PROJPL and INVPL using the code fragment */

/*             CALL NVP2PL  ( PROJN,  VIN,   PROJPL ) */
/*             CALL NVC2PL  ( INVN,   INVC,  INVPL  ) */

/*          and then perform the inverse projection using the call */

/*             CALL VPRJPI ( VIN, PROJPL, INVPL, VOUT ) */

/*          VPRJPI will return the value */

/*             VOUT = ( 0.0, 1.0, 1.0 ) */

/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     [1] `Calculus and Analytic Geometry', Thomas and Finney. */

/* $ Author_and_Institution */

/*     N.J. Bachman   (JPL) */

/* $ Version */

/* -    SPICELIB Version 2.0.0, 17-FEB-2004 (NJB) */

/*        Computation of LIMIT was re-structured to avoid */
/*        run-time underflow warnings on some platforms. */

/* -    SPICELIB Version 1.0.1, 10-MAR-1992 (WLT) */

/*        Comment section for permuted index source lines was added */
/*        following the header. */

/* -    SPICELIB Version 1.0.0, 01-NOV-1990 (NJB) */

/* -& */
/* $ Index_Entries */

/*     vector projection onto plane inverted */

/* -& */
/* $ Revisions */

/* -    SPICELIB Version 2.0.0, 17-FEB-2004 (NJB) */

/*        Computation of LIMIT was re-structured to avoid */
/*        run-time underflow warnings on some platforms. */
/*        In the revised code, BOUND/DPMAX() is never */
/*        scaled by a number having absolute value < 1. */

/* -& */

/*     SPICELIB functions */


/*     Local parameters */


/*     BOUND is used to bound the magnitudes of the numbers that we */
/*     try to take the reciprocal of, since we can't necessarily invert */
/*     any non-zero number.  We won't try to invert any numbers with */
/*     magnitude less than */

/*        BOUND / DPMAX(). */

/*     BOUND is chosen somewhat arbitrarily.... */


/*     Local variables */


/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    } else {
	chkin_("VPRJPI", (ftnlen)6);
    }

/*     Unpack the planes. */

    pl2nvc_(projpl, projn, &projc);
    pl2nvc_(invpl, invn, &invc);

/*     We'll first discuss the computation of VOUT in the nominal case, */
/*     and then deal with the exceptional cases. */

/*     When PROJPL and INVPL are not orthogonal to each other, the */
/*     inverse projection of VIN will differ from VIN by a multiple of */
/*     PROJN, the unit normal vector to PROJPL.  We find this multiple */
/*     by using the fact that the inverse projection VOUT satisfies the */
/*     plane equation for the inverse projection plane INVPL. */

/*        We have */

/*           VOUT = VIN  +  MULT * PROJN;                           (1) */

/*        since VOUT satisfies */

/*           < VOUT, INVN >  =  INVC */

/*        we must have */

/*           <  VIN  +  MULT * PROJN,  INVN  > = INVC */

/*        which in turn implies */


/*                     INVC  -  < VIN, INVN > */
/*           MULT  =  ------------------------.                     (2) */
/*                        < PROJN, INVN > */

/*        Having MULT, we can compute VOUT according to equation (1). */

/*     Now, if the denominator in the above expression for MULT is zero */
/*     or just too small, performing the division would cause a */
/*     divide-by-zero error or an overflow of MULT.  In either case, we */
/*     will avoid carrying out the division, and we'll set FOUND to */
/*     .FALSE. */


/*     Compute the numerator and denominator of the right side of (2). */

    numer = invc - vdot_(vin, invn);
    denom = vdot_(projn, invn);

/*     If the magnitude of the denominator is greater than the absolute */
/*     value of */

/*                    BOUND */
/*        LIMIT  =  --------- * NUMER, */
/*                   DPMAX() */

/*     we can safely divide the numerator by the denominator, and the */
/*     magnitude of the result will be no greater than */

/*         DPMAX() */
/*        --------- . */
/*          BOUND */

/*     Note that we have ruled out the case where NUMER and DENOM are */
/*     both zero by insisting on strict inequality in the comparison of */
/*     DENOM and LIMIT. */

/*     We never set LIMIT smaller than BOUND/DPMAX(), since */
/*     the computation using NUMER causes underflow to be signaled */
/*     on some systems. */

    if (abs(numer) < 1.) {
	limit = 10. / dpmax_();
    } else {
	limit = (d__1 = 10. / dpmax_() * numer, abs(d__1));
    }
    if (abs(denom) > limit) {

/*        We can find VOUT after all. */

	mult = numer / denom;
	vlcom_(&c_b3, vin, &mult, projn, vout);
	*found = TRUE_;
    } else {

/*        No dice. */

	*found = FALSE_;
    }
    chkout_("VPRJPI", (ftnlen)6);
    return 0;
} /* vprjpi_ */
Esempio n. 2
0
/* $Procedure ZZEDTERM ( Ellipsoid terminator ) */
/* Subroutine */ int zzedterm_(char *type__, doublereal *a, doublereal *b, 
	doublereal *c__, doublereal *srcrad, doublereal *srcpos, integer *
	npts, doublereal *trmpts, ftnlen type_len)
{
    /* System generated locals */
    integer trmpts_dim2, i__1, i__2;
    doublereal d__1, d__2, d__3;

    /* Builtin functions */
    integer s_cmp(char *, char *, ftnlen, ftnlen);
    double asin(doublereal);
    integer s_rnge(char *, integer, char *, integer);
    double d_sign(doublereal *, doublereal *);

    /* Local variables */
    extern /* Subroutine */ int vadd_(doublereal *, doublereal *, doublereal *
	    );
    doublereal rmin, rmax;
    extern /* Subroutine */ int vscl_(doublereal *, doublereal *, doublereal *
	    );
    extern doublereal vdot_(doublereal *, doublereal *), vsep_(doublereal *, 
	    doublereal *);
    integer nitr;
    extern /* Subroutine */ int vsub_(doublereal *, doublereal *, doublereal *
	    ), vequ_(doublereal *, doublereal *);
    doublereal d__, e[3];
    integer i__;
    doublereal s, angle, v[3], x[3], delta, y[3], z__[3], inang;
    extern /* Subroutine */ int chkin_(char *, ftnlen), frame_(doublereal *, 
	    doublereal *, doublereal *);
    doublereal plane[4];
    extern /* Subroutine */ int ucase_(char *, char *, ftnlen, ftnlen), 
	    errch_(char *, char *, ftnlen, ftnlen), vpack_(doublereal *, 
	    doublereal *, doublereal *, doublereal *);
    doublereal theta;
    extern /* Subroutine */ int errdp_(char *, doublereal *, ftnlen);
    doublereal trans[9]	/* was [3][3] */, srcpt[3], vtemp[3];
    extern doublereal vnorm_(doublereal *), twopi_(void);
    extern /* Subroutine */ int ljust_(char *, char *, ftnlen, ftnlen), 
	    pl2nvc_(doublereal *, doublereal *, doublereal *);
    doublereal lambda;
    extern /* Subroutine */ int nvp2pl_(doublereal *, doublereal *, 
	    doublereal *);
    extern doublereal halfpi_(void);
    doublereal minang, minrad, maxang, maxrad;
    extern /* Subroutine */ int latrec_(doublereal *, doublereal *, 
	    doublereal *, doublereal *);
    doublereal angerr;
    logical umbral;
    extern doublereal touchd_(doublereal *);
    doublereal offset[3], prvdif;
    extern /* Subroutine */ int sigerr_(char *, ftnlen);
    doublereal outang, plcons, prvang;
    extern /* Subroutine */ int chkout_(char *, ftnlen), setmsg_(char *, 
	    ftnlen), errint_(char *, integer *, ftnlen);
    char loctyp[50];
    extern logical return_(void);
    extern /* Subroutine */ int vminus_(doublereal *, doublereal *);
    doublereal dir[3];
    extern /* Subroutine */ int mxv_(doublereal *, doublereal *, doublereal *)
	    ;
    doublereal vtx[3];

/* $ Abstract */

/*     SPICE Private routine intended solely for the support of SPICE */
/*     routines.  Users should not call this routine directly due */
/*     to the volatile nature of this routine. */

/*     Compute a set of points on the umbral or penumbral terminator of */
/*     a specified ellipsoid, given a spherical light source. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Required_Reading */

/*     ELLIPSES */

/* $ Keywords */

/*     BODY */
/*     GEOMETRY */
/*     MATH */

/* $ Declarations */
/* $ Brief_I/O */

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     TYPE       I   Terminator type. */
/*     A          I   Length of ellipsoid semi-axis lying on the x-axis. */
/*     B          I   Length of ellipsoid semi-axis lying on the y-axis. */
/*     C          I   Length of ellipsoid semi-axis lying on the z-axis. */
/*     SRCRAD     I   Radius of light source. */
/*     SRCPOS     I   Position of center of light source. */
/*     NPTS       I   Number of points in terminator point set. */
/*     TRMPTS     O   Terminator point set. */

/* $ Detailed_Input */

/*     TYPE           is a string indicating the type of terminator to */
/*                    compute:  umbral or penumbral.  The umbral */
/*                    terminator is the boundary of the portion of the */
/*                    ellipsoid surface in total shadow.  The penumbral */
/*                    terminator is the boundary of the portion of the */
/*                    surface that is completely illuminated.  Possible */
/*                    values of TYPE are */

/*                       'UMBRAL' */
/*                       'PENUMBRAL' */

/*                    Case and leading or trailing blanks in TYPE are */
/*                    not significant. */

/*     A, */
/*     B, */
/*     C              are the lengths of the semi-axes of a triaxial */
/*                    ellipsoid.  The ellipsoid is centered at the */
/*                    origin and oriented so that its axes lie on the */
/*                    x, y and z axes.  A, B, and C are the lengths of */
/*                    the semi-axes that point in the x, y, and z */
/*                    directions respectively. */

/*                    Length units associated with A, B, and C must */
/*                    match those associated with SRCRAD, SRCPOS, */
/*                    and the output TRMPTS. */

/*     SRCRAD         is the radius of the spherical light source. */

/*     SRCPOS         is the position of the center of the light source */
/*                    relative to the center of the ellipsoid. */

/*     NPTS           is the number of terminator points to compute. */


/* $ Detailed_Output */

/*     TRMPTS         is an array of points on the umbral or penumbral */
/*                    terminator of the ellipsoid, as specified by the */
/*                    input argument TYPE.  The Ith point is contained */
/*                    in the array elements */

/*                        TRMPTS(J,I),  J = 1, 2, 3 */

/*                    The terminator points are expressed in the */
/*                    body-fixed reference frame associated with the */
/*                    ellipsoid.  Units are those associated with */
/*                    the input axis lengths. */

/*                    Each terminator point is the point of tangency of */
/*                    a plane that is also tangent to the light source. */
/*                    These associated points of tangency on the light */
/*                    source have uniform distribution in longitude when */
/*                    expressed in a cylindrical coordinate system whose */
/*                    Z-axis is SRCPOS.  The magnitude of the separation */
/*                    in longitude between these tangency points on the */
/*                    light source is */

/*                       2*Pi / NPTS */

/*                    If the target is spherical, the terminator points */
/*                    also are uniformly distributed in longitude in the */
/*                    cylindrical system described above.  If the target */
/*                    is non-spherical, the longitude distribution of */
/*                    the points generally is not uniform. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1)  If the terminator type is not recognized, the error */
/*         SPICE(NOTSUPPORTED) is signaled. */

/*     2)  If the set size NPTS is not at least 1, the error */
/*         SPICE(INVALIDSIZE) is signaled. */

/*     3)  If any of the ellipsoid's semi-axis lengths is non-positive, */
/*         the error SPICE(INVALIDAXISLENGTH) is signaled. */

/*     4)  If the light source has non-positive radius, the error */
/*         SPICE(INVALIDRADIUS) is signaled. */

/*     5)  If the light source intersects the smallest sphere */
/*         centered at the origin and containing the ellipsoid, the */
/*         error SPICE(OBJECTSTOOCLOSE) is signaled. */

/* $ Files */

/*     None. */

/* $ Particulars */

/*     This routine models the boundaries of shadow regions on an */
/*     ellipsoid "illuminated" by a spherical light source.  Light rays */
/*     are assumed to travel along straight lines; refraction is not */
/*     modeled. */

/*     Points on the ellipsoid at which the entire cap of the light */
/*     source is visible are considered to be completely illuminated. */
/*     Points on the ellipsoid at which some portion (or all) of the cap */
/*     of the light source are blocked are considered to be in partial */
/*     (or total) shadow. */

/*     In this routine, we use the term "umbral terminator" to denote */
/*     the curve ususally called the "terminator":  this curve is the */
/*     boundary of the portion of the surface that lies in total shadow. */
/*     We use the term "penumbral terminator" to denote the boundary of */
/*     the completely illuminated portion of the surface. */

/*     In general, the terminator on an ellipsoid is a more complicated */
/*     curve than the limb (which is always an ellipse).  Aside from */
/*     various special cases, the terminator does not lie in a plane. */

/*     However, the condition for a point X on the ellipsoid to lie on */
/*     the terminator is simple:  a plane tangent to the ellipsoid at X */
/*     must also be tangent to the light source.  If this tangent plane */
/*     does not intersect the vector from the center of the ellipsoid to */
/*     the center of the light source, then X lies on the umbral */
/*     terminator; otherwise X lies on the penumbral terminator. */

/* $ Examples */

/*     See the SPICELIB routine EDTERM. */

/* $ Restrictions */

/*     This is a private SPICELIB routine.  User applications should not */
/*     call this routine. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     N.J. Bachman    (JPL) */

/* $ Version */

/* -    SPICELIB Version 1.0.0, 03-FEB-2007 (NJB) */

/* -& */
/* $ Index_Entries */

/*     find terminator on ellipsoid */
/*     find umbral terminator on ellipsoid */
/*     find penumbral terminator on ellipsoid */

/* -& */

/*     SPICELIB functions */


/*     Local parameters */


/*     Local variables */


/*     Standard SPICELIB error handling. */

    /* Parameter adjustments */
    trmpts_dim2 = *npts;

    /* Function Body */
    if (return_()) {
	return 0;
    }
    chkin_("ZZEDTERM", (ftnlen)8);

/*     Check the terminator type. */

    ljust_(type__, loctyp, type_len, (ftnlen)50);
    ucase_(loctyp, loctyp, (ftnlen)50, (ftnlen)50);
    if (s_cmp(loctyp, "UMBRAL", (ftnlen)50, (ftnlen)6) == 0) {
	umbral = TRUE_;
    } else if (s_cmp(loctyp, "PENUMBRAL", (ftnlen)50, (ftnlen)9) == 0) {
	umbral = FALSE_;
    } else {
	setmsg_("Terminator type must be UMBRAL or PENUMBRAL but was actuall"
		"y #.", (ftnlen)63);
	errch_("#", type__, (ftnlen)1, type_len);
	sigerr_("SPICE(NOTSUPPORTED)", (ftnlen)19);
	chkout_("ZZEDTERM", (ftnlen)8);
	return 0;
    }

/*     Check the terminator set dimension. */

    if (*npts < 1) {
	setmsg_("Set must contain at least one point; NPTS  = #.", (ftnlen)47)
		;
	errint_("#", npts, (ftnlen)1);
	sigerr_("SPICE(INVALIDSIZE)", (ftnlen)18);
	chkout_("ZZEDTERM", (ftnlen)8);
	return 0;
    }

/*     The ellipsoid semi-axes must have positive length. */

    if (*a <= 0. || *b <= 0. || *c__ <= 0.) {
	setmsg_("Semi-axis lengths:  A = #, B = #, C = #. ", (ftnlen)41);
	errdp_("#", a, (ftnlen)1);
	errdp_("#", b, (ftnlen)1);
	errdp_("#", c__, (ftnlen)1);
	sigerr_("SPICE(INVALIDAXISLENGTH)", (ftnlen)24);
	chkout_("ZZEDTERM", (ftnlen)8);
	return 0;
    }

/*     Check the input light source radius. */

    if (*srcrad <= 0.) {
	setmsg_("Light source must have positive radius; actual radius was #."
		, (ftnlen)60);
	errdp_("#", srcrad, (ftnlen)1);
	sigerr_("SPICE(INVALIDRADIUS)", (ftnlen)20);
	chkout_("ZZEDTERM", (ftnlen)8);
	return 0;
    }

/*     The light source must not intersect the outer bounding */
/*     sphere of the ellipsoid. */

    d__ = vnorm_(srcpos);
/* Computing MAX */
    d__1 = max(*a,*b);
    rmax = max(d__1,*c__);
/* Computing MIN */
    d__1 = min(*a,*b);
    rmin = min(d__1,*c__);
    if (*srcrad + rmax >= d__) {

/*        The light source is too close. */

	setmsg_("Light source intersects outer bounding sphere of the ellips"
		"oid.  Light source radius = #; ellipsoid's longest axis = #;"
		" sum = #; distance between centers = #.", (ftnlen)158);
	errdp_("#", srcrad, (ftnlen)1);
	errdp_("#", &rmax, (ftnlen)1);
	d__1 = *srcrad + rmax;
	errdp_("#", &d__1, (ftnlen)1);
	errdp_("#", &d__, (ftnlen)1);
	sigerr_("SPICE(OBJECTSTOOCLOSE)", (ftnlen)22);
	chkout_("ZZEDTERM", (ftnlen)8);
	return 0;
    }

/*     Find bounds on the angular size of the target as seen */
/*     from the source. */

/* Computing MIN */
    d__1 = rmax / d__;
    minang = asin((min(d__1,1.)));
/* Computing MIN */
    d__1 = rmin / d__;
    maxang = asin((min(d__1,1.)));

/*     Let the inverse of the ellipsoid-light source vector be the */
/*     Z-axis of a frame we'll use to generate the terminator set. */

    vminus_(srcpos, z__);
    frame_(z__, x, y);

/*     Create the rotation matrix required to convert vectors */
/*     from the source-centered frame back to the target body-fixed */
/*     frame. */

    vequ_(x, trans);
    vequ_(y, &trans[3]);
    vequ_(z__, &trans[6]);

/*     Find the maximum and minimum target radii. */

/* Computing MAX */
    d__1 = max(*a,*b);
    maxrad = max(d__1,*c__);
/* Computing MIN */
    d__1 = min(*a,*b);
    minrad = min(d__1,*c__);
    if (umbral) {

/*        Compute the angular offsets from the axis of rays tangent to */
/*        both the source and the bounding spheres of the target, where */
/*        the tangency points lie in a half-plane bounded by the line */
/*        containing the origin and SRCPOS.  (We'll call this line */
/*        the "axis.") */

/*        OUTANG corresponds to the target's outer bounding sphere; */
/*        INANG to the inner bounding sphere. */

	outang = asin((*srcrad - maxrad) / d__);
	inang = asin((*srcrad - minrad) / d__);
    } else {

/*        Compute the angular offsets from the axis of rays tangent to */
/*        both the source and the bounding spheres of the target, where */
/*        the tangency points lie in opposite half-planes bounded by the */
/*        axis (compare the case above). */

/*        OUTANG corresponds to the target's outer bounding sphere; */
/*        INANG to the inner bounding sphere. */

	outang = asin((*srcrad + maxrad) / d__);
	inang = asin((*srcrad + minrad) / d__);
    }

/*     Compute the angular delta we'll use for generating */
/*     terminator points. */

    delta = twopi_() / *npts;

/*     Generate the terminator points. */

    i__1 = *npts;
    for (i__ = 1; i__ <= i__1; ++i__) {
	theta = (i__ - 1) * delta;

/*        Let SRCPT be the surface point on the source lying in */
/*        the X-Y plane of the frame produced by FRAME */
/*        and corresponding to the angle THETA. */

	latrec_(srcrad, &theta, &c_b30, srcpt);

/*        Now solve for the angle by which SRCPT must be rotated (toward */
/*        +Z in the umbral case, away from +Z in the penumbral case) */
/*        so that a plane tangent to the source at SRCPT is also tangent */
/*        to the target. The rotation is bracketed by OUTANG on the low */
/*        side and INANG on the high side in the umbral case; the */
/*        bracketing values are reversed in the penumbral case. */

	if (umbral) {
	    angle = outang;
	} else {
	    angle = inang;
	}
	prvdif = twopi_();
	prvang = angle + halfpi_();
	nitr = 0;
	for(;;) { /* while(complicated condition) */
	    d__2 = (d__1 = angle - prvang, abs(d__1));
	    if (!(nitr <= 10 && touchd_(&d__2) < prvdif))
	    	break;
	    ++nitr;
	    d__2 = (d__1 = angle - prvang, abs(d__1));
	    prvdif = touchd_(&d__2);
	    prvang = angle;

/*           Find the closest point on the ellipsoid to the plane */
/*           corresponding to "ANGLE". */

/*           The tangent point on the source is obtained by rotating */
/*           SRCPT by ANGLE towards +Z.  The plane's normal vector is */
/*           parallel to VTX in the source-centered frame. */

	    latrec_(srcrad, &theta, &angle, vtx);
	    vequ_(vtx, dir);

/*           VTX and DIR are expressed in the source-centered frame.  We */
/*           must translate VTX to the target frame and rotate both */
/*           vectors into that frame. */

	    mxv_(trans, vtx, vtemp);
	    vadd_(srcpos, vtemp, vtx);
	    mxv_(trans, dir, vtemp);
	    vequ_(vtemp, dir);

/*           Create the plane defined by VTX and DIR. */

	    nvp2pl_(dir, vtx, plane);

/*           Find the closest point on the ellipsoid to the plane. At */
/*           the point we seek, the outward normal on the ellipsoid is */
/*           parallel to the choice of plane normal that points away */
/*           from the origin.  We can always obtain this choice from */
/*           PL2NVC. */

	    pl2nvc_(plane, dir, &plcons);

/*           At the point */

/*               E = (x, y, z) */

/*           on the ellipsoid's surface, an outward normal */
/*           is */

/*               N = ( x/A**2, y/B**2, z/C**2 ) */

/*           which is also */

/*               lambda * ( DIR(1), DIR(2), DIR(3) ) */

/*           Equating components in the normal vectors yields */

/*               E = lambda * ( DIR(1)*A**2, DIR(2)*B**2, DIR(3)*C**2 ) */

/*           Taking the inner product with the point E itself and */
/*           applying the ellipsoid equation, we find */

/*               lambda * <DIR, E>  =  < N, E >  =  1 */

/*           The first term above is */

/*               lambda**2 * || ( A*DIR(1), B*DIR(2), C*DIR(3) ) ||**2 */

/*           So the positive root lambda is */

/*               1 / || ( A*DIR(1), B*DIR(2), C*DIR(3) ) || */

/*           Having lambda we can compute E. */

	    d__1 = *a * dir[0];
	    d__2 = *b * dir[1];
	    d__3 = *c__ * dir[2];
	    vpack_(&d__1, &d__2, &d__3, v);
	    lambda = 1. / vnorm_(v);
	    d__1 = *a * v[0];
	    d__2 = *b * v[1];
	    d__3 = *c__ * v[2];
	    vpack_(&d__1, &d__2, &d__3, e);
	    vscl_(&lambda, e, &trmpts[(i__2 = i__ * 3 - 3) < trmpts_dim2 * 3 
		    && 0 <= i__2 ? i__2 : s_rnge("trmpts", i__2, "zzedterm_", 
		    (ftnlen)586)]);

/*           Make a new estimate of the plane rotation required to touch */
/*           the target. */

	    vsub_(&trmpts[(i__2 = i__ * 3 - 3) < trmpts_dim2 * 3 && 0 <= i__2 
		    ? i__2 : s_rnge("trmpts", i__2, "zzedterm_", (ftnlen)592)]
		    , vtx, offset);

/*           Let ANGERR be an estimate of the magnitude of angular error */
/*           between the plane and the terminator. */

	    angerr = vsep_(dir, offset) - halfpi_();

/*           Let S indicate the sign of the altitude error:  where */
/*           S is positive, the plane is above E. */

	    d__1 = vdot_(e, dir);
	    s = d_sign(&c_b35, &d__1);
	    if (umbral) {

/*              If the plane is above the target, increase the */
/*              rotation angle; otherwise decrease the angle. */

		angle += s * angerr;
	    } else {

/*              This is the penumbral case; decreasing the angle */
/*              "lowers" the plane toward the target. */

		angle -= s * angerr;
	    }
	}
    }
    chkout_("ZZEDTERM", (ftnlen)8);
    return 0;
} /* zzedterm_ */
Esempio n. 3
0
/* $Procedure      PJELPL ( Project ellipse onto plane ) */
/* Subroutine */ int pjelpl_(doublereal *elin, doublereal *plane, doublereal *
	elout)
{
    extern /* Subroutine */ int chkin_(char *, ftnlen);
    doublereal const__;
    extern /* Subroutine */ int vperp_(doublereal *, doublereal *, doublereal 
	    *), vprjp_(doublereal *, doublereal *, doublereal *), el2cgv_(
	    doublereal *, doublereal *, doublereal *, doublereal *), cgv2el_(
	    doublereal *, doublereal *, doublereal *, doublereal *), pl2nvc_(
	    doublereal *, doublereal *, doublereal *);
    doublereal prjvc1[3], prjvc2[3], center[3], normal[3], smajor[3];
    extern /* Subroutine */ int chkout_(char *, ftnlen);
    doublereal prjctr[3], sminor[3];
    extern logical return_(void);

/* $ Abstract */

/*     Project an ellipse onto a plane, orthogonally. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Required_Reading */

/*     ELLIPSES */
/*     PLANES */

/* $ Keywords */

/*     ELLIPSE */
/*     GEOMETRY */
/*     MATH */

/* $ Declarations */
/* $ Brief_I/O */

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     ELIN       I   A SPICELIB ellipse to be projected. */
/*     PLANE      I   A plane onto which ELIN is to be projected. */
/*     ELOUT      O   A SPICELIB ellipse resulting from the projection. */

/* $ Detailed_Input */

/*     ELIN, */
/*     PLANE          are, respectively, a SPICELIB ellipse and a */
/*                    SPICELIB plane.  The geometric ellipse represented */
/*                    by ELIN is to be orthogonally projected onto the */
/*                    geometric plane represented by PLANE. */

/* $ Detailed_Output */

/*     ELOUT          is a SPICELIB ellipse that represents the geometric */
/*                    ellipse resulting from orthogonally projecting the */
/*                    ellipse represented by INEL onto the plane */
/*                    represented by PLANE. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1)  If the input plane is invalid, the error will be diagnosed */
/*         by routines called by this routine. */

/*     2)  The input ellipse may be degenerate--its semi-axes may be */
/*         linearly dependent.  Such ellipses are allowed as inputs. */

/*     3)  The ellipse resulting from orthogonally projecting the input */
/*         ellipse onto a plane may be degenerate, even if the input */
/*         ellipse is not. */

/* $ Files */

/*     None. */

/* $ Particulars */

/*     Projecting an ellipse orthogonally onto a plane can be thought of */
/*     finding the points on the plane that are `under' or `over' the */
/*     ellipse, with the `up' direction considered to be perpendicular */
/*     to the plane.  More mathematically, the orthogonal projection is */
/*     the set of points Y in the plane such that for some point X in */
/*     the ellipse, the vector Y - X is perpendicular to the plane. */
/*     The orthogonal projection of an ellipse onto a plane yields */
/*     another ellipse. */

/* $ Examples */

/*     1)  With  CENTER  = ( 1.D0,  1.D0,  1.D0 ), */
/*               VECT1   = ( 2.D0,  0.D0,  0.D0 ), */
/*               VECT2   = ( 0.D0,  1.D0,  1.D0 ), */
/*               NORMAL  = ( 0.D0,  0.D0,  1.D0 ), */

/*         the code fragment */

/*               CALL NVC2PL ( NORMAL,  0.D0,    PLANE           ) */
/*               CALL CGV2EL ( CENTER,  VECT1,   VECT2,   ELIN   ) */
/*               CALL PJELPL ( ELIN,    PLANE,   ELOUT           ) */
/*               CALL EL2CGV ( ELOUT,   PRJCTR,  PRJMAJ,  PRJMIN ) */

/*         returns */

/*               PRJCTR  = ( 1.D0,  1.D0,  0.D0 ) */
/*               PRJMAJ  = ( 2.D0,  0.D0,  0.D0 ) */
/*               PRJMIN  = ( 0.D0,  1.D0,  0.D0 ) */


/*     2)  With  VECT1   = ( 2.D0,  0.D0,  0.D0 ), */
/*               VECT2   = ( 1.D0,  1.D0,  1.D0 ), */
/*               CENTER  = ( 0.D0,  0.D0,  0.D0 ), */
/*               NORMAL  = ( 0.D0,  0.D0,  1.D0 ), */

/*         the code fragment */

/*               CALL NVC2PL ( NORMAL,  0.D0,    PLANE           ) */
/*               CALL CGV2EL ( CENTER,  VECT1,   VECT2,   ELIN   ) */
/*               CALL PJELPL ( ELIN,    PLANE,   ELOUT           ) */
/*               CALL EL2CGV ( ELOUT,   PRJCTR,  PRJMAJ,  PRJMIN ) */

/*         returns */

/*               PRJCTR  = ( 0.D0,  0.D0,  0.D0 ) */

/*               PRJMAJ  = ( -2.227032728823213D0, */
/*                           -5.257311121191336D-1, */
/*                            0.D0                  ) */

/*               PRJMIN  = (  2.008114158862273D-1, */
/*                           -8.506508083520399D-1, */
/*                            0.D0                  ) */



/*     3)    An example of actual use:   Suppose we wish to compute the */
/*           distance from an ellipsoid to a line.   Let the line be */
/*           defined by a point P and a direction vector DIRECT; the */
/*           line is the set of points */

/*              P   +   t * DIRECT, */

/*           where t is any real number.  Let the ellipsoid have semi- */
/*           axis lengths A, B, and C. */

/*           We can reduce the problem to that of finding the distance */
/*           between the line and an ellipse on the ellipsoid surface by */
/*           considering the fact that the surface normal at the nearest */
/*           point to the line will be orthogonal to DIRECT; the set of */
/*           surface points where this condition holds lies in a plane, */
/*           and hence is an ellipse on the surface.  The problem can be */
/*           further simplified by projecting the ellipse orthogonally */
/*           onto the plane defined by */

/*              < X, DIRECT >  =  0. */

/*           The problem is then a two dimensional one:  find the */
/*           distance of the projected ellipse from the intersection of */
/*           the line and this plane (which is necessarily one point). */
/*           A `paraphrase' of the relevant code is: */


/*              C     Step 1.   Find the candidate ellipse CAND. */
/*              C               NORMAL is a normal vector to the plane */
/*              C               containing the candidate ellipse.  The */
/*              C               ellipse must exist, since it's the */
/*              C               intersection of an ellipsoid centered at */
/*              C               the origin and a plane containing the */
/*              C               origin.  For this reason, we don't check */
/*              C               INEDPL's `found flag' FOUND below. */
/*              C */
/*                    NORMAL(1)  =  DIRECT(1) / A**2 */
/*                    NORMAL(2)  =  DIRECT(2) / B**2 */
/*                    NORMAL(3)  =  DIRECT(3) / C**2 */

/*                    CALL NVC2PL ( NORMAL, 0.D0, CANDPL ) */

/*                    CALL INEDPL ( A, B, C, CANDPL, CAND, FOUND ) */

/*              C */
/*              C     Step 2.   Project the candidate ellipse onto a */
/*              C               plane orthogonal to the line.  We'll */
/*              C               call the plane PRJPL and the */
/*              C               projected ellipse PRJEL. */
/*              C */
/*                     CALL NVC2PL ( DIRECT,  0.D0,   PRJPL ) */
/*                     CALL PJELPL ( CAND,    PRJPL,  PRJEL ) */

/*              C */
/*              C     Step 3.   Find the point on the line lying in the */
/*              C               projection plane, and then find the */
/*              C               near point PJNEAR on the projected */
/*              C               ellipse.  Here PRJPT is the point on the */
/*              C               input line that lies in the projection */
/*              C               plane.  The distance between PRJPT and */
/*              C               PJNEAR is DIST. */

/*                    CALL VPRJP  ( LINEPT,  PRJPL,  PRJPT         ) */
/*                    CALL NPEDPT ( PRJEL,   PRJPT,  PJNEAR,  DIST ) */

/*              C */
/*              C     Step 4.  Find the near point PNEAR on the */
/*              C              ellipsoid by taking the inverse */
/*              C              orthogonal projection of PJNEAR; this is */
/*              C              the point on the candidate ellipse that */
/*              C              projects to PJNEAR.  Note that the output */
/*              C              DIST was computed in step 3. */
/*              C */
/*              C              The inverse projection of PJNEAR is */
/*              C              guaranteed to exist, so we don't have to */
/*              C              check FOUND. */
/*              C */
/*                    CALL VPRJPI ( PJNEAR, PRJPL, CANDPL, PNEAR, FOUND ) */


/*           The value of DIST returned is the distance we're looking */
/*           for. */

/*           The procedure described here is carried out in the routine */
/*           NPEDLN. */


/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     N.J. Bachman   (JPL) */

/* $ Version */

/* -    SPICELIB Version 1.0.1, 10-MAR-1992 (WLT) */

/*        Comment section for permuted index source lines was added */
/*        following the header. */

/* -    SPICELIB Version 1.0.0, 02-NOV-1990 (NJB) */

/* -& */
/* $ Index_Entries */

/*     project ellipse onto plane */

/* -& */

/*     SPICELIB functions */


/*     Local variables */


/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    } else {
	chkin_("PJELPL", (ftnlen)6);
    }

/*     Find generating vectors of the input ellipse. */

    el2cgv_(elin, center, smajor, sminor);

/*     Find a normal vector for the input plane. */

    pl2nvc_(plane, normal, &const__);

/*     Find the components of the semi-axes that are orthogonal to the */
/*     input plane's normal vector.  The components are generating */
/*     vectors for the projected plane. */

    vperp_(smajor, normal, prjvc1);
    vperp_(sminor, normal, prjvc2);

/*     Find the projection of the ellipse's center onto the input plane. */
/*     This is the center of the projected ellipse. */

/*     In case the last assertion is non-obvious, note that the */
/*     projection we're carrying out is the composition of a linear */
/*     mapping (projection to a plane containing the origin and parallel */
/*     to PLANE) and a translation mapping (adding the closest point to */
/*     the origin in PLANE to every point), and both linear mappings and */
/*     translations carry the center of an ellipse to the center of the */
/*     ellipse's image.  Let's state this using mathematical symbols. */
/*     Let L be a linear mapping and let T be a translation mapping, */
/*     say */

/*        T(x) = x + A. */

/*     Then */

/*           T  (  L ( center + cos(theta)smajor + sin(theta)sminor )  ) */

/*        =  A  +  L ( center + cos(theta)smajor + sin(theta)sminor ) */

/*        =  A  +  L (center) */
/*              +  cos(theta) L(smajor) */
/*              +  sin(theta) L(sminor) */

/*     From the form of this last expression, we see that we have an */
/*     ellipse centered at */

/*           A  +  L (center) */

/*        =  T  (  L (center)  ) */

/*     This last term is the image of the center of the original ellipse, */
/*     as we wished to demonstrate. */

/*     Now in the case of orthogonal projection onto a plane PL, L can be */
/*     taken as the orthogonal projection onto a parallel plane PL' */
/*     containing the origin.  Then L is a linear mapping.  Let M be */
/*     the multiple of the normal vector of PL such that M is contained */
/*     in PL (M is the closest point in PL to the origin).  Then the */
/*     orthogonal projection mapping onto PL, which we will name PRJ, */
/*     can be defined by */

/*       PRJ (x)  =  L (x)  +  M. */

/*     So PRJ is the composition of a translation and a linear mapping, */
/*     as claimed. */


    vprjp_(center, plane, prjctr);

/*     Put together the projected ellipse. */

    cgv2el_(prjctr, prjvc1, prjvc2, elout);
    chkout_("PJELPL", (ftnlen)6);
    return 0;
} /* pjelpl_ */
Esempio n. 4
0
File: pl2nvp.c Progetto: Dbelsa/coft
/* $Procedure      PL2NVP ( Plane to normal vector and point ) */
/* Subroutine */ int pl2nvp_(doublereal *plane, doublereal *normal, 
	doublereal *point)
{
    extern /* Subroutine */ int vscl_(doublereal *, doublereal *, doublereal *
	    );
    doublereal const__;
    extern /* Subroutine */ int pl2nvc_(doublereal *, doublereal *, 
	    doublereal *);

/* $ Abstract */

/*     Return a unit normal vector and point that define a specified */
/*     plane. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Required_Reading */

/*     PLANES */

/* $ Keywords */

/*     GEOMETRY */
/*     MATH */
/*     PLANE */

/* $ Declarations */
/* $ Brief_I/O */

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     PLANE      I   A SPICELIB plane. */
/*     NORMAL, */
/*     POINT      O   A unit normal vector and point that define PLANE. */

/* $ Detailed_Input */

/*     PLANE          is a SPICELIB plane. */

/* $ Detailed_Output */

/*     NORMAL, */
/*     POINT          are, respectively, a unit normal vector and point */
/*                    that define the geometric plane represented by */
/*                    PLANE.  Let the symbol < a, b > indicate the inner */
/*                    product of vectors a and b; then the geometric */
/*                    plane is the set of vectors X in three-dimensional */
/*                    space that satisfy */

/*                       < X - POINT, NORMAL >  =  0. */

/*                    POINT is always the closest point in the input */
/*                    plane to the origin.  POINT is always a */
/*                    non-negative scalar multiple of NORMAL. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     Error free. */

/*     1)  The input plane MUST have been created by one of the SPICELIB */
/*         routines */

/*            NVC2PL ( Normal vector and constant to plane ) */
/*            NVP2PL ( Normal vector and point to plane    ) */
/*            PSV2PL ( Point and spanning vectors to plane ) */

/*         Otherwise, the results of this routine are unpredictable. */

/* $ Files */

/*     None. */

/* $ Particulars */

/*     SPICELIB geometry routines that deal with planes use the `plane' */
/*     data type to represent input and output planes.  This data type */
/*     makes the subroutine interfaces simpler and more uniform. */

/*     The SPICELIB routines that produce SPICELIB planes from data that */
/*     define a plane are: */

/*        NVC2PL ( Normal vector and constant to plane ) */
/*        NVP2PL ( Normal vector and point to plane    ) */
/*        PSV2PL ( Point and spanning vectors to plane ) */

/*     The SPICELIB routines that convert SPICELIB planes to data that */
/*     define a plane are: */

/*        PL2NVC ( Plane to normal vector and constant ) */
/*        PL2NVP ( Plane to normal vector and point    ) */
/*        PL2PSV ( Plane to point and spanning vectors ) */

/* $ Examples */

/*     1)  Given a plane normal and constant, find a point in */
/*         the plane.  POINT is the point we seek. */

/*            CALL NVC2PL ( NORMAL, CONST,  PLANE ) */
/*            CALL PL2NVP ( PLANE,  NORMAL, POINT ) */

/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     [1] `Calculus and Analytic Geometry', Thomas and Finney. */

/* $ Author_and_Institution */

/*     N.J. Bachman   (JPL) */

/* $ Version */

/* -    SPICELIB Version 1.0.1, 10-MAR-1992 (WLT) */

/*        Comment section for permuted index source lines was added */
/*        following the header. */

/* -    SPICELIB Version 1.0.0, 01-NOV-1990 (NJB) */

/* -& */
/* $ Index_Entries */

/*     plane to normal vector and point */

/* -& */

/*     Local variables */


/*     Find a unit normal and constant for the plane.  Scaling the */
/*     unit normal by the constant gives us the closest point in */
/*     the plane to the origin. */

    pl2nvc_(plane, normal, &const__);
    vscl_(&const__, normal, point);
    return 0;
} /* pl2nvp_ */
Esempio n. 5
0
/* $Procedure      INEDPL ( Intersection of ellipsoid and plane ) */
/* Subroutine */ int inedpl_(doublereal *a, doublereal *b, doublereal *c__, 
	doublereal *plane, doublereal *ellips, logical *found)
{
    /* System generated locals */
    integer i__1, i__2, i__3;
    doublereal d__1, d__2;

    /* Builtin functions */
    integer s_rnge(char *, integer, char *, integer);
    double sqrt(doublereal);

    /* Local variables */
    doublereal dist, span1[3], span2[3];
    integer i__;
    extern /* Subroutine */ int chkin_(char *, ftnlen), errdp_(char *, 
	    doublereal *, ftnlen);
    doublereal const__, point[3];
    extern doublereal vnorm_(doublereal *);
    extern logical vzero_(doublereal *);
    extern /* Subroutine */ int cgv2el_(doublereal *, doublereal *, 
	    doublereal *, doublereal *), pl2nvc_(doublereal *, doublereal *, 
	    doublereal *), pl2psv_(doublereal *, doublereal *, doublereal *, 
	    doublereal *), psv2pl_(doublereal *, doublereal *, doublereal *, 
	    doublereal *);
    doublereal dplane[4];
    extern doublereal brcktd_(doublereal *, doublereal *, doublereal *);
    doublereal maxrad, rcircl, center[3], normal[3];
    extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *, 
	    ftnlen), vsclip_(doublereal *, doublereal *), setmsg_(char *, 
	    ftnlen);
    doublereal invdst[3];
    extern logical return_(void);
    doublereal dstort[3], vec1[3], vec2[3];

/* $ Abstract */

/*     Find the intersection of a triaxial ellipsoid and a plane. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Required_Reading */

/*     ELLIPSES */
/*     PLANES */

/* $ Keywords */

/*     ELLIPSE */
/*     ELLIPSOID */
/*     GEOMETRY */
/*     MATH */

/* $ Declarations */
/* $ Brief_I/O */

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     A          I   Length of ellipsoid semi-axis lying on the x-axis. */
/*     B          I   Length of ellipsoid semi-axis lying on the y-axis. */
/*     C          I   Length of ellipsoid semi-axis lying on the z-axis. */
/*     PLANE      I   Plane that intersects ellipsoid. */
/*     ELLIPS     O   Intersection ellipse, when FOUND is .TRUE. */
/*     FOUND      O   Flag indicating whether ellipse was found. */

/* $ Detailed_Input */

/*     A, */
/*     B, */
/*     C              are the lengths of the semi-axes of a triaxial */
/*                    ellipsoid.  The ellipsoid is centered at the */
/*                    origin and oriented so that its axes lie on the */
/*                    x, y and z axes.  A, B, and C are the lengths of */
/*                    the semi-axes that point in the x, y, and z */
/*                    directions respectively. */

/*     PLANE          is a SPICELIB plane. */

/* $ Detailed_Output */

/*     ELLIPS         is the SPICELIB ellipse formed by the intersection */
/*                    of the input plane and ellipsoid.  ELLIPS will */
/*                    represent a single point if the ellipsoid and */
/*                    plane are tangent. */

/*                    If the intersection of the ellipsoid and plane is */
/*                    empty, ELLIPS is not modified. */


/*     FOUND          is .TRUE. if and only if the intersection of the */
/*                    ellipsoid and plane is non-empty. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1)  If any of the lengths of the semi-axes of the input ellipsoid */
/*         are non-positive, the error SPICE(DEGENERATECASE) is */
/*         signaled.  ELLIPS is not modified.  FOUND is set to .FALSE. */

/*     2)  If the input plane in invalid, in other words, if the input */
/*         plane as the zero vector as its normal vector, the error */
/*         SPICE(INVALIDPLANE) is signaled. ELLIPS is not modified. */
/*         FOUND is set to .FALSE. */

/*     3)  If the input plane and ellipsoid are very nearly tangent, */
/*         roundoff error may cause this routine to give unreliable */
/*         results. */

/*     4)  If the input plane and ellipsoid are precisely tangent, the */
/*         intersection is a single point.  In this case, the output */
/*         ellipse is degenerate, but FOUND will still have the value */
/*         .TRUE.  You must decide whether this output makes sense for */
/*         your application. */

/* $ Files */

/*     None. */

/* $ Particulars */

/*     An ellipsoid and a plane can intersect in an ellipse, a single */
/*     point, or the empty set. */

/* $ Examples */

/*     1)  Suppose we wish to find the limb of a body, as observed from */
/*         location LOC in body-fixed coordinates.  The SPICELIB routine */
/*         EDLIMB solves this problem.  Here's how INEDPL is used in */
/*         that solution. */

/*         We assume LOC is outside of the body. The body is modelled as */
/*         a triaxial ellipsoid with semi-axes of length A, B, and C. */
/*         The notation */

/*            < X, Y > */

/*         indicates the inner product of the vectors X and Y. */

/*         The limb lies on the plane defined by */

/*            < X,  N >  =  1, */

/*         where the vector N is defined as */

/*            ( LOC(1) / A**2,   LOC(2) / B**2,   LOC(3) / C**2 ). */

/*         The assignments */

/*            N(1) = LOC(1) / A**2 */
/*            N(2) = LOC(2) / B**2 */
/*            N(3) = LOC(3) / C**2 */

/*         and the calls */

/*            CALL NVC2PL ( N,  1.0D0,  PLANE ) */

/*            CALL INEDPL ( A,  B,  C,  PLANE,  LIMB,  FOUND ) */

/*            CALL EL2CGV ( LIMB, CENTER, SMAJOR, SMINOR ) */

/*         will return the center and semi-axes of the limb. */


/*         How do we know that  < X, N > = 1  for all X on the limb? */
/*         This is because all limb points X satisfy */

/*            < LOC - X, SURFNM(X) >  =  0, */

/*         where SURFNM(X) is a surface normal at X.  SURFNM(X) is */
/*         parallel to the vector */

/*            V = (  X(1) / A**2,   X(2) / B**2,   X(3) / C**2  ) */

/*         so we have */

/*            < LOC - X, V >  =  0, */

/*            < LOC, V >      =  < X, V >  =  1  (from the original */
/*                                                ellipsoid */
/*                                                equation); */
/*         and finally */

/*            < X,   N >      =  1, */

/*         where the vector N is defined as */

/*            (  LOC(1) / A**2,    LOC(2) / B**2,   LOC(3) / C**2  ). */


/*     2)  Suppose we wish to find the terminator of a body.  We can */
/*         make a fair approximation to the location of the terminator */
/*         by finding the limb of the body as seen from the vertex of */
/*         the umbra; then the problem is essentially the same as in */
/*         example 1.  Let VERTEX be this location.  We make the */
/*         assignments */

/*            P(1) =   VERTEX(1) / A**2 */
/*            P(2) =   VERTEX(2) / B**2 */
/*            P(3) =   VERTEX(3) / C**2 */

/*         and then make the calls */

/*            CALL NVC2PL ( P,  1.0D0,  PLANE ) */

/*            CALL INEDPL ( A,  B,  C,  PLANE,  TERM,  FOUND ) */

/*         The SPICELIB ellipse TERM represents the terminator of the */
/*         body. */


/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     N.J. Bachman   (JPL) */

/* $ Version */

/* -    SPICELIB Version 1.2.0, 16-NOV-2005 (NJB) */

/*        Bug fix:  error detection for case of invalid input plane was */
/*        added. */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in VSCL calls. */

/* -    SPICELIB Version 1.1.0, 11-JUL-1995 (KRG) */

/*        Removed potential numerical precision problems that could be */
/*        caused by using a REAL constant in a double precision */
/*        computation. The value 1.0 was repaced with the value 1.0D0 in */
/*        the following three lines: */

/*           DSTORT(1) = 1.0 / A */
/*           DSTORT(2) = 1.0 / B */
/*           DSTORT(3) = 1.0 / C */

/*        Also changed was a numeric constant from 1.D0 to the */
/*        equivalent, but more aesthetically pleasing 1.0D0. */

/* -    SPICELIB Version 1.0.1, 10-MAR-1992 (WLT) */

/*        Comment section for permuted index source lines was added */
/*        following the header. */

/* -    SPICELIB Version 1.0.0, 02-NOV-1990 (NJB) */

/* -& */
/* $ Index_Entries */

/*     intersection of ellipsoid and plane */

/* -& */
/* $ Revisions */

/* -    SPICELIB Version 1.2.0, 16-NOV-2005 (NJB) */

/*        Bug fix:  error detection for case of invalid input plane was */
/*        added. */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in VSCL calls. */

/* -    SPICELIB Version 1.1.0, 11-JUL-1995 (KRG) */

/*        Removed potential numerical precision problems that could be */
/*        caused by using a REAL constant in a double precision */
/*        computation. The value 1.0 was repaced with the value 1.0D0 in */
/*        the following three lines: */

/*           DSTORT(1) = 1.0 / A */
/*           DSTORT(2) = 1.0 / B */
/*           DSTORT(3) = 1.0 / C */

/*        Also changed was a numeric constant from 1.D0 to the */
/*        equivalent, but more aesthetically pleasing 1.0D0. */

/* -    SPICELIB Version 1.0.1, 10-MAR-1992 (WLT) */

/*        Comment section for permuted index source lines was added */
/*        following the header. */

/* -& */

/*     SPICELIB functions */


/*     Local variables */


/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    } else {
	chkin_("INEDPL", (ftnlen)6);
    }

/*     We don't want to worry about flat ellipsoids: */

    if (*a <= 0. || *b <= 0. || *c__ <= 0.) {
	*found = FALSE_;
	setmsg_("Semi-axes: A = #,  B = #,  C = #.", (ftnlen)33);
	errdp_("#", a, (ftnlen)1);
	errdp_("#", b, (ftnlen)1);
	errdp_("#", c__, (ftnlen)1);
	sigerr_("SPICE(DEGENERATECASE)", (ftnlen)21);
	chkout_("INEDPL", (ftnlen)6);
	return 0;
    }

/*     Check input plane for zero normal vector. */

    pl2nvc_(plane, normal, &const__);
    if (vzero_(normal)) {
	setmsg_("Normal vector of the input PLANE is the zero vector.", (
		ftnlen)52);
	sigerr_("SPICE(INVALIDPLANE)", (ftnlen)19);
	chkout_("INEDPL", (ftnlen)6);
	return 0;
    }

/*     This algorithm is partitioned into a series of steps: */


/*     1)  Identify a linear transformation that maps the input */
/*         ellipsoid to the unit sphere.  We'll call this mapping the */
/*         `distortion' mapping.  Apply the distortion mapping to both */
/*         the input plane and ellipsoid.  The image of the plane under */
/*         this transformation will be a plane. */

/*     2)  Find the intersection of the transformed plane and the unit */
/*         sphere. */

/*     3)  Apply the inverse of the distortion mapping to the */
/*         intersection ellipse to find the undistorted intersection */
/*         ellipse. */


/*     Step 1: */

/*     Find the image of the ellipsoid and plane under the distortion */
/*     matrix.  Since the image of the ellipsoid is the unit sphere, */
/*     only the plane transformation requires any work. */

/*     If the input plane is too far from the origin to possibly */
/*     intersect the ellipsoid, return now.  This can save us */
/*     some numerical problems when we scale the plane and ellipsoid. */

/*     The point returned by PL2PSV is the closest point in PLANE */
/*     to the origin, so its norm gives the distance of the plane */
/*     from the origin. */

    pl2psv_(plane, point, span1, span2);
/* Computing MAX */
    d__1 = abs(*a), d__2 = abs(*b), d__1 = max(d__1,d__2), d__2 = abs(*c__);
    maxrad = max(d__1,d__2);
    if (vnorm_(point) > maxrad) {
	*found = FALSE_;
	chkout_("INEDPL", (ftnlen)6);
	return 0;
    }

/*     The distortion matrix and its inverse are */

/*        +-               -+        +-               -+ */
/*        |  1/A   0    0   |        |   A    0    0   | */
/*        |   0   1/B   0   |,       |   0    B    0   |. */
/*        |   0    0   1/C  |        |   0    0    C   | */
/*        +-               -+        +-               -+ */

/*     We declare them with length three, since we are going to make */
/*     use of the diagonal elements only. */

    dstort[0] = 1. / *a;
    dstort[1] = 1. / *b;
    dstort[2] = 1. / *c__;
    invdst[0] = *a;
    invdst[1] = *b;
    invdst[2] = *c__;

/*     Apply the distortion mapping to the input plane.  Applying */
/*     the distortion mapping to a point and two spanning vectors that */
/*     define the input plane yields a point and two spanning vectors */
/*     that define the distorted plane. */

    for (i__ = 1; i__ <= 3; ++i__) {
	point[(i__1 = i__ - 1) < 3 && 0 <= i__1 ? i__1 : s_rnge("point", i__1,
		 "inedpl_", (ftnlen)449)] = dstort[(i__2 = i__ - 1) < 3 && 0 
		<= i__2 ? i__2 : s_rnge("dstort", i__2, "inedpl_", (ftnlen)
		449)] * point[(i__3 = i__ - 1) < 3 && 0 <= i__3 ? i__3 : 
		s_rnge("point", i__3, "inedpl_", (ftnlen)449)];
	span1[(i__1 = i__ - 1) < 3 && 0 <= i__1 ? i__1 : s_rnge("span1", i__1,
		 "inedpl_", (ftnlen)450)] = dstort[(i__2 = i__ - 1) < 3 && 0 
		<= i__2 ? i__2 : s_rnge("dstort", i__2, "inedpl_", (ftnlen)
		450)] * span1[(i__3 = i__ - 1) < 3 && 0 <= i__3 ? i__3 : 
		s_rnge("span1", i__3, "inedpl_", (ftnlen)450)];
	span2[(i__1 = i__ - 1) < 3 && 0 <= i__1 ? i__1 : s_rnge("span2", i__1,
		 "inedpl_", (ftnlen)451)] = dstort[(i__2 = i__ - 1) < 3 && 0 
		<= i__2 ? i__2 : s_rnge("dstort", i__2, "inedpl_", (ftnlen)
		451)] * span2[(i__3 = i__ - 1) < 3 && 0 <= i__3 ? i__3 : 
		s_rnge("span2", i__3, "inedpl_", (ftnlen)451)];
    }
    psv2pl_(point, span1, span2, dplane);

/*     Step 2: */

/*     Find the intersection of the distorted plane and unit sphere. */


/*     The intersection of the distorted plane and the unit sphere */
/*     may be a circle, a point, or the empty set.  The distance of the */
/*     plane from the origin determines which type of intersection we */
/*     have.  If we represent the distorted plane by a unit normal */
/*     vector and constant, the size of the constant gives us the */
/*     distance of the plane from the origin.  If the distance is greater */
/*     than 1, the intersection of plane and unit sphere is empty. If */
/*     the distance is equal to 1, we have the tangency case. */

/*     The routine PL2PSV always gives us an output point that is the */
/*     closest point to the origin in the input plane.  This point is */
/*     the center of the intersection circle.  The spanning vectors */
/*     returned by PL2PSV, after we scale them by the radius of the */
/*     intersection circle, become an orthogonal pair of vectors that */
/*     extend from the center of the circle to the circle itself.  So, */
/*     the center and these scaled vectors define the intersection */
/*     circle. */

    pl2psv_(dplane, center, vec1, vec2);
    dist = vnorm_(center);
    if (dist > 1.) {
	*found = FALSE_;
	chkout_("INEDPL", (ftnlen)6);
	return 0;
    }

/*     Scale the generating vectors by the radius of the intersection */
/*     circle. */

/* Computing 2nd power */
    d__2 = dist;
    d__1 = 1. - d__2 * d__2;
    rcircl = sqrt(brcktd_(&d__1, &c_b32, &c_b33));
    vsclip_(&rcircl, vec1);
    vsclip_(&rcircl, vec2);

/*     Step 3: */

/*     Apply the inverse distortion to the intersection circle to find */
/*     the actual intersection ellipse. */

    for (i__ = 1; i__ <= 3; ++i__) {
	center[(i__1 = i__ - 1) < 3 && 0 <= i__1 ? i__1 : s_rnge("center", 
		i__1, "inedpl_", (ftnlen)511)] = invdst[(i__2 = i__ - 1) < 3 
		&& 0 <= i__2 ? i__2 : s_rnge("invdst", i__2, "inedpl_", (
		ftnlen)511)] * center[(i__3 = i__ - 1) < 3 && 0 <= i__3 ? 
		i__3 : s_rnge("center", i__3, "inedpl_", (ftnlen)511)];
	vec1[(i__1 = i__ - 1) < 3 && 0 <= i__1 ? i__1 : s_rnge("vec1", i__1, 
		"inedpl_", (ftnlen)512)] = invdst[(i__2 = i__ - 1) < 3 && 0 <=
		 i__2 ? i__2 : s_rnge("invdst", i__2, "inedpl_", (ftnlen)512)]
		 * vec1[(i__3 = i__ - 1) < 3 && 0 <= i__3 ? i__3 : s_rnge(
		"vec1", i__3, "inedpl_", (ftnlen)512)];
	vec2[(i__1 = i__ - 1) < 3 && 0 <= i__1 ? i__1 : s_rnge("vec2", i__1, 
		"inedpl_", (ftnlen)513)] = invdst[(i__2 = i__ - 1) < 3 && 0 <=
		 i__2 ? i__2 : s_rnge("invdst", i__2, "inedpl_", (ftnlen)513)]
		 * vec2[(i__3 = i__ - 1) < 3 && 0 <= i__3 ? i__3 : s_rnge(
		"vec2", i__3, "inedpl_", (ftnlen)513)];
    }

/*     Make an ellipse from the center and generating vectors. */

    cgv2el_(center, vec1, vec2, ellips);
    *found = TRUE_;
    chkout_("INEDPL", (ftnlen)6);
    return 0;
} /* inedpl_ */
Esempio n. 6
0
/* $Procedure      INRYPL ( Intersection of ray and plane ) */
/* Subroutine */ int inrypl_(doublereal *vertex, doublereal *dir, doublereal *
	plane, integer *nxpts, doublereal *xpt)
{
    /* System generated locals */
    doublereal d__1, d__2;

    /* Local variables */
    doublereal udir[3];
    extern /* Subroutine */ int vhat_(doublereal *, doublereal *), vscl_(
	    doublereal *, doublereal *, doublereal *);
    extern doublereal vdot_(doublereal *, doublereal *);
    extern /* Subroutine */ int vequ_(doublereal *, doublereal *);
    doublereal scale;
    extern /* Subroutine */ int chkin_(char *, ftnlen);
    extern doublereal dpmax_(void);
    extern /* Subroutine */ int vlcom_(doublereal *, doublereal *, doublereal 
	    *, doublereal *, doublereal *);
    doublereal const__, prjvn;
    extern doublereal vnorm_(doublereal *);
    extern logical vzero_(doublereal *);
    extern /* Subroutine */ int pl2nvc_(doublereal *, doublereal *, 
	    doublereal *), cleard_(integer *, doublereal *);
    doublereal mscale, prjdif, sclcon, toobig, normal[3], prjdir;
    extern logical smsgnd_(doublereal *, doublereal *);
    extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *, 
	    ftnlen), vsclip_(doublereal *, doublereal *), setmsg_(char *, 
	    ftnlen);
    extern logical return_(void);
    doublereal sclvtx[3];

/* $ Abstract */

/*     Find the intersection of a ray and a plane. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Required_Reading */

/*     PLANES */

/* $ Keywords */

/*     GEOMETRY */

/* $ Declarations */
/* $ Brief_I/O */

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     VERTEX, */
/*     DIR        I   Vertex and direction vector of ray. */
/*     PLANE      I   A SPICELIB plane. */
/*     NXPTS      O   Number of intersection points of ray and plane. */
/*     XPT        O   Intersection point, if NXPTS = 1. */

/* $ Detailed_Input */

/*     VERTEX, */
/*     DIR            are a point and direction vector that define a */
/*                    ray in three-dimensional space. */

/*     PLANE          is a SPICELIB plane. */

/* $ Detailed_Output */

/*     NXPTS          is the number of points of intersection of the */
/*                    input ray and plane.  Values and meanings of */
/*                    NXPTS are: */

/*                       0     No intersection. */

/*                       1     One point of intersection.  Note that */
/*                             this case may occur when the ray's */
/*                             vertex is in the plane. */

/*                      -1     An infinite number of points of */
/*                             intersection; the ray lies in the plane. */


/*     XPT            is the point of intersection of the input ray */
/*                    and plane, when there is exactly one point of */
/*                    intersection.  Otherwise, XPT is the zero vector. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1)  If the ray's direction vector is the zero vector, the error */
/*         SPICE(ZEROVECTOR) is signaled.  NXPTS and XPT are not */
/*         modified. */


/*     2)  If the ray's vertex is further than DPMAX() / 3 from the */
/*         origin, the error SPICE(VECTORTOOBIG) is signaled.  NXPTS */
/*         and XPT are not modified. */


/*     3)  If the input plane is s further than DPMAX() / 3 from the */
/*         origin, the error SPICE(VECTORTOOBIG) is signaled.  NXPTS */
/*         and XPT are not modified. */


/*     4)  The input plane should be created by one of the SPICELIB */
/*         routines */

/*            NVC2PL */
/*            NVP2PL */
/*            PSV2PL */

/*         Invalid input planes will cause unpredictable results. */


/*     5)  In the interest of good numerical behavior, in the case */
/*         where the ray's vertex is not in the plane, this routine */
/*         considers that an intersection of the ray and plane occurs */
/*         only if the distance between the ray's vertex and the */
/*         intersection point is less than DPMAX() / 3. */

/*         If VERTEX is not in the plane and this condition is not */
/*         met, then NXPTS is set to 0 and XPT is set to the zero */
/*         vector. */

/* $ Files */

/*     None. */

/* $ Particulars */

/*     The intersection of a ray and plane in three-dimensional space */
/*     can be a the empty set, a single point, or the ray itself. */

/* $ Examples */

/*     1)  Find the camera projection of the center of an extended */
/*         body.  For simplicity, we assume: */

/*            -- The camera has no distortion;  the image of a point */
/*               is determined by the intersection of the focal plane */
/*               and the line determined by the point and the camera's */
/*               focal point. */

/*            -- The camera's pointing matrix (C-matrix) is available */
/*               in a C-kernel. */


/*            C */
/*            C     Load Leapseconds and SCLK kernels to support time */
/*            C     conversion. */
/*            C */
/*                  CALL FURNSH ( 'LEAP.KER' ) */
/*                  CALL FURNSH ( 'SCLK.KER' ) */

/*            C */
/*            C     Load an SPK file containing ephemeris data for */
/*            C     observer (a spacecraft, whose NAIF integer code */
/*            C     is SC) and target at the UTC epoch of observation. */
/*            C */
/*                  CALL FURNSH ( 'SPK.BSP' ) */

/*            C */
/*            C     Load a C-kernel containing camera pointing for */
/*            C     the UTC epoch of observation. */
/*            C */
/*                  CALL FURNSH ( 'CK.BC' ) */

/*            C */
/*            C     Find the ephemeris time (barycentric dynamical time) */
/*            C     and encoded spacecraft clock times corresponding to */
/*            C     the UTC epoch of observation. */
/*            C */
/*                  CALL UTC2ET ( UTC, ET          ) */
/*                  CALL SCE2C  ( SC,  ET,  SCLKDP ) */

/*            C */
/*            C     Encode the pointing lookup tolerance. */
/*            C */
/*                  CALL SCTIKS ( SC, TOLCH,  TOLDP  ) */

/*            C */
/*            C     Find the observer-target vector at the observation */
/*            C     epoch.  In this example, we'll use a light-time */
/*            C     corrected state vector. */
/*            C */
/*                  CALL SPKEZ ( TARGET,  ET,  'J2000',  'LT',  SC, */
/*                 .             STATE,   LT                        ) */

/*            C */
/*            C     Look up camera pointing. */
/*            C */
/*                  CALL CKGP  ( CAMERA, SCLKDP, TOLDP, 'J2000', CMAT, */
/*                 .             CLKOUT, FOUND                        ) */

/*                  IF ( .NOT. FOUND ) THEN */

/*                     [Handle this case...] */

/*                  END IF */

/*            C */
/*            C     Negate the spacecraft-to-target body vector and */
/*            C     convert it to camera coordinates. */
/*            C */
/*                  CALL VMINUS ( STATE, DIR       ) */
/*                  CALL MXV    ( CMAT,  DIR,  DIR ) */

/*            C */
/*            C     If FL is the camera's focal length, the effective */
/*            C     focal point is */
/*            C */
/*            C        FL * ( 0, 0, 1 ) */
/*            C */
/*                  CALL VSCL ( FL, ZVEC, FOCUS ) */

/*            C */
/*            C     The camera's focal plane contains the origin in */
/*            C     camera coordinates, and the z-vector is orthogonal */
/*            C     to the plane.  Make a SPICELIB plane representing */
/*            C     the focal plane. */
/*            C */
/*                  CALL NVC2PL ( ZVEC, 0.D0, FPLANE ) */

/*            C */
/*            C     The image of the target body's center in the focal */
/*            C     plane is defined by the intersection with the focal */
/*            C     plane of the ray whose vertex is the focal point and */
/*            C     whose direction is DIR. */
/*            C */
/*                  CALL INRYPL ( FOCUS, DIR, FPLANE, NXPTS, IMAGE ) */

/*                  IF ( NXPTS .EQ. 1 ) THEN */
/*            C */
/*            C        The body center does project to the focal plane. */
/*            C        Check whether the image is actually in the */
/*            C        camera's field of view... */
/*            C */
/*                               . */
/*                               . */
/*                               . */
/*                  ELSE */

/*            C */
/*            C        The body center does not map to the focal plane. */
/*            C        Handle this case... */
/*            C */
/*                               . */
/*                               . */
/*                               . */
/*                  END IF */



/*     2)  Find the Saturn ring plane intercept of a spacecraft-mounted */
/*         instrument's boresight vector.  We want the find the point */
/*         in the ring plane that will be observed by an instrument */
/*         with a give boresight direction at a specified time.  We */
/*         must account for light time and stellar aberration in order */
/*         to find this point.  The intercept point will be expressed */
/*         in Saturn body-fixed coordinates. */

/*         In this example, we assume */

/*            -- The ring plane is equatorial. */

/*            -- Light travels in a straight line. */

/*            -- The light time correction for the ring plane intercept */
/*               can be obtained by performing three light-time */
/*               correction iterations.  If this assumption does not */
/*               lead to a sufficiently accurate result, additional */
/*               iterations can be performed. */

/*            -- A Newtonian approximation of stellar aberration */
/*               suffices. */

/*            -- The boresight vector is given in J2000 coordinates. */

/*            -- The observation epoch is ET ephemeris seconds past */
/*               J2000. */

/*            -- The boresight vector, spacecraft and planetary */
/*               ephemerides, and ring plane orientation are all known */
/*               with sufficient accuracy for the application. */

/*            -- All necessary kernels are loaded by the caller of */
/*               this example routine. */


/*            SUBROUTINE RING_XPT ( SC, ET, BORVEC, SBFXPT, FOUND ) */
/*            IMPLICIT NONE */

/*            CHARACTER*(*)         SC */
/*            DOUBLE PRECISION      ET */
/*            DOUBLE PRECISION      BORVEC ( 3 ) */
/*            DOUBLE PRECISION      SBFXPT ( 3 ) */
/*            LOGICAL               FOUND */

/*      C */
/*      C     SPICELIB functions */
/*      C */
/*            DOUBLE PRECISION      CLIGHT */
/*            DOUBLE PRECISION      VDIST */

/*      C */
/*      C     Local parameters */
/*      C */
/*            INTEGER               UBPL */
/*            PARAMETER           ( UBPL = 4 ) */

/*            INTEGER               SATURN */
/*            PARAMETER           ( SATURN = 699 ) */

/*      C */
/*      C     Local variables */
/*      C */
/*            DOUBLE PRECISION      BORV2  ( 3 ) */
/*            DOUBLE PRECISION      CORVEC ( 3 ) */
/*            DOUBLE PRECISION      LT */
/*            DOUBLE PRECISION      PLANE  ( UBPL ) */
/*            DOUBLE PRECISION      SATSSB ( 6 ) */
/*            DOUBLE PRECISION      SCPOS  ( 3 ) */
/*            DOUBLE PRECISION      SCSSB  ( 6 ) */
/*            DOUBLE PRECISION      STATE  ( 6 ) */
/*            DOUBLE PRECISION      STCORR ( 3 ) */
/*            DOUBLE PRECISION      TAU */
/*            DOUBLE PRECISION      TPMI   ( 3,  3 ) */
/*            DOUBLE PRECISION      XPT    ( 3 ) */
/*            DOUBLE PRECISION      ZVEC   ( 3 ) */

/*            INTEGER               I */
/*            INTEGER               NXPTS */
/*            INTEGER               SCID */

/*            LOGICAL               FND */

/*      C */
/*      C     First step:  account for stellar aberration.  Since the */
/*      C     instrument pointing is given, we need to find the intercept */
/*      C     point such that, when the stellar aberration correction is */
/*      C     applied to the vector from the spacecraft to that point, */
/*      C     the resulting vector is parallel to BORVEC.  An easy */
/*      C     solution is to apply the inverse of the normal stellar */
/*      C     aberration correction to BORVEC, and then solve the */
/*      C     intercept problem with this corrected boresight vector. */
/*      C */
/*      C     Find the position of the observer relative */
/*      C     to the solar system barycenter at ET. */
/*      C */
/*            CALL BODN2C ( SC, SCID, FND ) */

/*            IF ( .NOT. FND ) THEN */

/*               CALL SETMSG ( 'ID code for body # was not found.' ) */
/*               CALL ERRCH  ( '#',  SC                            ) */
/*               CALL SIGERR ( 'SPICE(NOTRANSLATION'               ) */
/*               RETURN */

/*            END IF */

/*            CALL SPKSSB ( SCID, ET, 'J2000', SCSSB ) */

/*      C */
/*      C     We now wish to find the vector CORVEC that, when */
/*      C     corrected for stellar aberration, yields BORVEC. */
/*      C     A good first approximation is obtained by applying */
/*      C     the stellar aberration correction for transmission */
/*      C     to BORVEC. */
/*      C */
/*            CALL STLABX ( BORVEC, SCSSB(4), CORVEC ) */

/*      C */
/*      C     The inverse of the stellar aberration correction */
/*      C     applicable to CORVEC should be a very good estimate of */
/*      C     the correction we need to apply to BORVEC.  Apply */
/*      C     this correction to BORVEC to obtain an improved estimate */
/*      C     of CORVEC. */
/*      C */
/*            CALL STELAB ( CORVEC, SCSSB(4), BORV2  ) */
/*            CALL VSUB   ( BORV2,  CORVEC,   STCORR ) */
/*            CALL VSUB   ( BORVEC, STCORR,   CORVEC ) */

/*      C */
/*      C     Because the ring plane intercept may be quite far from */
/*      C     Saturn's center, we cannot assume light time from the */
/*      C     intercept to the observer is well approximated by */
/*      C     light time from Saturn's center to the observer. */
/*      C     We compute the light time explicitly using an iterative */
/*      C     approach. */
/*      C */
/*      C     We can however use the light time from Saturn's center to */
/*      C     the observer to obtain a first estimate of the actual light */
/*      C     time. */
/*      C */
/*            CALL SPKEZR ( 'SATURN', ET, 'J2000', 'LT', SC, */
/*           .               STATE,   LT                       ) */
/*            TAU = LT */

/*      C */
/*      C     Find the ring plane intercept and calculate the */
/*      C     light time from it to the spacecraft. */
/*      C     Perform three iterations. */
/*      C */
/*            I     = 1 */
/*            FOUND = .TRUE. */

/*            DO WHILE (  ( I .LE. 3 )  .AND.  ( FOUND )  ) */
/*      C */
/*      C        Find the position of Saturn relative */
/*      C        to the solar system barycenter at ET-TAU. */
/*      C */
/*               CALL SPKSSB ( SATURN, ET-TAU, 'J2000', SATSSB ) */

/*      C */
/*      C        Find the Saturn-to-observer vector defined by these */
/*      C        two position vectors. */
/*      C */
/*               CALL VSUB ( SCSSB, SATSSB, SCPOS ) */

/*      C */
/*      C        Look up Saturn's pole at ET-TAU; this is the third */
/*      C        column of the matrix that transforms Saturn body-fixed */
/*      C        coordinates to J2000 coordinates. */
/*      C */
/*               CALL PXFORM ( 'IAU_SATURN', 'J2000', ET-TAU, TPMI ) */

/*               CALL MOVED  ( TPMI(1,3), 3, ZVEC ) */

/*      C */
/*      C        Make a SPICELIB plane representing the ring plane. */
/*      C        We're treating Saturn's center as the origin, so */
/*      C        the plane constant is 0. */
/*      C */
/*               CALL NVC2PL ( ZVEC, 0.D0, PLANE ) */

/*      C */
/*      C        Find the intersection of the ring plane and the */
/*      C        ray having vertex SCPOS and direction vector */
/*      C        CORVEC. */
/*      C */
/*               CALL INRYPL ( SCPOS, CORVEC, PLANE, NXPTS, XPT ) */

/*      C */
/*      C        If the number of intersection points is 1, */
/*      C        find the next light time estimate. */
/*      C */
/*               IF ( NXPTS .EQ. 1 ) THEN */
/*      C */
/*      C           Find the light time (zero-order) from the */
/*      C           intercept point to the spacecraft. */
/*      C */
/*                  TAU  =  VDIST ( SCPOS, XPT )  /  CLIGHT() */
/*                  I    =  I + 1 */

/*               ELSE */

/*                  FOUND = .FALSE. */

/*               END IF */

/*            END DO */

/*      C */
/*      C     At this point, if FOUND is .TRUE., we iterated */
/*      C     3 times, and XPT is our estimate of the */
/*      C     position of the ring plane intercept point */
/*      C     relative to Saturn in the J2000 frame.  This is the */
/*      C     point observed by an instrument pointed in direction */
/*      C     BORVEC at ET at mounted on the spacecraft SC. */
/*      C */
/*      C     If FOUND is .FALSE., the boresight ray does not */
/*      C     intersect the ring plane. */
/*      C */
/*      C     As a final step, transform XPT to Saturn body-fixed */
/*      C     coordinates. */
/*      C */
/*            IF ( FOUND ) THEN */

/*               CALL MTXV ( TPMI, XPT, SBFXPT ) */

/*            END IF */

/*            END */



/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     N.J. Bachman   (JPL) */
/*     W.L. Taber     (JPL) */

/* $ Version */

/* -    SPICELIB Version 1.1.1, 07-FEB-2008 (BVS) */

/*        Fixed a few typos in the header. */

/* -    SPICELIB Version 1.1.0, 02-SEP-2005 (NJB) */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in VSCL call. */

/* -    SPICELIB Version 1.0.3, 12-DEC-2002 (NJB) */

/*        Header fix:  ring plane intercept algorithm was corrected. */
/*        Now light time is computed accurately, and stellar aberration */
/*        is accounted for.  Example was turned into a complete */
/*        subroutine. */

/* -    SPICELIB Version 1.0.2, 09-MAR-1999 (NJB) */

/*        Reference to SCE2T replaced by reference to SCE2C.  An */
/*        occurrence of ENDIF was replaced by END IF. */

/* -    SPICELIB Version 1.0.1, 10-MAR-1992 (WLT) */

/*        Comment section for permuted index source lines was added */
/*        following the header. */

/* -    SPICELIB Version 1.0.0, 01-APR-1991 (NJB) (WLT) */

/* -& */
/* $ Index_Entries */

/*     intersection of ray and plane */

/* -& */
/* $ Revisions */

/* -    SPICELIB Version 1.1.0, 02-SEP-2005 (NJB) */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in VSCL call. */

/* -& */

/*     SPICELIB functions */


/*     Local parameters */


/*     Local variables */


/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    } else {
	chkin_("INRYPL", (ftnlen)6);
    }

/*     We'll give the name TOOBIG to the bound DPMAX() / MARGIN. */
/*     If we let VTXPRJ be the orthogonal projection of VERTEX onto */
/*     PLANE, and let DIFF be the vector VTXPRJ - VERTEX, then */
/*     we know that */

/*        ||  DIFF  ||    <     2 * TOOBIG */

/*     Check the distance of the ray's vertex from the origin. */

    toobig = dpmax_() / 3.;
    if (vnorm_(vertex) >= toobig) {
	setmsg_("Ray's vertex is too far from the origin.", (ftnlen)40);
	sigerr_("SPICE(VECTORTOOBIG)", (ftnlen)19);
	chkout_("INRYPL", (ftnlen)6);
	return 0;
    }

/*     Check the distance of the plane from the origin.  (The returned */
/*     plane constant IS this distance.) */

    pl2nvc_(plane, normal, &const__);
    if (const__ >= toobig) {
	setmsg_("Plane is too far from the origin.", (ftnlen)33);
	sigerr_("SPICE(VECTORTOOBIG)", (ftnlen)19);
	chkout_("INRYPL", (ftnlen)6);
	return 0;
    }

/*     Check the ray's direction vector. */

    vhat_(dir, udir);
    if (vzero_(udir)) {
	setmsg_("Ray's direction vector is the zero vector.", (ftnlen)42);
	sigerr_("SPICE(ZEROVECTOR)", (ftnlen)17);
	chkout_("INRYPL", (ftnlen)6);
	return 0;
    }

/*     That takes care of the error cases.  Now scale the input vertex */
/*     and plane to improve numerical behavior. */

/* Computing MAX */
    d__1 = const__, d__2 = vnorm_(vertex);
    mscale = max(d__1,d__2);
    if (mscale != 0.) {
	d__1 = 1. / mscale;
	vscl_(&d__1, vertex, sclvtx);
	sclcon = const__ / mscale;
    } else {
	vequ_(vertex, sclvtx);
	sclcon = const__;
    }
    if (mscale > 1.) {
	toobig /= mscale;
    }
/*     Find the projection (coefficient) of the ray's vertex along the */
/*     plane's normal direction. */

    prjvn = vdot_(sclvtx, normal);

/*     If this projection is the plane constant, the ray's vertex lies in */
/*     the plane.  We have one intersection or an infinite number of */
/*     intersections.  It all depends on whether the ray actually lies */
/*     in the plane. */

/*     The absolute value of PRJDIF is the distance of the ray's vertex */
/*     from the plane. */

    prjdif = sclcon - prjvn;
    if (prjdif == 0.) {

/*        XPT is the original, unscaled vertex. */

	vequ_(vertex, xpt);
	if (vdot_(normal, udir) == 0.) {

/*           The ray's in the plane. */

	    *nxpts = -1;
	} else {
	    *nxpts = 1;
	}
	chkout_("INRYPL", (ftnlen)6);
	return 0;
    }

/*     Ok, the ray's vertex is not in the plane.  The ray may still be */
/*     parallel to or may point away from the plane.  If the ray does */
/*     point towards the plane, mathematicians would say that the */
/*     ray does intersect the plane, but the computer may disagree. */

/*     For this routine to find an intersection, both of the following */
/*     conditions must be met: */

/*        -- The ray must point toward the plane; this happens when */
/*           PRJDIF has the same sign as < UDIR, NORMAL >. */

/*        -- The vector difference XPT - SCLVTX must not overflow. */

/*      Qualitatively, the case of interest looks something like the */
/*      picture below: */


/*                      * SCLVTX */
/*                      |\ */
/*                      | \   <-- UDIR */
/*                      |  \ */
/*    length of this    |   \| */
/*      segment is      |   -* */
/*                      | */
/*     | PRJDIF |   --> | ___________________________ */
/*                      |/                          / */
/*                      |       *                  /   <-- PLANE */
/*                     /|        XPT              / */
/*                    / ^                        / */
/*                   /  | NORMAL                / */
/*                  /   | .                    / */
/*                 /    |/|                   / */
/*                / .---| /                  / */
/*               /  |   |/                  / */
/*              /   `---*                  / */
/*             /          Projection of SCLVTX onto the plane */
/*            /                          / */
/*           /                          / */
/*          ---------------------------- */




/*     Find the projection of the direction vector along the plane's */
/*     normal vector. */

    prjdir = vdot_(udir, normal);

/*     We're done if the ray doesn't point toward the plane.  PRJDIF */
/*     has already been found to be non-zero at this point; PRJDIR is */
/*     zero if the ray and plane are parallel.  The SPICELIB routine */
/*     SMSGND will return a value of .FALSE. if PRJDIR is zero. */

    if (! smsgnd_(&prjdir, &prjdif)) {

/*        The ray is parallel to or points away from the plane. */

	*nxpts = 0;
	cleard_(&c__3, xpt);
	chkout_("INRYPL", (ftnlen)6);
	return 0;
    }

/*     The difference XPT - SCLVTX is the hypotenuse of a right triangle */
/*     formed by SCLVTX, XPT, and the orthogonal projection of SCLVTX */
/*     onto the plane.  We'll obtain the hypotenuse by scaling UDIR. */
/*     We must make sure that this hypotenuse does not overflow.  The */
/*     scale factor has magnitude */

/*         | PRJDIF | */
/*       -------------- */
/*         | PRJDIR | */

/*     and UDIR is a unit vector, so as long as */

/*         | PRJDIF |   <   | PRJDIR |  *  TOOBIG */

/*     the hypotenuse is no longer than TOOBIG.  The product can be */
/*     computed safely since PRJDIR has magnitude 1 or less. */

    if (abs(prjdif) >= abs(prjdir) * toobig) {

/*        If the hypotenuse is too long, we say that no intersection */
/*        exists. */

	*nxpts = 0;
	cleard_(&c__3, xpt);
	chkout_("INRYPL", (ftnlen)6);
	return 0;
    }

/*     We conclude that it's safe to compute XPT.  Scale UDIR and add */
/*     the result to SCLVTX.  The addition is safe because both addends */
/*     have magnitude no larger than TOOBIG.  The vector thus obtained */
/*     is the intersection point. */

    *nxpts = 1;
    scale = abs(prjdif) / abs(prjdir);
    vlcom_(&c_b17, sclvtx, &scale, udir, xpt);

/*     Re-scale XPT.  This is safe, since TOOBIG has already been */
/*     scaled to allow for any growth of XPT at this step. */

    vsclip_(&mscale, xpt);
    chkout_("INRYPL", (ftnlen)6);
    return 0;
} /* inrypl_ */