1 /*
2  * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
3  * Applied Mathematics, Norway.
4  *
5  * Contact information: E-mail: tor.dokken@sintef.no
6  * SINTEF ICT, Department of Applied Mathematics,
7  * P.O. Box 124 Blindern,
8  * 0314 Oslo, Norway.
9  *
10  * This file is part of SISL.
11  *
12  * SISL is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU Affero General Public License as
14  * published by the Free Software Foundation, either version 3 of the
15  * License, or (at your option) any later version.
16  *
17  * SISL is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Affero General Public License for more details.
21  *
22  * You should have received a copy of the GNU Affero General Public
23  * License along with SISL. If not, see
24  * <http://www.gnu.org/licenses/>.
25  *
26  * In accordance with Section 7(b) of the GNU Affero General Public
27  * License, a covered work must retain the producer line in every data
28  * file that is created or manipulated using SISL.
29  *
30  * Other Usage
31  * You can be released from the requirements of the license by purchasing
32  * a commercial license. Buying such a license is mandatory as soon as you
33  * develop commercial activities involving the SISL library without
34  * disclosing the source code of your own applications.
35  *
36  * This file may be used in accordance with the terms contained in a
37  * written agreement between you and SINTEF ICT.
38  */
39 
40 #include "sisl-copyright.h"
41 
42 /*
43  *
44  * $Id: s6dline.c,v 1.2 2001-03-19 15:59:01 afr Exp $
45  *
46  */
47 
48 
49 #define S6DLINE
50 
51 #include "sislP.h"
52 
53 #if defined(SISLNEEDPROTOTYPES)
54 double
s6dline(double estart[],double eend[],double epoint[],int idim,int * jstat)55   s6dline(double estart[],double eend[],double epoint[],
56 	  int idim,int *jstat)
57 #else
58 double s6dline(estart,eend,epoint,idim,jstat)
59    double estart[];
60    double eend[];
61    double epoint[];
62    int    idim;
63    int    *jstat;
64 #endif
65 /*
66 *********************************************************************
67 *
68 *********************************************************************
69 *
70 * PURPOSE    : Compute the distance between a line segment and a point.
71 *
72 *
73 *
74 * INPUT      : estart - Start point of line segment. Dimension is idim.
75 *              eend   - End point of line segment. Dimension is idim.
76 *              epoint - Point. Dimension is idim.
77 *              idim   - Dimension of geometry space.
78 *
79 *
80 *
81 * OUTPUT     : s6dline - Distance between line and point.
82 *              jstat   - status messages
83 *                        = 2      : Zero line segment. Closest point
84 *                                   is outside segment.
85 *                        = 1      : Closest point on the extended
86 *                                   line through estart and end is
87 *                                    outside the segment.
88 *                        = 0      : ok
89 *                        < 0      : error
90 *
91 *
92 * METHOD     :
93 *
94 *
95 *
96 * REFERENCES :
97 *
98 *-
99 * CALLS      : s6scpr   -  Scalar product between two vectors.
100 *              s6diff   -  Difference vector between two vectors.
101 *              s6length -  Length of vector.
102 *
103 * WRITTEN BY : Vibeke Skytt, SI, 91-02.
104 *
105 *********************************************************************
106 */
107 {
108    int kstat = 0;         /* Local status varaible.           */
109    int ki;                /* Counter.                         */
110    double tpar;           /* Parameter of closest point.      */
111    double tdist;          /* Distance between point and line. */
112    double t1;             /* Scalar product.                  */
113    double *sline = SISL_NULL;  /* Line vector.                     */
114    double *sdiff = SISL_NULL;  /* Difference vector.               */
115 
116    /* Allocate scratch for local vectors.  */
117 
118    if ((sline = newarray(idim,DOUBLE)) == SISL_NULL) goto err101;
119    if ((sdiff = newarray(idim,DOUBLE)) == SISL_NULL) goto err101;
120 
121    /* Compute help vectors.  */
122 
123    s6diff(eend,estart,idim,sline);
124    s6diff(epoint,estart,idim,sdiff);
125 
126    /* Compute parameter of closest point. */
127 
128    t1 = s6scpr(sline,sline,idim);
129    if (t1 <= REL_COMP_RES)
130    {
131       /* Compute distance between point and first endpoint of line. */
132 
133       tdist = s6dist(estart,epoint,idim);
134 
135       /* Set a warning.  */
136 
137       *jstat = 2;
138       goto out;
139    }
140 
141    tpar = s6scpr(sline,sdiff,idim)/t1;
142 
143    /* Compute vector between input point and closest point on
144       line.      */
145 
146    for (ki=0; ki<idim; ki++)
147       sdiff[ki] = estart[ki] + tpar*sline[ki] - epoint[ki];
148 
149    /* Compute length of vector.  */
150 
151    tdist = s6length(sdiff,idim,&kstat);
152 
153    /* Set status.  */
154 
155    *jstat = (tpar < 0 || tpar > 1) ? 1 : 0;
156    goto out;
157 
158    /* Error in scratch allocation.  */
159 
160    err101 : *jstat = -101;
161    goto out;
162 
163    out :
164       /* Free space occupied by local arrays.  */
165 
166       if (sline != SISL_NULL) freearray(sline);
167       if (sdiff != SISL_NULL) freearray(sdiff);
168 
169       return tdist;
170  }
171