/* npsgpt.f -- translated by f2c (version 19980913).
   You must link the resulting object file with the libraries:
	-lf2c -lm   (in that order)
*/

#include "f2c.h"

/* $Procedure      NPSGPT ( Nearest point on line segment ) */
/* Subroutine */ int npsgpt_(doublereal *ep1, doublereal *ep2, doublereal *
	point, doublereal *pnear, doublereal *dist)
{
    extern doublereal vdot_(doublereal *, doublereal *);
    extern /* Subroutine */ int vsub_(doublereal *, doublereal *, doublereal *
	    ), vequ_(doublereal *, doublereal *);
    doublereal lnear[3];
    extern doublereal vdist_(doublereal *, doublereal *);
    extern logical vzero_(doublereal *), failed_(void);
    doublereal offdot, segdot, offset[3];
    extern /* Subroutine */ int nplnpt_(doublereal *, doublereal *, 
	    doublereal *, doublereal *, doublereal *);
    extern logical return_(void);
    doublereal seg[3];

/* $ Abstract */

/*     Find the nearest point on a line segment to a given point. */

/* $ 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 */

/*     None. */

/* $ Keywords */

/*     GEOMETRY */
/*     MATH */

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

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     EP1, */
/*     EP2        I   Endpoints of a line segment. */
/*     POINT      I   A point in 3-dimensional space. */
/*     PNEAR      O   Nearest point on the line segment to POINT. */
/*     DIST       O   Distance between PNEAR and POINT. */

/* $ Detailed_Input */

/*     EP1, */
/*     EP2        are the endpoints of a line segment in 3-dimensional */
/*                space. EP1 and EP2 need not be distinct. */

/*     POINT      is an arbitrary point in 3-dimensional space. */

/* $ Detailed_Output */

/*     PNEAR      is the closest point on the line segment to POINT. */

/*     DIST       is the distance between POINT and PNEAR. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1) The input segment is allowed to be degenerate: it may be */
/*        a single point. */

/* $ Files */

/*     None. */

/* $ Particulars */

/*     None. */

/* $ Examples */

/*     The numerical results shown for these examples may differ across */
/*     platforms. The results depend on the SPICE kernels used as input */
/*     (if any), the compiler and supporting libraries, and the machine */
/*     specific arithmetic implementation. */

/*     1) Compute the nearest point on a line segment to a given */
/*        point in a simple case for which the results can easily be */
/*        checked. */


/*        Example code begins here. */


/*              PROGRAM EX1 */
/*              IMPLICIT NONE */
/*        C */
/*        C     Local parameters */
/*        C */
/*              CHARACTER*(*)         FMT1 */
/*              PARAMETER           ( FMT1 = '(A,3F13.8)' ) */
/*        C */
/*        C     Local variables */
/*        C */
/*              DOUBLE PRECISION      DIST */
/*              DOUBLE PRECISION      ENDPT1 ( 3 ) */
/*              DOUBLE PRECISION      ENDPT2 ( 3 ) */
/*              DOUBLE PRECISION      PNEAR  ( 3 ) */
/*              DOUBLE PRECISION      POINT  ( 3 ) */

/*        C */
/*        C     Initialize the line segment's endpoints. */
/*        C */
/*              CALL VPACK ( 1.D0, -2.D0, 3.D0, ENDPT1 ) */
/*              CALL VPACK ( 1.D0,  2.D0, 3.D0, ENDPT2 ) */
/*        C */
/*        C     Set the input point. */
/*        C */
/*              CALL VPACK ( 1.D0,  0.D0, 0.D0, POINT ) */
/*        C */
/*        C     Find the near point on the segment. */
/*        C */
/*              CALL NPSGPT ( ENDPT1, ENDPT2, POINT, PNEAR, DIST ) */

/*              WRITE (*,*) ' ' */
/*              WRITE (*,FMT1) 'Endpoint 1:  ', ENDPT1 */
/*              WRITE (*,FMT1) 'Endpoint 2:  ', ENDPT2 */
/*              WRITE (*,FMT1) 'Point:       ', POINT */
/*              WRITE (*,*) ' ' */
/*              WRITE (*,FMT1) 'Near point:  ', PNEAR */
/*              WRITE (*,FMT1) 'Distance:    ', DIST */
/*              WRITE (*,*) ' ' */

/*              END */


/*     When this program was executed on a PC/Linux/gfortran/64-bit */
/*     platform, the output was: */


/*        Endpoint 1:     1.00000000  -2.00000000   3.00000000 */
/*        Endpoint 2:     1.00000000   2.00000000   3.00000000 */
/*        Point:          1.00000000   0.00000000   0.00000000 */

/*        Near point:     1.00000000   0.00000000   3.00000000 */
/*        Distance:       3.00000000 */


/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

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

/* $ Version */

/* -    SPICELIB Version 1.0.0, 02-FEB-MAR-2016 (NJB) */

/*        Updated from DSKLIB Version 1.0.0, 20-MAR-2015 (NJB) */

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

/*     nearest point on line segment */

/* -& */

/*     SPICELIB functions */


/*     Local variables */


/*     Use discovery check-in. */

    if (return_()) {
	return 0;
    }

/*     Find a direction vector defined by the endpoints. */

    vsub_(ep2, ep1, seg);
    if (vzero_(seg)) {

/*        The endpoints coincide, and both coincide with the */
/*        near point. */

	vequ_(ep1, pnear);
	*dist = vdist_(ep1, point);
	return 0;
    }

/*     Find the nearest point to POINT on the line defined by */
/*     EP1 and SEG. */

    nplnpt_(ep1, seg, point, lnear, dist);
    if (failed_()) {
	return 0;
    }

/*     Determine whether LNEAR is on the segment, "before" EP1, or */
/*     "after" EP2, where SEG points in the "increasing" direction. */

    vsub_(lnear, ep1, offset);
    offdot = vdot_(offset, seg);
    if (offdot < 0.) {

/*        The nearest point on the line precedes the first endpoint. */
/*        The closest point on the segment is the first endpoint. */

	vequ_(ep1, pnear);
	*dist = vdist_(ep1, point);
    } else {

/*        See whether OFFSET is past the second endpoint. Compare */
/*        the dot product of OFFSET with SEG to that of SEG with */
/*        itself, since SEG is the offset of EP2 from EP1. */

	segdot = vdot_(seg, seg);
	if (offdot > segdot) {

/*           The nearest point on the line follows the last endpoint. */
/*           The closest point on the segment is the last endpoint. */

	    vequ_(ep2, pnear);
	    *dist = vdist_(ep2, point);
	} else {

/*           The near point is on the segment. LNEAR is actually the */
/*           solution. */

	    vequ_(lnear, pnear);

/*           DIST was correctly set by the call to NPLNPT. */

	}
    }
    return 0;
} /* npsgpt_ */

