forked from guglie/Birds
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pointLineSegmentDistance.h
137 lines (101 loc) · 3.62 KB
/
pointLineSegmentDistance.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
* pointLineSegmentDistance.h
*
*
* Created by Guglielmo Cassinelli on 13/09/10.
* Copyright 2010 __MyCompanyName__. All rights reserved.
*
*/
//returns true if the nearest point to C is A or B, false if the nearest point is between A and B
bool DistanceFromLine(float cx, float cy, float ax, float ay , float bx, float by, float &distanceSegment)
{
//
// find the distance from the point (cx,cy) to the line
// determined by the points (ax,ay) and (bx,by)
//
// distanceSegment = distance from the point to the line segment
// distanceLine = distance from the point to the line (assuming
// infinite extent in both directions
//
/*
Subject 1.02: How do I find the distance from a point to a line?
Let the point be C (Cx,Cy) and the line be AB (Ax,Ay) to (Bx,By).
Let P be the point of perpendicular projection of C on AB. The parameter
r, which indicates P's position along AB, is computed by the dot product
of AC and AB divided by the square of the length of AB:
(1) AC dot AB
r = ---------
||AB||^2
r has the following meaning:
r=0 P = A
r=1 P = B
r<0 P is on the backward extension of AB
r>1 P is on the forward extension of AB
0<r<1 P is interior to AB
The length of a line segment in d dimensions, AB is computed by:
L = sqrt( (Bx-Ax)^2 + (By-Ay)^2 + ... + (Bd-Ad)^2)
so in 2D:
L = sqrt( (Bx-Ax)^2 + (By-Ay)^2 )
and the dot product of two vectors in d dimensions, U dot V is computed:
D = (Ux * Vx) + (Uy * Vy) + ... + (Ud * Vd)
so in 2D:
D = (Ux * Vx) + (Uy * Vy)
So (1) expands to:
(Cx-Ax)(Bx-Ax) + (Cy-Ay)(By-Ay)
r = -------------------------------
L^2
The point P can then be found:
Px = Ax + r(Bx-Ax)
Py = Ay + r(By-Ay)
And the distance from A to P = r*L.
Use another parameter s to indicate the location along PC, with the
following meaning:
s<0 C is left of AB
s>0 C is right of AB
s=0 C is on AB
Compute s as follows:
(Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
s = -----------------------------
L^2
Then the distance from C to P = |s|*L.
*/
bool ret;
float r_numerator = (cx-ax)*(bx-ax) + (cy-ay)*(by-ay);
float r_denomenator = (bx-ax)*(bx-ax) + (by-ay)*(by-ay);
float r = r_numerator / r_denomenator;
//
float px = ax + r*(bx-ax);
float py = ay + r*(by-ay);
//
float s = ((ay-cy)*(bx-ax)-(ax-cx)*(by-ay) ) / r_denomenator;
float distanceLine = fabs(s)*sqrt(r_denomenator);
//
// (xx,yy) is the point on the lineSegment closest to (cx,cy)
//
float xx = px;
float yy = py;
if ( (r >= 0) && (r <= 1) )
{
distanceSegment = distanceLine;
ret = false;
}
else
{
float dist1 = (cx-ax)*(cx-ax) + (cy-ay)*(cy-ay);
float dist2 = (cx-bx)*(cx-bx) + (cy-by)*(cy-by);
if (dist1 < dist2)
{
xx = ax;
yy = ay;
distanceSegment = sqrt(dist1);
}
else
{
xx = bx;
yy = by;
distanceSegment = sqrt(dist2);
}
ret = true;
}
return ret;
}