Bioplib
Protein Structure C Library
 All Data Structures Files Functions Variables Typedefs Macros Pages
pldist.c
Go to the documentation of this file.
1 /************************************************************************/
2 /**
3 
4  \file pldist.c
5 
6  \version V1.1
7  \date 07.07.14
8  \brief Calculate distance from a point to a line
9 
10  \copyright (c) University of Reading / Dr. Andrew C. R. Martin 1999-2014
11  \author Dr. Andrew C. R. Martin
12  \par
13  Institute of Structural & Molecular Biology,
14  University College London,
15  Gower Street,
16  London.
17  WC1E 6BT.
18  \par
19  andrew@bioinf.org.uk
20  andrew.martin@ucl.ac.uk
21 
22 **************************************************************************
23 
24  This code is NOT IN THE PUBLIC DOMAIN, but it may be copied
25  according to the conditions laid out in the accompanying file
26  COPYING.DOC.
27 
28  The code may be modified as required, but any modifications must be
29  documented so that the person responsible can be identified.
30 
31  The code may not be sold commercially or included as part of a
32  commercial product except as described in the file COPYING.DOC.
33 
34 **************************************************************************
35 
36  Description:
37  ============
38 
39 
40 **************************************************************************
41 
42  Usage:
43  ======
44 
45 **************************************************************************
46 
47  Revision History:
48  =================
49 
50 - V1.1 07.07.14 Use bl prefix for functions By: CTP
51 
52 *************************************************************************/
53 /* Doxygen
54  -------
55  #GROUP Maths
56  #SUBGROUP Geometry
57  #FUNCTION blPointLineDistance()
58  Calculates the shortest distance from a point P to a line between
59  points P1 and P2. This value is returned and the point on the line
60  can also be returned. See also blDistPtLine()
61 
62 */
63 /************************************************************************/
64 /* Includes
65 */
66 #include <stdio.h>
67 #include <math.h>
68 #include "MathType.h"
69 
70 /************************************************************************/
71 /* Defines and macros
72 */
73 #define CROSSPRODUCT(p1,p2,p3) \
74  (p3).x = (p1).y*(p2).z - (p1).z*(p2).y; \
75  (p3).y = (p1).z*(p2).x - (p1).x*(p2).z; \
76  (p3).z = (p1).x*(p2).y - (p1).y*(p2).x
77 #define DOTPRODUCT(v1,v2) ((v1).x*(v2).x + (v1).y*(v2).y + (v1).z*(v2).z)
78 
79 /************************************************************************/
80 /* Globals
81 */
82 
83 /************************************************************************/
84 /* Prototypes
85 */
86 
87 /************************************************************************/
88 /*>REAL blPointLineDistance(REAL Px, REAL Py, REAL Pz,
89  REAL P1x, REAL P1y, REAL P1z,
90  REAL P2x, REAL P2y, REAL P2z,
91  REAL *Rx, REAL *Ry, REAL *Rz,
92  REAL *frac)
93  ------------------------------------------------------
94 *//**
95  \param[in] Px Point x coordinate
96  \param[in] Py Point y coordinate
97  \param[in] Pz Point z coordinate
98  \param[in] P1x Line start x coordinate
99  \param[in] P1y Line start y coordinate
100  \param[in] P1z Line start z coordinate
101  \param[in] P2x Line end x coordinate
102  \param[in] P2y Line end y coordinate
103  \param[in] P2z Line end z coordinate
104  \param[out] *Rx Nearest point on line x coordinate
105  \param[out] *Ry Nearest point on line y coordinate
106  \param[out] *Rz Nearest point on line z coordinate
107  \param[out] *frac Fraction along P1-P2 of R
108  \return Distance from P to R
109 
110  Calculates the shortest distance from a point P to a line between
111  points P1 and P2. This value is returned.
112 
113  If the Rx,Ry,Rz pointers are all non-NULL, then the point on the
114  line nearest to P is output.
115 
116  If the frac pointer is non-NULL then the fraction of R along the
117  P1-P2 vector is output. Thus:
118  R==P1 ==> frac=0
119  R==P2 ==> frac=1
120  Thus if (0<=frac<=1) then the point R is within the line segment
121  P1-P2
122 
123 - 16.11.99 Original By: ACRM
124 - 07.07.14 Use bl prefix for functions By: CTP
125 */
127  REAL P1x, REAL P1y, REAL P1z,
128  REAL P2x, REAL P2y, REAL P2z,
129  REAL *Rx, REAL *Ry, REAL *Rz,
130  REAL *frac)
131 {
132  VEC3F A, u, Q, PQ, PR, QP, QP2;
133  REAL alen, len, f;
134 
135 
136  /* Calculate vector from P1 to P2 */
137  A.x = P2x - P1x;
138  A.y = P2y - P1y;
139  A.z = P2z - P1z;
140 
141  /* Calculate length of this vector */
142  alen = sqrt(DOTPRODUCT(A,A));
143 
144  /* If the two ends of the line are coincident then return the distance
145  from either of them
146  */
147  if(alen==(REAL)0.0)
148  {
149  len = sqrt((Px-P1x)*(Px-P1x) +
150  (Py-P1y)*(Py-P1y) +
151  (Pz-P1z)*(Pz-P1z));
152  if(frac!=NULL)
153  *frac = 0.0;
154  if(Rx != NULL && Ry != NULL && Rz != NULL)
155  {
156  *Rx = P1x;
157  *Ry = P1y;
158  *Rz = P1z;
159  }
160 
161  return(len);
162  }
163 
164  /* Calculate the unit vector along A */
165  u.x = A.x / alen;
166  u.y = A.y / alen;
167  u.z = A.z / alen;
168 
169  /* Select Q as any point on A, we'll make it P1 */
170  Q.x = P1x;
171  Q.y = P1y;
172  Q.z = P1z;
173 
174  /* Calculate vector PQ */
175  PQ.x = Q.x - Px;
176  PQ.y = Q.y - Py;
177  PQ.z = Q.z - Pz;
178 
179  /* Vector PR is the cross product of PQ and the unit vector
180  along A (i.e. u)
181  */
182  CROSSPRODUCT(PQ, u, PR);
183 
184  /* And the length of that vector is the length we want */
185  len = sqrt(DOTPRODUCT(PR,PR));
186 
187 
188  if(frac != NULL || Rx != NULL || Ry != NULL || Rz != NULL)
189  {
190  /*** OK we now know how far the point is from the line, so we ***
191  *** now want to calculate where the closest point (R) on the ***
192  *** line is to point P ***/
193 
194  /* Find the projection of QP onto QP2 */
195  QP.x = Px - Q.x;
196  QP.y = Py - Q.y;
197  QP.z = Pz - Q.z;
198 
199  QP2.x = P2x - Q.x;
200  QP2.y = P2y - Q.y;
201  QP2.z = P2z - Q.z;
202 
203  f = DOTPRODUCT(QP, QP2) / sqrt(DOTPRODUCT(QP2, QP2));
204  if(frac != NULL)
205  {
206  *frac = f/alen;
207  }
208 
209  /* Find point R: this is the fraction f of the unit vector along
210  P1-P2 added onto Q
211  */
212  if(Rx != NULL && Ry != NULL && Rz != NULL)
213  {
214  *Rx = Q.x + f * u.x;
215  *Ry = Q.y + f * u.y;
216  *Rz = Q.z + f * u.z;
217  }
218  }
219 
220  return(len);
221 }
222 
223 
224 /************************************************************************/
225 #ifdef DEMO
226 int main(int argc, char **argv)
227 {
228  REAL Px, Py, Pz,
229  P1x, P1y, P1z,
230  P2x, P2y, P2z,
231  Rx, Ry, Rz, d, f;
232 
233  Px = 5; Py = 2; Pz = 0;
234  P1x = 5; P1y = 2; P1z = 0;
235  P2x = 10; P2y = 2; P2z = 0;
236 
237  d = blPointLineDistance(Px, Py, Pz,
238  P1x, P1y, P1z,
239  P2x, P2y, P2z,
240  &Rx, &Ry, &Rz, &f);
241 
242  printf("*** Distance is %f; Point R is %f %f %f; f is %f\n",
243  d,Rx,Ry,Rz,f);
244 
245  return(0);
246 }
247 #endif
int main(int argc, char **argv)
Definition: test.c:4
REAL x
Definition: MathType.h:70
#define NULL
Definition: array2.c:99
REAL blPointLineDistance(REAL Px, REAL Py, REAL Pz, REAL P1x, REAL P1y, REAL P1z, REAL P2x, REAL P2y, REAL P2z, REAL *Rx, REAL *Ry, REAL *Rz, REAL *frac)
Definition: pldist.c:126
Definition: MathType.h:69
double REAL
Definition: MathType.h:67
#define DOTPRODUCT(v1, v2)
Definition: pldist.c:77
#define CROSSPRODUCT(p1, p2, p3)
Definition: pldist.c:73
Type definitions for maths.
REAL z
Definition: MathType.h:70
REAL y
Definition: MathType.h:70