vgl_distance.hxx
Go to the documentation of this file.
1 // This is core/vgl/vgl_distance.hxx
2 #ifndef vgl_distance_hxx_
3 #define vgl_distance_hxx_
4 //:
5 // \file
6 // \author fsm
7 
8 #include <cmath>
9 #include <utility>
10 #include "vgl_distance.h"
11 #include <vgl/vgl_point_2d.h>
12 #include <vgl/vgl_point_3d.h>
13 #include <vgl/vgl_homg_point_1d.h>
14 #include <vgl/vgl_homg_point_2d.h>
15 #include <vgl/vgl_homg_point_3d.h>
16 #include <vgl/vgl_line_2d.h>
19 #include <vgl/vgl_homg_line_2d.h>
21 #include <vgl/vgl_plane_3d.h>
22 #include <vgl/vgl_homg_plane_3d.h>
23 #include <vgl/vgl_sphere_3d.h>
24 #include <vgl/vgl_polygon.h>
25 #include <vgl/vgl_box_2d.h>
26 #include <vgl/vgl_closest_point.h>
27 #include <cassert>
28 #ifdef _MSC_VER
29 # include <vcl_msvc_warnings.h>
30 #endif
31 
32 template <class T>
33 static inline T square_of(T x) { return x*x; }
34 
35 template <class T>
36 double vgl_distance_to_linesegment(T x1, T y1,
37  T x2, T y2,
38  T x, T y)
39 {
40  return std::sqrt(vgl_distance2_to_linesegment(x1, y1, x2, y2, x, y));
41 }
42 
43 template <class T>
44 double vgl_distance2_to_linesegment(T x1, T y1,
45  T x2, T y2,
46  T x, T y)
47 {
48  // squared distance between endpoints :
49  T ddh = square_of(x2-x1) + square_of(y2-y1);
50 
51  // squared distance to endpoints :
52  T dd1 = square_of(x-x1) + square_of(y-y1);
53  T dd2 = square_of(x-x2) + square_of(y-y2);
54 
55  // if closest to the start point :
56  if (dd2 >= ddh + dd1)
57  return dd1;
58 
59  // if closest to the end point :
60  if (dd1 >= ddh + dd2)
61  return dd2;
62 
63  // squared perpendicular distance to line :
64  T a = y1-y2;
65  T b = x2-x1;
66  T c = x1*y2-x2*y1;
67  return square_of(a*x + b*y + c)/double(a*a + b*b);
68 }
69 
70 template <class T>
71 double vgl_distance_to_linesegment(T x1, T y1, T z1,
72  T x2, T y2, T z2,
73  T x, T y, T z)
74 {
75  return std::sqrt(vgl_distance2_to_linesegment(x1, y1, z1, x2, y2, z2, x, y, z));
76 }
77 
78 template <class T>
79 double vgl_distance2_to_linesegment(T x1, T y1, T z1,
80  T x2, T y2, T z2,
81  T x, T y, T z)
82 {
83  // squared distance between endpoints :
84  T ddh = square_of(x2-x1) + square_of(y2-y1) + square_of(z2-z1);
85 
86  // squared distance to endpoints :
87  T dd1 = square_of(x-x1) + square_of(y-y1) + square_of(z-z1);
88  T dd2 = square_of(x-x2) + square_of(y-y2) + square_of(z-z2);
89 
90  // if closest to the start point :
91  if (dd2 >= ddh + dd1)
92  return dd1;
93 
94  // if closest to the end point :
95  if (dd1 >= ddh + dd2)
96  return dd2;
97 
98  // squared perpendicular distance to line :
99  // plane through (x,y,z) and orthogonal to the line is a(X-x)+b(Y-y)+c(Z-z)=0
100  // where (a,b,c) is the direction of the line.
101  T a = x2-x1, b = y2-y1, c = z2-z1;
102  // The closest point is then the intersection of this plane with the line.
103  // This point equals (x1,y1,z1) + lambda * (a,b,c), with this lambda:
104  double lambda = (a*(x-x1)+b*(y-y1)+c*(z-z1))/double(a*a+b*b+c*c);
105  // return squared distance:
106  return square_of(x-x1-lambda*a) + square_of(y-y1-lambda*b) + square_of(z-z1-lambda*c);
107 }
108 
109 template <class T>
110 double vgl_distance_to_non_closed_polygon(T const px[], T const py[], unsigned n,
111  T x, T y)
112 {
113  double dd = -1;
114  for (unsigned i=0; i+1<n; ++i) {
115  double nd = vgl_distance_to_linesegment(px[i ], py[i ],
116  px[i+1], py[i+1],
117  x, y);
118  if (dd<0 || nd<dd)
119  dd = nd;
120  }
121  return dd;
122 }
123 
124 template <class T>
125 double vgl_distance_to_closed_polygon(T const px[], T const py[], unsigned n,
126  T x, T y)
127 {
128  double dd = vgl_distance_to_linesegment(px[n-1], py[n-1],
129  px[0 ], py[0 ],
130  x, y);
131  for (unsigned i=0; i+1<n; ++i) {
132  double nd = vgl_distance_to_linesegment(px[i ], py[i ],
133  px[i+1], py[i+1],
134  x, y);
135  if (nd<dd)
136  dd = nd;
137  }
138 
139  return dd;
140 }
141 
142 template <class T>
143 double vgl_distance_to_non_closed_polygon(T const px[], T const py[], T const pz[], unsigned int n,
144  T x, T y, T z)
145 {
146  double dd = -1;
147  for (unsigned i=0; i+1<n; ++i) {
148  double nd = vgl_distance_to_linesegment(px[i ], py[i ], pz[i ],
149  px[i+1], py[i+1], pz[i+1],
150  x, y, z);
151  if (dd<0 || nd<dd)
152  dd = nd;
153  }
154  return dd;
155 }
156 
157 template <class T>
158 double vgl_distance_to_closed_polygon(T const px[], T const py[], T const pz[], unsigned int n,
159  T x, T y, T z)
160 {
161  double dd = vgl_distance_to_linesegment(px[n-1], py[n-1], pz[n-1],
162  px[0 ], py[0 ], pz[0 ],
163  x, y, z);
164  for (unsigned i=0; i+1<n; ++i) {
165  double nd = vgl_distance_to_linesegment(px[i ], py[i ], pz[i ],
166  px[i+1], py[i+1], pz[i+1],
167  x, y, z);
168  if (nd<dd)
169  dd = nd;
170  }
171 
172  return dd;
173 }
174 
175 template <class T>
177 {
178  if (l.c() == 0) return 0.0; // no call to sqrt if not necessary
179  else return std::abs(static_cast<double>(l.c())) / std::sqrt(static_cast<double>( l.a()*l.a()+l.b()*l.b() ));
180 }
181 
182 template <class T>
184 {
185  if (l.c() == 0) return 0.0; // no call to sqrt if not necessary
186  else return std::abs(static_cast<double>(l.c())) / std::sqrt(static_cast<double>( l.a()*l.a()+l.b()*l.b() ));
187 }
188 
189 template <class T>
191 {
192  if (pl.d() == 0) return 0.0; // no call to sqrt if not necessary
193  else return std::abs(static_cast<double>(pl.d())) / std::sqrt(static_cast<double>( pl.a()*pl.a()+pl.b()*pl.b()+pl.c()*pl.c()) );
194 }
195 
196 template <class T>
198 {
199  if (pl.d() == 0) return 0.0; // no call to sqrt if not necessary
200  else return std::abs(static_cast<double>(pl.d())) / std::sqrt(static_cast<double>( pl.a()*pl.a()+pl.b()*pl.b()+pl.c()*pl.c()) );
201 }
202 
203 template <class T>
205 {
207  return std::sqrt(static_cast<double>(square_of(q.x())+square_of(q.y())+square_of(q.z())))/q.w();
208 }
209 
210 template <class T>
212 {
214  return std::sqrt(static_cast<double>(square_of(q.x())+square_of(q.y())+square_of(q.z())));
215 }
216 
217 template <class T>
219  vgl_homg_point_1d<T>const& p2)
220 {
221  return std::abs(static_cast<double>(p1.x()/p1.w() - p2.x()/p2.w()));
222 }
223 
224 template <class T>
226 {
227  T num = l.a()*p.x() + l.b()*p.y() + l.c();
228  if (num == 0) return 0.0; // no call to sqrt if not necessary
229  else return std::abs(static_cast<double>(num)) / std::sqrt(static_cast<double>(l.a()*l.a() + l.b()*l.b()));
230 }
231 
232 template <class T>
234 {
235  T num = l.a()*p.x() + l.b()*p.y() + l.c()*p.w();
236  if (num == 0) return 0.0; // always return 0 when point on line, even at infinity
237  else return std::abs(static_cast<double>(num)) / std::sqrt(static_cast<double>(l.a()*l.a() + l.b()*l.b())) / p.w(); // could be inf
238 }
239 
240 template <class T>
242 {
243  T num = l.nx()*p.x() + l.ny()*p.y() + l.nz()*p.z() + l.d();
244  if (num == 0) return 0.0; // no call to sqrt if not necessary
245  else return std::abs(static_cast<double>(num)) / std::sqrt(static_cast<double>(l.nx()*l.nx() + l.ny()*l.ny() + l.nz()*l.nz()));
246 }
247 
248 template <class T>
250 {
251  T num = l.nx()*p.x() + l.ny()*p.y() + l.nz()*p.z() + l.d()*p.w();
252  if (num == 0) return 0.0; // always return 0 when point on plane, even at infinity
253  else return std::abs(static_cast<double>(num/p.w())) / std::sqrt(static_cast<double>(l.nx()*l.nx() + l.ny()*l.ny() + l.nz()*l.nz()));
254 }
255 template <class T>
257  vgl_sphere_3d<T> const& s){
258  double r = static_cast<double>(s.radius());
259  vgl_point_3d<T> c = s.centre();
260  double d = vgl_distance<T>(p,c);
261  return std::fabs(d-r);
262 }
263 
264 template <class T>
265 double vgl_distance(vgl_polygon<T> const& poly, vgl_point_2d<T> const& point, bool closed)
266 {
267  double dist = -1;
268  for ( unsigned int s=0; s < poly.num_sheets(); ++s )
269  {
270  const std::vector<vgl_point_2d<T> > &sheet = poly[s];
271  unsigned int n = (unsigned int)(sheet.size());
272  assert( n > 1 );
273  double dd = closed ?
274  vgl_distance_to_linesegment(sheet[n-1].x(), sheet[n-1].y(),
275  sheet[0 ].x(), sheet[0 ].y(),
276  point.x(), point.y()) :
277  vgl_distance_to_linesegment(sheet[0 ].x(), sheet[0 ].y(),
278  sheet[1 ].x(), sheet[1 ].y(),
279  point.x(), point.y());
280  for ( unsigned int i=0; i+1 < n; ++i )
281  {
282  double nd = vgl_distance_to_linesegment(sheet[i ].x(), sheet[i ].y(),
283  sheet[i+1].x(), sheet[i+1].y(),
284  point.x(), point.y());
285  if ( nd<dd ) dd=nd;
286  }
287  if ( dist < 0 || dd < dist ) dist = dd;
288  }
289 
290  return dist;
291 }
292 
293 template <class T>
295  vgl_homg_line_3d_2_points<T> const& line2)
296 {
297  std::pair<vgl_homg_point_3d<T>, vgl_homg_point_3d<T> > pp =
298  vgl_closest_points(line1, line2);
299  if (pp.first.w() != 0)
300  return vgl_distance(pp.first,pp.second);
301  else // the two lines are parallel
302  return vgl_distance(line1.point_finite(), line2);
303 }
304 
305 
306 template <class T>
308  vgl_homg_point_3d<T> const& p)
309 {
311  return vgl_distance(p,q);
312 }
313 
314 template <class T>
316  vgl_point_3d<T> const& p)
317 {
319  return vgl_distance(p,q);
320 }
321 
322 template <class T>
324  vgl_point_2d<T> const& p)
325 {
326  return vgl_distance_to_linesegment(l.point1().x(), l.point1().y(),
327  l.point2().x(), l.point2().y(),
328  p.x(), p.y());
329 }
330 
331 template <class T>
333  vgl_point_3d<T> const& p)
334 {
335  return vgl_distance_to_linesegment(l.point1().x(), l.point1().y(), l.point1().z(),
336  l.point2().x(), l.point2().y(), l.point2().z(),
337  p.x(), p.y(), p.z());
338 }
339 
340 //: return the closest distance from a point to a ray
341 template <class T>
342 double vgl_distance(vgl_ray_3d<T> const& r, vgl_point_3d<T> const& p)
343 {
345  return vgl_distance(p,q);
346 }
347 //: return the closest distance from a point to an infinite line
348 template <class T>
350  vgl_point_3d<T> const& p){
352  return vgl_distance(p,q);
353 }
354 
355 template <class T>
356 double vgl_distance(vgl_point_2d<T> const& p, vgl_box_2d<T> const& b){
357  //create line segments for the box boundary
358  vgl_point_2d<T> p0 = b.min_point();
359  vgl_point_2d<T> p2 = b.max_point();
360  vgl_point_2d<T> p1(p2.x(), p0.y());
361  vgl_point_2d<T> p3(p0.x(), p2.y());
362  // find distance to each line segment and return minimum
363  vgl_line_segment_2d<T> l0(p0, p1), l1(p1, p2), l2(p2,p3), l3(p3,p0);
364  T min_d = std::numeric_limits<T>::max();
365  double d = vgl_distance(p,l0);
366  if(d < min_d) min_d = d;
367  d = vgl_distance(p,l1);
368  if(d < min_d) min_d = d;
369  d = vgl_distance(p,l2);
370  if(d < min_d) min_d = d;
371  d = vgl_distance(p,l3);
372  if(d < min_d) min_d = d;
373  return min_d;
374 }
375 
376 #undef VGL_DISTANCE_INSTANTIATE
377 #define VGL_DISTANCE_INSTANTIATE(T) \
378 template double vgl_distance2_to_linesegment(T,T,T,T,T,T); \
379 template double vgl_distance_to_linesegment(T,T,T,T,T,T); \
380 template double vgl_distance2_to_linesegment(T,T,T,T,T,T,T,T,T); \
381 template double vgl_distance_to_linesegment(T,T,T,T,T,T,T,T,T); \
382 template double vgl_distance_to_non_closed_polygon(T const[],T const[],unsigned int,T,T); \
383 template double vgl_distance_to_non_closed_polygon(T const[],T const[],T const[],unsigned int,T,T,T); \
384 template double vgl_distance_to_closed_polygon(T const[],T const[],unsigned int,T,T); \
385 template double vgl_distance_to_closed_polygon(T const[],T const[],T const[],unsigned int,T,T,T); \
386 template double vgl_distance_origin(vgl_line_2d<T >const& l); \
387 template double vgl_distance_origin(vgl_homg_line_2d<T >const& l); \
388 template double vgl_distance_origin(vgl_plane_3d<T > const& pl); \
389 template double vgl_distance_origin(vgl_homg_plane_3d<T > const& pl); \
390 template double vgl_distance_origin(vgl_line_3d_2_points<T > const& l); \
391 template double vgl_distance_origin(vgl_homg_line_3d_2_points<T > const& l); \
392 template double vgl_distance(vgl_homg_point_1d<T >const&,vgl_homg_point_1d<T >const&); \
393 template double vgl_distance(vgl_point_2d<T >const&,vgl_point_2d<T >const&); \
394 template double vgl_distance(vgl_homg_point_2d<T >const&,vgl_homg_point_2d<T >const&); \
395 template double vgl_distance(vgl_point_3d<T >const&,vgl_point_3d<T >const&); \
396 template double vgl_distance(vgl_homg_point_3d<T >const&,vgl_homg_point_3d<T >const&); \
397 template double vgl_distance(vgl_line_2d<T >const&,vgl_point_2d<T >const&); \
398 template double vgl_distance(vgl_point_2d<T >const&,vgl_line_2d<T >const&); \
399 template double vgl_distance(vgl_homg_line_2d<T >const&,vgl_homg_point_2d<T >const&); \
400 template double vgl_distance(vgl_homg_point_2d<T >const&,vgl_homg_line_2d<T >const&); \
401 template double vgl_distance(vgl_plane_3d<T >const&,vgl_point_3d<T >const&); \
402 template double vgl_distance(vgl_point_3d<T >const&,vgl_plane_3d<T >const&); \
403 template double vgl_distance(vgl_homg_plane_3d<T >const&,vgl_homg_point_3d<T >const&); \
404 template double vgl_distance(vgl_homg_point_3d<T >const&,vgl_homg_plane_3d<T >const&); \
405 template double vgl_distance(vgl_point_3d<T> const&, vgl_sphere_3d<T> const&); \
406 template double vgl_distance(vgl_polygon<T >const&,vgl_point_2d<T >const&,bool); \
407 template double vgl_distance(vgl_homg_line_3d_2_points<T >const&,vgl_homg_line_3d_2_points<T >const&); \
408 template double vgl_distance(vgl_homg_line_3d_2_points<T >const&,vgl_homg_point_3d<T >const&); \
409 template double vgl_distance(vgl_line_3d_2_points<T >const&,vgl_point_3d<T >const&); \
410 template double vgl_distance(vgl_ray_3d<T > const& r, vgl_point_3d<T > const& p); \
411 template double vgl_distance(vgl_infinite_line_3d<T > const& l, vgl_point_3d<T > const& p); \
412 template double vgl_distance(vgl_homg_point_3d<T > const&,vgl_homg_line_3d_2_points<T > const&); \
413 template double vgl_distance(vgl_line_segment_2d<T > const&, vgl_point_2d<T > const&); \
414 template double vgl_distance(vgl_line_segment_3d<T > const&, vgl_point_3d<T > const&); \
415 template double vgl_distance(vgl_point_2d<T> const& p, vgl_box_2d<T> const& b)
416 #endif // vgl_distance_hxx_
homogeneous plane in 3D projective space
point in projective 3D space
a point in 2D nonhomogeneous space
Represents a homogeneous 2D line.
Definition: vgl_fwd.h:14
T a() const
Return x coefficient.
Definition: vgl_plane_3d.h:89
vgl_point_2d< Type > max_point() const
Return upper right corner of box.
Definition: vgl_box_2d.hxx:147
a point in homogeneous 1-D space, i.e., a homogeneous pair (x,w)
Type b() const
Return y coefficient.
Type c() const
Return z coefficient.
Type d() const
Return homogeneous scaling coefficient.
line in projective 2D space
Represents a homogeneous 3D point.
Definition: vgl_fwd.h:9
Type & z()
Definition: vgl_point_3d.h:73
Type radius() const
Definition: vgl_sphere_3d.h:46
A class to hold a non-homogeneous representation of a 3D line.
Definition: vgl_fwd.h:17
Set of closest-point functions.
vgl_point_2d< T > vgl_closest_point_origin(vgl_line_2d< T > const &l)
Return the point on the given line closest to the origin.
T b() const
Return y coefficient.
Definition: vgl_plane_3d.h:92
a point in 3D nonhomogeneous space
line segment in 3D nonhomogeneous space
vgl_point_2d< T > vgl_closest_point(vgl_line_2d< T > const &l, vgl_point_2d< T > const &p)
Return the point on the given line closest to the given point.
double vgl_distance_origin(vgl_line_2d< T > const &l)
find the shortest distance of the line to the origin.
Type & y()
Definition: vgl_point_2d.h:72
Represents a Euclidean 3D plane.
Definition: vgl_fwd.h:23
Represents a 3D line segment using two points.
Definition: vgl_fwd.h:19
Represents a 3-d ray.
Definition: vgl_fwd.h:21
a sphere in 3D nonhomogeneous space
double vgl_distance_to_non_closed_polygon(T const px[], T const py[], unsigned n, T x, T y)
point in projective 2D space
T d() const
Return constant coefficient.
Definition: vgl_plane_3d.h:98
Contains class to represent a cartesian 2D bounding box.
Type a() const
Return x coefficient.
Type & x()
Definition: vgl_point_3d.h:71
Represents a 3-d line with position defined in the orthogonal plane passing through the origin.
Definition: vgl_fwd.h:20
const vgl_point_3d< Type > & centre() const
Definition: vgl_sphere_3d.h:45
double vgl_distance2_to_linesegment(T x1, T y1, T x2, T y2, T x, T y)
Squared distance between point (x,y) and closest point on line segment (x1,y1)-(x2,...
double vgl_distance(vgl_point_2d< T >const &p1, vgl_point_2d< T >const &p2)
return the distance between two points.
Definition: vgl_distance.h:104
#define l
double vgl_distance_to_closed_polygon(T const px[], T const py[], unsigned n, T x, T y)
vgl_point_2d< Type > min_point() const
Return lower left corner of box.
Definition: vgl_box_2d.hxx:140
a plane in 3D nonhomogeneous space
Represents a homogeneous 1-D point, i.e., a homogeneous pair (x,w).
Definition: vgl_fwd.h:7
Set of distance functions.
Represents a homogeneous 2D point.
Definition: vgl_fwd.h:8
unsigned int num_sheets() const
Definition: vgl_polygon.h:116
Store a polygon.
Definition: vgl_area.h:6
vgl_homg_point_3d< Type > point_finite() const
Finite point (Could be an ideal point, if the whole line is at infinity.).
double vgl_distance_to_linesegment(T x1, T y1, T x2, T y2, T x, T y)
Distance between point (x,y) and closest point on line segment (x1,y1)-(x2,y2).
T c() const
Return z coefficient.
Definition: vgl_plane_3d.h:95
Type & y()
Definition: vgl_point_3d.h:72
Type & x()
Definition: vgl_point_2d.h:71
std::pair< vgl_homg_point_3d< T >, vgl_homg_point_3d< T > > vgl_closest_points(vgl_homg_line_3d_2_points< T > const &line1, vgl_homg_line_3d_2_points< T > const &line2)
Return the two points of nearest approach of two 3D lines, one on each line.
Represents a homogeneous 3D line using two points.
Definition: vgl_fwd.h:15