00001
00002 #ifndef vgl_closest_point_txx_
00003 #define vgl_closest_point_txx_
00004
00005
00006
00007
00008 #include "vgl_closest_point.h"
00009 #include <vgl/vgl_distance.h>
00010 #include <vgl/vgl_line_2d.h>
00011 #include <vgl/vgl_homg_line_2d.h>
00012 #include <vgl/vgl_point_2d.h>
00013 #include <vgl/vgl_point_3d.h>
00014 #include <vgl/vgl_homg_point_2d.h>
00015 #include <vgl/vgl_homg_point_3d.h>
00016 #include <vgl/vgl_plane_3d.h>
00017 #include <vgl/vgl_homg_plane_3d.h>
00018 #include <vgl/vgl_homg_line_3d_2_points.h>
00019 #include <vgl/vgl_line_3d_2_points.h>
00020 #include <vgl/vgl_line_segment_2d.h>
00021 #include <vgl/vgl_line_segment_3d.h>
00022 #include <vgl/vgl_polygon.h>
00023 #include <vgl/vgl_ray_3d.h>
00024 #include <vcl_cassert.h>
00025 #include <vcl_cmath.h>
00026
00027 template <class T>
00028 static inline T square(T x) { return x*x; }
00029
00030
00031
00032 const double SMALL_DOUBLE = 1e-12;
00033
00034
00035
00036
00037
00038
00039
00040 #ifdef VCL_BORLAND_55
00041 # define DIST_SQR_TO_LINE_SEG_2D( T, x1, y1, x2, y2, x, y ) \
00042 vgl_distance2_to_linesegment(T(x1), T(y1), T(x2), T(y2), T(x), T(y) );
00043 # define DIST_SQR_TO_LINE_SEG_3D( T, x1, y1, z1, x2, y2, z2, x, y, z ) \
00044 vgl_distance2_to_linesegment(T(x1), T(y1), T(z1), T(x2), T(y2), T(z2), T(x), T(y), T(z) );
00045 #else
00046 # define DIST_SQR_TO_LINE_SEG_2D( T, x1, y1, x2, y2, x, y ) \
00047 vgl_distance2_to_linesegment(x1, y1, x2, y2, x, y );
00048 # define DIST_SQR_TO_LINE_SEG_3D( T, x1, y1, z1, x2, y2, z2, x, y, z ) \
00049 vgl_distance2_to_linesegment(x1, y1, z1, x2, y2, z2, x, y, z );
00050 #endif
00051
00052
00053 template <class T>
00054 void vgl_closest_point_to_linesegment(T& ret_x, T& ret_y,
00055 T x1, T y1,
00056 T x2, T y2,
00057 T x0, T y0)
00058 {
00059
00060 T ddh = square(x2-x1) + square(y2-y1);
00061
00062
00063 T dd1 = square(x0-x1) + square(y0-y1);
00064 T dd2 = square(x0-x2) + square(y0-y2);
00065
00066
00067 if (dd2 > ddh + dd1) { ret_x=x1; ret_y=y1; return; }
00068
00069
00070 if (dd1 > ddh + dd2) { ret_x=x2; ret_y=y2; return; }
00071
00072
00073
00074
00075 T dx = x2-x1;
00076 T dy = y2-y1;
00077 double c = dx*dx+dy*dy;
00078 ret_x = T((dx*dx*x0+dy*dy*x1-dx*dy*(y1-y0))/c);
00079 ret_y = T((dx*dx*y1+dy*dy*y0-dx*dy*(x1-x0))/c);
00080 }
00081
00082 template <class T>
00083 void vgl_closest_point_to_linesegment(T& ret_x, T& ret_y, T& ret_z,
00084 T x1, T y1, T z1,
00085 T x2, T y2, T z2,
00086 T x, T y, T z)
00087 {
00088
00089 T ddh = square(x2-x1) + square(y2-y1) + square(z2-z1);
00090
00091
00092 T dd1 = square(x-x1) + square(y-y1) + square(z-z1);
00093 T dd2 = square(x-x2) + square(y-y2) + square(z-z2);
00094
00095
00096 if (dd2 > ddh + dd1) { ret_x=x1; ret_y=y1; ret_z=z1; return; }
00097
00098
00099 if (dd1 > ddh + dd2) { ret_x=x2; ret_y=y2; ret_z=z2; return; }
00100
00101
00102
00103 T a = x2-x1, b = y2-y1, c = z2-z1;
00104
00105
00106 double lambda = (a*(x-x1)+b*(y-y1)+c*(z-z1))/double(a*a+b*b+c*c);
00107 ret_x = x1+T(lambda*a); ret_y = y1+T(lambda*b); ret_z = z1+T(lambda*c);
00108 }
00109
00110 template <class T>
00111 int vgl_closest_point_to_non_closed_polygon(T& ret_x, T& ret_y,
00112 T const px[], T const py[], unsigned int n,
00113 T x, T y)
00114 {
00115 assert(n>1);
00116 double dd = DIST_SQR_TO_LINE_SEG_2D(T,px[0],py[0], px[1],py[1], x,y);
00117 int di = 0;
00118 for (unsigned i=1; i+1<n; ++i)
00119 {
00120 double nd = DIST_SQR_TO_LINE_SEG_2D(T,px[i],py[i], px[i+1],py[i+1], x,y);
00121 if (nd<dd) { dd=nd; di=i; }
00122 }
00123 vgl_closest_point_to_linesegment(ret_x,ret_y, px[di],py[di], px[di+1],py[di+1], x,y);
00124 return di;
00125 }
00126
00127 template <class T>
00128 int vgl_closest_point_to_non_closed_polygon(T& ret_x, T& ret_y, T& ret_z,
00129 T const px[], T const py[], T const pz[], unsigned int n,
00130 T x, T y, T z)
00131 {
00132 assert(n>1);
00133 double dd = DIST_SQR_TO_LINE_SEG_3D(T,px[0],py[0],pz[0], px[1],py[1],pz[1], x,y,z);
00134 int di = 0;
00135 for (unsigned i=1; i+1<n; ++i)
00136 {
00137 double nd = DIST_SQR_TO_LINE_SEG_3D(T,px[i],py[i],pz[i], px[i+1],py[i+1],pz[i+1], x,y,z);
00138 if (nd<dd) { dd=nd; di=i; }
00139 }
00140 vgl_closest_point_to_linesegment(ret_x,ret_y,ret_z, px[di],py[di],pz[di],
00141 px[di+1],py[di+1],pz[di+1], x,y,z);
00142 return di;
00143 }
00144
00145 template <class T>
00146 int vgl_closest_point_to_closed_polygon(T& ret_x, T& ret_y,
00147 T const px[], T const py[], unsigned int n,
00148 T x, T y)
00149 {
00150 assert(n>1);
00151 double dd = DIST_SQR_TO_LINE_SEG_2D(T,px[0],py[0], px[n-1],py[n-1], x,y);
00152 int di = -1;
00153 for (unsigned i=0; i+1<n; ++i)
00154 {
00155 double nd = DIST_SQR_TO_LINE_SEG_2D(T,px[i],py[i], px[i+1],py[i+1], x,y);
00156 if (nd<dd) { dd=nd; di=i; }
00157 }
00158 if (di == -1) di+=n,
00159 vgl_closest_point_to_linesegment(ret_x,ret_y, px[0],py[0], px[n-1],py[n-1], x,y);
00160 else
00161 vgl_closest_point_to_linesegment(ret_x,ret_y, px[di],py[di], px[di+1],py[di+1], x,y);
00162 return di;
00163 }
00164
00165 template <class T>
00166 int vgl_closest_point_to_closed_polygon(T& ret_x, T& ret_y, T& ret_z,
00167 T const px[], T const py[], T const pz[], unsigned int n,
00168 T x, T y, T z)
00169 {
00170 assert(n>1);
00171 double dd = DIST_SQR_TO_LINE_SEG_3D(T,px[0],py[0],pz[0], px[n-1],py[n-1],pz[n-1], x,y,z);
00172 int di = -1;
00173 for (unsigned i=0; i+1<n; ++i)
00174 {
00175 double nd = DIST_SQR_TO_LINE_SEG_3D(T,px[i],py[i],pz[i], px[i+1],py[i+1],pz[i+1], x,y,z);
00176 if (nd<dd) { dd=nd; di=i; }
00177 }
00178 if (di == -1) di+=n,
00179 vgl_closest_point_to_linesegment(ret_x,ret_y,ret_z, px[0],py[0],pz[0],
00180 px[n-1],py[n-1],pz[n-1], x,y,z);
00181 else
00182 vgl_closest_point_to_linesegment(ret_x,ret_y,ret_z, px[di],py[di],pz[di],
00183 px[di+1],py[di+1],pz[di+1], x,y,z);
00184 return di;
00185 }
00186
00187 template <class T>
00188 vgl_point_2d<T> vgl_closest_point_origin(vgl_line_2d<T> const& l)
00189 {
00190 T d = l.a()*l.a()+l.b()*l.b();
00191 return vgl_point_2d<T>(-l.a()*l.c()/d, -l.b()*l.c()/d);
00192 }
00193
00194 template <class T>
00195 vgl_homg_point_2d<T> vgl_closest_point_origin(vgl_homg_line_2d<T> const& l)
00196 {
00197 return vgl_homg_point_2d<T>(l.a()*l.c(), l.b()*l.c(),
00198 -l.a()*l.a()-l.b()*l.b());
00199 }
00200
00201 template <class T>
00202 vgl_point_3d<T> vgl_closest_point_origin(vgl_plane_3d<T> const& pl)
00203 {
00204 T d = pl.a()*pl.a()+pl.b()*pl.b()+pl.c()*pl.c();
00205 return vgl_point_3d<T>(-pl.a()*pl.d()/d, -pl.b()*pl.d()/d, -pl.c()*pl.d()/d);
00206 }
00207
00208 template <class T>
00209 vgl_homg_point_3d<T> vgl_closest_point_origin(vgl_homg_plane_3d<T> const& pl)
00210 {
00211 return vgl_homg_point_3d<T>(pl.a()*pl.d(), pl.b()*pl.d(), pl.c()*pl.d(),
00212 -pl.a()*pl.a()-pl.b()*pl.b()-pl.c()*pl.c());
00213 }
00214
00215 template <class T>
00216 vgl_homg_point_3d<T> vgl_closest_point_origin(vgl_homg_line_3d_2_points<T> const& l)
00217 {
00218 vgl_homg_point_3d<T> const& q = l.point_finite();
00219
00220
00221 T a = l.point_infinite().x(), b = l.point_infinite().y(), c = l.point_infinite().z(),
00222 d = a*a+b*b+c*c;
00223
00224
00225 T lambda = a*q.x()+b*q.y()+c*q.z();
00226 return vgl_homg_point_3d<T>(d*q.x()-lambda*a*q.w(), d*q.y()-lambda*b*q.w(), d*q.z()-lambda*c*q.w(), d*q.w());
00227 }
00228
00229 template <class T>
00230 vgl_point_3d<T> vgl_closest_point_origin(vgl_line_3d_2_points<T> const& l)
00231 {
00232 vgl_point_3d<T> const& q = l.point1();
00233
00234
00235 T a = l.point2().x()-q.x(), b = l.point2().y()-q.y(), c = l.point2().z()-q.z(),
00236 d = a*a+b*b+c*c;
00237
00238
00239 T lambda = (a*q.x()+b*q.y()+c*q.z())/d;
00240 return vgl_point_3d<T>(q.x()-lambda*a, q.y()-lambda*b, q.z()-lambda*c);
00241 }
00242
00243 template <class T>
00244 vgl_point_2d<T> vgl_closest_point(vgl_line_2d<T> const& l,
00245 vgl_point_2d<T> const& p)
00246 {
00247 T d = l.a()*l.a()+l.b()*l.b();
00248 assert(d!=0);
00249 return vgl_point_2d<T>((l.b()*l.b()*p.x()-l.a()*l.b()*p.y()-l.a()*l.c())/d,
00250 (l.a()*l.a()*p.y()-l.a()*l.b()*p.x()-l.b()*l.c())/d);
00251 }
00252
00253 template <class T>
00254 vgl_homg_point_2d<T> vgl_closest_point(vgl_homg_line_2d<T> const& l,
00255 vgl_homg_point_2d<T> const& p)
00256 {
00257 T d = l.a()*l.a()+l.b()*l.b();
00258 assert(d!=0);
00259 return vgl_homg_point_2d<T>(l.b()*l.b()*p.x()-l.a()*l.b()*p.y()-l.a()*l.c(),
00260 l.a()*l.a()*p.y()-l.a()*l.b()*p.x()-l.b()*l.c(),
00261 d);
00262 }
00263
00264 template <class T>
00265 vgl_point_3d<T> vgl_closest_point(vgl_plane_3d<T> const& l,
00266 vgl_point_3d<T> const& p)
00267 {
00268
00269
00270
00271 T d = l.a()*l.a()+l.b()*l.b()+l.c()*l.c();
00272 return vgl_point_3d<T>(((l.b()*l.b()+l.c()*l.c())*p.x()-l.a()*l.b()*p.y()-l.a()*l.c()*p.z()-l.a()*l.d())/d,
00273 ((l.a()*l.a()+l.c()*l.c())*p.y()-l.a()*l.b()*p.x()-l.b()*l.c()*p.z()-l.b()*l.d())/d,
00274 ((l.a()*l.a()+l.b()*l.b())*p.z()-l.a()*l.c()*p.x()-l.b()*l.c()*p.y()-l.c()*l.d())/d);
00275 }
00276
00277 template <class T>
00278 vgl_homg_point_3d<T> vgl_closest_point(vgl_homg_plane_3d<T> const& l,
00279 vgl_homg_point_3d<T> const& p)
00280 {
00281 return vgl_homg_point_3d<T>((l.b()*l.b()+l.c()*l.c())*p.x()-l.a()*l.b()*p.y()-l.a()*l.c()*p.z()-l.a()*l.d(),
00282 (l.a()*l.a()+l.c()*l.c())*p.y()-l.a()*l.b()*p.x()-l.b()*l.c()*p.z()-l.b()*l.d(),
00283 (l.a()*l.a()+l.b()*l.b())*p.z()-l.a()*l.c()*p.x()-l.b()*l.c()*p.y()-l.c()*l.d(),
00284 l.a()*l.a()+l.b()*l.b()+l.c()*l.c());
00285 }
00286
00287 template <class T>
00288 vgl_point_2d<T> vgl_closest_point(vgl_polygon<T> const& poly,
00289 vgl_point_2d<T> const& point,
00290 bool closed)
00291 {
00292 T x=point.x(), y=point.y();
00293 double dd = DIST_SQR_TO_LINE_SEG_2D(T,poly[0][0].x(),poly[0][0].y(), poly[0][1].x(),poly[0][1].y(), x,y);
00294 int si = 0, di = 0;
00295 for ( unsigned int s=0; s < poly.num_sheets(); ++s )
00296 {
00297 unsigned int n = (unsigned int)(poly[s].size());
00298 assert( n > 1 );
00299 for (unsigned i=0; i+1<n; ++i)
00300 {
00301 double nd = DIST_SQR_TO_LINE_SEG_2D(T,poly[s][i].x(),poly[s][i].y(), poly[s][i+1].x(),poly[s][i+1].y(), x,y);
00302 if (nd<dd) { dd=nd; di=i; si=s; }
00303 }
00304 if (closed)
00305 {
00306 double nd = DIST_SQR_TO_LINE_SEG_2D(T,poly[s][0].x(),poly[s][0].y(), poly[s][n-1].x(),poly[s][n-1].y(), x,y);
00307 if (nd<dd) { dd=nd; di=-1; si=s; }
00308 }
00309 }
00310 T ret_x, ret_y;
00311 unsigned int n = (unsigned int)(poly[si].size());
00312 if (di == -1)
00313 vgl_closest_point_to_linesegment(ret_x,ret_y, poly[si][0].x(),poly[si][0].y(), poly[si][n-1].x(),poly[si][n-1].y(), x,y);
00314 else
00315 vgl_closest_point_to_linesegment(ret_x,ret_y, poly[si][di].x(),poly[si][di].y(), poly[si][di+1].x(),poly[si][di+1].y(), x,y);
00316 return vgl_point_2d<T>(T(ret_x), T(ret_y));
00317 }
00318
00319 template <class T>
00320 vcl_pair<vgl_homg_point_3d<T>, vgl_homg_point_3d<T> >
00321 vgl_closest_points(vgl_homg_line_3d_2_points<T> const& line1,
00322 vgl_homg_line_3d_2_points<T> const& line2)
00323 {
00324 vcl_pair<vgl_homg_point_3d<T>, vgl_homg_point_3d<T> > ret;
00325
00326 if ((line1==line2)||(line1.point_infinite()==line2.point_infinite()))
00327 {
00328 ret.first = ret.second = line1.point_infinite();
00329 }
00330
00331 else if (concurrent(line1, line2))
00332 {
00333 ret.first = ret.second = intersection(line1, line2);
00334 }
00335
00336
00337 else
00338 {
00339
00340 vgl_homg_point_3d<T> p21 = line1.point_infinite();
00341 vgl_homg_point_3d<T> p43 = line2.point_infinite();
00342 vgl_vector_3d<T> p13 = line1.point_finite()-line2.point_finite();
00343
00344 T d1343 = p13.x() * p43.x() + p13.y() * p43.y() + p13.z() * p43.z();
00345 T d4321 = p43.x() * p21.x() + p43.y() * p21.y() + p43.z() * p21.z();
00346 T d1321 = p13.x() * p21.x() + p13.y() * p21.y() + p13.z() * p21.z();
00347 T d4343 = p43.x() * p43.x() + p43.y() * p43.y() + p43.z() * p43.z();
00348 T d2121 = p21.x() * p21.x() + p21.y() * p21.y() + p21.z() * p21.z();
00349
00350 T denom = d2121 * d4343 - d4321 * d4321;
00351 T numer = d1343 * d4321 - d1321 * d4343;
00352
00353
00354
00355
00356 T mu_n = d1343 * denom + d4321 * numer;
00357 T mu_d = d4343 * denom;
00358
00359 ret.first.set(denom*line1.point_finite().x()+numer*p21.x(),
00360 denom*line1.point_finite().y()+numer*p21.y(),
00361 denom*line1.point_finite().z()+numer*p21.z(),
00362 denom);
00363 ret.second.set(mu_d*line2.point_finite().x()+mu_n*p43.x(),
00364 mu_d*line2.point_finite().y()+mu_n*p43.y(),
00365 mu_d*line2.point_finite().z()+mu_n*p43.z(),
00366 mu_d);
00367 }
00368 return ret;
00369 }
00370
00371 template <class T>
00372 vgl_homg_point_3d<T> vgl_closest_point(vgl_homg_line_3d_2_points<T> const& l,
00373 vgl_homg_point_3d<T> const& p)
00374 {
00375
00376 if (p.w() == 0) return l.point_infinite();
00377 vgl_homg_point_3d<T> const& q = l.point_finite();
00378 vgl_vector_3d<T> v = p-q;
00379
00380
00381 T a = l.point_infinite().x(), b = l.point_infinite().y(), c = l.point_infinite().z(),
00382 d = a*a+b*b+c*c;
00383
00384
00385 T lambda = a*v.x()+b*v.y()+c*v.z();
00386 return vgl_homg_point_3d<T>(d*q.x()+lambda*a*q.w(), d*q.y()+lambda*b*q.w(), d*q.z()+lambda*c*q.w(), d*q.w());
00387 }
00388
00389 template <class T>
00390 double vgl_closest_point_t(vgl_line_3d_2_points<T> const& l,
00391 vgl_point_3d<T> const& p)
00392 {
00393 vgl_point_3d<T> const& q = l.point1();
00394 vgl_vector_3d<T> v = p-q;
00395
00396
00397 double a = l.point2().x()-q.x(), b = l.point2().y()-q.y(),
00398 c = l.point2().z()-q.z(), d = a*a+b*b+c*c;
00399
00400
00401 double lambda = (a*v.x()+b*v.y()+c*v.z())/d;
00402 return lambda;
00403 }
00404
00405
00406 template <class T>
00407 vgl_point_3d<T> vgl_closest_point(vgl_line_3d_2_points<T> const& l,
00408 vgl_point_3d<T> const& p)
00409 {
00410 vgl_point_3d<T> const& q = l.point1();
00411 vgl_vector_3d<T> v = p-q;
00412
00413
00414 T a = l.point2().x()-q.x(), b = l.point2().y()-q.y(), c = l.point2().z()-q.z(),
00415 d = a*a+b*b+c*c;
00416
00417
00418 T lambda = (a*v.x()+b*v.y()+c*v.z())/d;
00419 return vgl_point_3d<T>(q.x()+lambda*a, q.y()+lambda*b, q.z()+lambda*c);
00420 }
00421
00422
00423 template <class T>
00424 vcl_pair<vgl_point_3d<T>, vgl_point_3d<T> >
00425 vgl_closest_points(const vgl_line_3d_2_points<T>& l1,
00426 const vgl_line_3d_2_points<T>& l2,
00427 bool* unique)
00428 {
00429 vcl_pair<vgl_point_3d<T>, vgl_point_3d<T> > ret;
00430
00431
00432
00433
00434 vgl_vector_3d<T> u = l1.direction();
00435 vgl_vector_3d<T> v = l2.direction();
00436
00437
00438 vgl_vector_3d<T> w = l1.point1() - l2.point1();
00439
00440 double a = dot_product(u,u);
00441 double b = dot_product(u,v);
00442 double c = dot_product(v,v);
00443 double d = dot_product(u,w);
00444 double e = dot_product(v,w);
00445
00446
00447 double denom = a*c - b*b;
00448 if (denom<0.0) denom = 0.0;
00449 if (denom>SMALL_DOUBLE)
00450 {
00451 double s = (b*e - c*d) / denom;
00452 double t = (a*e - b*d) / denom;
00453
00454 ret.first = l1.point_t(s);
00455 ret.second = l2.point_t(t);
00456 if (unique) *unique = true;
00457 }
00458 else
00459 {
00460
00461
00462 double s = 0.0;
00463 double t = (b>c ? d/b : e/c);
00464 ret.first = l1.point_t(s);
00465 ret.second = l2.point_t(t);
00466 if (unique) *unique = false;
00467 }
00468
00469 return ret;
00470 }
00471
00472 template <class T>
00473 vgl_point_3d<T> vgl_closest_point(vgl_point_3d<T> const& p,
00474 vgl_ray_3d<T> const& r)
00475 {
00476 vgl_line_3d_2_points<T> l2(r.origin(), r.origin()+r.direction());
00477 return vgl_closest_point(p,l2);
00478 }
00479
00480
00481 template <class T>
00482 vcl_pair<vgl_point_3d<T>, vgl_point_3d<T> >
00483 vgl_closest_points(vgl_line_segment_3d<T> const& l1,
00484 vgl_line_segment_3d<T> const& l2,
00485 bool* unique)
00486 {
00487 vcl_pair<vgl_point_3d<T>, vgl_point_3d<T> > ret;
00488
00489
00490
00491
00492 vgl_vector_3d<T> u = l1.direction();
00493 vgl_vector_3d<T> v = l2.direction();
00494
00495
00496 vgl_vector_3d<T> w = l1.point1() - l2.point1();
00497
00498 double a = dot_product(u,u); assert(a>0.0);
00499 double b = dot_product(u,v);
00500 double c = dot_product(v,v); assert(c>0.0);
00501 double d = dot_product(u,w);
00502 double e = dot_product(v,w);
00503
00504
00505 double denom = a*c - b*b;
00506 assert(denom>=0.0);
00507
00508
00509
00510
00511
00512
00513
00514 double s_numer;
00515 double s_denom = denom;
00516 double t_numer;
00517 double t_denom = denom;
00518
00519 if (denom < SMALL_DOUBLE)
00520 {
00521
00522 s_numer = 0.0;
00523 s_denom = 1.0;
00524 t_numer = e;
00525 t_denom = c;
00526 if (unique) *unique = false;
00527 }
00528 else
00529 {
00530
00531 s_numer = (b*e - c*d);
00532 t_numer = (a*e - b*d);
00533 if (s_numer < 0.0)
00534 {
00535
00536 s_numer = 0.0;
00537 t_numer = e;
00538 t_denom = c;
00539 }
00540 else if (s_numer > s_denom)
00541 {
00542
00543 s_numer = s_denom;
00544 t_numer = e + b;
00545 t_denom = c;
00546 }
00547 if (unique) *unique = true;
00548 }
00549
00550 if (t_numer < 0.0)
00551 {
00552
00553 t_numer = 0.0;
00554
00555
00556 if (-d < 0.0)
00557 s_numer = 0.0;
00558 else if (-d > a)
00559 s_numer = s_denom;
00560 else
00561 {
00562 s_numer = -d;
00563 s_denom = a;
00564 }
00565 }
00566 else if (t_numer > t_denom)
00567 {
00568
00569 t_numer = t_denom;
00570
00571
00572 if ((-d + b) < 0.0)
00573 s_numer = 0.0;
00574 else if ((-d + b) > a)
00575 s_numer = s_denom;
00576 else
00577 {
00578 s_numer = (-d + b);
00579 s_denom = a;
00580 }
00581 }
00582
00583
00584 double s = (vcl_abs(s_numer) < SMALL_DOUBLE ? 0.0 : s_numer / s_denom);
00585 double t = (vcl_abs(t_numer) < SMALL_DOUBLE ? 0.0 : t_numer / t_denom);
00586
00587
00588
00589 if (unique && ! *unique)
00590 {
00591 if ((s==0.0 || s==1.0) && (t==0.0 || t==1.0))
00592 *unique = true;
00593 }
00594
00595 ret.first = l1.point_t(s);
00596 ret.second = l2.point_t(t);
00597
00598 return ret;
00599 }
00600
00601 template <class T>
00602 vgl_point_2d<T> vgl_closest_point(vgl_line_segment_2d<T> const& l,
00603 vgl_point_2d<T> const& p)
00604 {
00605 vgl_point_2d<T> q;
00606 vgl_closest_point_to_linesegment(q.x(), q.y(),
00607 l.point1().x(), l.point1().y(),
00608 l.point2().x(), l.point2().y(),
00609 p.x(), p.y());
00610 return q;
00611 }
00612
00613 template <class T>
00614 vgl_point_3d<T> vgl_closest_point(vgl_line_segment_3d<T> const& l,
00615 vgl_point_3d<T> const& p)
00616 {
00617 vgl_point_3d<T> q;
00618 vgl_closest_point_to_linesegment(q.x(), q.y(), q.z(),
00619 l.point1().x(), l.point1().y(), l.point1().z(),
00620 l.point2().x(), l.point2().y(), l.point2().z(),
00621 p.x(), p.y(), p.z());
00622 return q;
00623 }
00624
00625 #undef DIST_SQR_TO_LINE_SEG_2D
00626 #undef DIST_SQR_TO_LINE_SEG_3D
00627
00628 #undef VGL_CLOSEST_POINT_INSTANTIATE
00629 #define VGL_CLOSEST_POINT_INSTANTIATE(T) \
00630 template void vgl_closest_point_to_linesegment(T&,T&,T,T,T,T,T,T); \
00631 template void vgl_closest_point_to_linesegment(T&,T&,T&,T,T,T,T,T,T,T,T,T); \
00632 template int vgl_closest_point_to_non_closed_polygon(T&,T&,T const[],T const[],unsigned int,T,T); \
00633 template int vgl_closest_point_to_non_closed_polygon(T&,T&,T&,T const[],T const[],T const[],unsigned int,T,T,T); \
00634 template int vgl_closest_point_to_closed_polygon(T&,T&,T const[],T const[],unsigned int,T,T); \
00635 template int vgl_closest_point_to_closed_polygon(T&,T&,T&,T const[],T const[],T const[],unsigned int,T,T,T); \
00636 template vgl_point_2d<T > vgl_closest_point_origin(vgl_line_2d<T >const& l); \
00637 template vgl_point_3d<T > vgl_closest_point_origin(vgl_plane_3d<T > const& pl); \
00638 template vgl_point_3d<T > vgl_closest_point_origin(vgl_line_3d_2_points<T > const& l); \
00639 template vgl_homg_point_2d<T > vgl_closest_point_origin(vgl_homg_line_2d<T >const& l); \
00640 template vgl_homg_point_3d<T > vgl_closest_point_origin(vgl_homg_plane_3d<T > const& pl); \
00641 template vgl_homg_point_3d<T > vgl_closest_point_origin(vgl_homg_line_3d_2_points<T > const& l); \
00642 template vgl_point_2d<T > vgl_closest_point(vgl_line_2d<T >const&,vgl_point_2d<T >const&); \
00643 template vgl_point_2d<T > vgl_closest_point(vgl_point_2d<T >const&,vgl_line_2d<T >const&); \
00644 template double vgl_closest_point_t(vgl_line_3d_2_points<T >const&,vgl_point_3d<T >const&); \
00645 template vgl_point_3d<T > vgl_closest_point(vgl_line_3d_2_points<T >const&,vgl_point_3d<T >const&); \
00646 template vgl_point_3d<T > vgl_closest_point(vgl_point_3d<T > const& p,vgl_ray_3d<T > const& r); \
00647 template vgl_homg_point_2d<T > vgl_closest_point(vgl_homg_line_2d<T >const&,vgl_homg_point_2d<T >const&); \
00648 template vgl_homg_point_2d<T > vgl_closest_point(vgl_homg_point_2d<T >const&,vgl_homg_line_2d<T >const&); \
00649 template vgl_point_3d<T > vgl_closest_point(vgl_plane_3d<T >const&,vgl_point_3d<T >const&); \
00650 template vgl_point_3d<T > vgl_closest_point(vgl_point_3d<T >const&,vgl_plane_3d<T >const&); \
00651 template vgl_homg_point_3d<T > vgl_closest_point(vgl_homg_plane_3d<T >const&,vgl_homg_point_3d<T >const&); \
00652 template vgl_homg_point_3d<T > vgl_closest_point(vgl_homg_point_3d<T >const&,vgl_homg_plane_3d<T >const&); \
00653 template vgl_point_2d<T > vgl_closest_point(vgl_polygon<T >const&,vgl_point_2d<T >const&,bool); \
00654 template vcl_pair<vgl_homg_point_3d<T >,vgl_homg_point_3d<T > > \
00655 vgl_closest_points(vgl_homg_line_3d_2_points<T >const&,vgl_homg_line_3d_2_points<T >const&); \
00656 template vgl_homg_point_3d<T > vgl_closest_point(vgl_homg_line_3d_2_points<T >const&,vgl_homg_point_3d<T >const&); \
00657 template vgl_homg_point_3d<T > vgl_closest_point(vgl_homg_point_3d<T >const&,vgl_homg_line_3d_2_points<T >const&); \
00658 template vcl_pair<vgl_point_3d<T >,vgl_point_3d<T > > \
00659 vgl_closest_points(vgl_line_3d_2_points<T >const&, vgl_line_3d_2_points<T >const&, bool*); \
00660 template vcl_pair<vgl_point_3d<T >,vgl_point_3d<T > > \
00661 vgl_closest_points(vgl_line_segment_3d<T >const&, vgl_line_segment_3d<T >const&, bool*); \
00662 template vgl_point_2d<T > vgl_closest_point(vgl_line_segment_2d<T > const&, vgl_point_2d<T > const&); \
00663 template vgl_point_3d<T > vgl_closest_point(vgl_line_segment_3d<T > const&, vgl_point_3d<T > const&)
00664
00665 #endif // vgl_closest_point_txx_