00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef __VCG_DISTANCE3
00026 #define __VCG_DISTANCE3
00027
00028 #include <limits>
00029 #include <vcg/space/intersection3.h>
00030
00031 namespace vcg {
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 template<class Scalar>
00042 Scalar PointFilledBoxDistance(const Point3<Scalar> &p, const Box3<Scalar> &bbox)
00043 {
00044 Scalar dist2 = 0.;
00045 Scalar aux;
00046 for (int k=0 ; k<3 ; ++k)
00047 {
00048 if ( (aux = (p[k]-bbox.min[k]))<0. )
00049 dist2 += aux*aux;
00050 else if ( (aux = (bbox.max[k]-p[k]))<0. )
00051 dist2 += aux*aux;
00052 }
00053 return sqrt(dist2);
00054 }
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 template <class ScalarType>
00066 void PointBoxDistance(const Point3<ScalarType> &p,
00067 const Box3<ScalarType> &b,
00068 ScalarType& dist)
00069 {
00071 if (b.IsIn(p))
00072 {
00073 const ScalarType dx = std::min<ScalarType>(b.max.X()-p.X(), p.X()-b.min.X());
00074 const ScalarType dy = std::min<ScalarType>(b.max.Y()-p.Y(), p.Y()-b.min.Y());
00075 const ScalarType dz = std::min<ScalarType>(b.max.Z()-p.Z(), p.Z()-b.min.Z());
00076
00077 dist= std::min<ScalarType>(dx, std::min<ScalarType>(dy, dz));
00078 return;
00079 }
00080
00081 {
00082 ScalarType sq_dist = ScalarType(0);
00083 for (int i=0; i<3; ++i)
00084 {
00085 ScalarType delta = ScalarType(0);
00086 if (p[i] < b.min[i]) delta = p[i] - b.min[i];
00087 else if (p[i] > b.max[i]) delta = p[i] - b.max[i];
00088 sq_dist += delta * delta;
00089 }
00090
00091 dist= math::Sqrt(sq_dist);
00092 }
00093 }
00094
00095
00096
00097
00098
00099
00100
00101 template <class ScalarType>
00102 void SpherePointDistance(const Sphere3<ScalarType> &sphere,
00103 const Point3<ScalarType> &p,
00104 ScalarType& dist)
00105 {
00106 dist = Distance(p, sphere.Center()) - sphere.Radius();
00107 if(dist < 0) dist = 0;
00108 }
00109
00110
00111
00112
00113
00114
00115
00116 template <class ScalarType>
00117 void SphereSphereDistance(const Sphere3<ScalarType> &sphere0,
00118 const Sphere3<ScalarType> &sphere1,
00119 ScalarType& dist)
00120 {
00121 dist = (sphere1.Center()-sphere0.Center()).Norm()
00122 - sphere0.Radius() - sphere1.Radius();
00123 if(dist < 0) dist = 0;
00124 return dist;
00125 }
00126
00127
00128
00129
00130
00131
00132
00133
00134 template <class ScalarType>
00135 void PlanePointSquaredDistance(const vcg::Plane3<ScalarType> &Pl,
00136 const Point3<ScalarType> &p,
00137 Point3<ScalarType> &closest,
00138 ScalarType &dist)
00139 {
00140 closest=Pl.Projection(p);
00141 dist= (closest - p).SquaredNorm();
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 template <class ScalarType>
00153 ScalarType PlanePointSquaredDistance(const vcg::Plane3<ScalarType> &Pl,
00154 const Point3<ScalarType> &p)
00155 {
00156 ScalarType dist;
00157 vcg::Point3<ScalarType> closest;
00158 PlanePointSquaredDistance(Pl,p,closest,dist);
00159 return (dist);
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 template <class ScalarType>
00171 void LinePointSquaredDistance(const Line3<ScalarType> &l,const Point3<ScalarType> &p,
00172 Point3<ScalarType> &closest,ScalarType &dist)
00173 {
00174 closest=l.P(l.Projection(p));
00175 dist= (closest - p).SquaredNorm();
00176 }
00177
00178
00179
00180
00181
00182
00183
00184
00185 template <class ScalarType>
00186 void LinePointDistance(const Line3<ScalarType> &l,const Point3<ScalarType> &p,
00187 Point3<ScalarType> &closest,ScalarType &dist)
00188 {
00189 LinePointSquaredDistance(l,p,closest,dist);
00190 dist=sqrt(dist);
00191 }
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 template <class ScalarType>
00202 void LineLineDistance(const vcg::Line3<ScalarType> &mLine0,
00203 const vcg::Line3<ScalarType> &mLine1,
00204 bool ¶llel,
00205 ScalarType &dist,
00206 vcg::Point3<ScalarType> &mClosestPoint0,
00207 vcg::Point3<ScalarType> &mClosestPoint1)
00208 {
00209 const ScalarType loc_EPSILON=ScalarType(0.000000001);
00210 typedef typename vcg::Point3<ScalarType> CoordType;
00211 CoordType diff = mLine0.Origin() - mLine1.Origin();
00212 ScalarType a01 = -mLine0.Direction()* mLine1.Direction();
00213 ScalarType b0 = diff *(mLine0.Direction());
00214 ScalarType c = diff.SquaredNorm();
00215 ScalarType det = fabs((ScalarType)1 - a01*a01);
00216 ScalarType b1, s0, s1, sqrDist;
00217
00218 if (det >=loc_EPSILON)
00219 {
00220
00221 b1 = -diff*(mLine1.Direction());
00222 ScalarType invDet = ((ScalarType)1)/det;
00223 s0 = (a01*b1 - b0)*invDet;
00224 s1 = (a01*b0 - b1)*invDet;
00225 sqrDist = s0*(s0 + a01*s1 + ((ScalarType)2)*b0) +
00226 s1*(a01*s0 + s1 + ((ScalarType)2)*b1) + c;
00227 parallel=false;
00228 }
00229 else
00230 {
00231
00232 s0 = -b0;
00233 s1 = (ScalarType)0;
00234 sqrDist = b0*s0 + c;
00235 parallel=true;
00236 }
00238 mClosestPoint0 = mLine0.Origin() + mLine0.Direction()*s0;
00239 mClosestPoint1 = mLine1.Origin() + mLine1.Direction()*s1;
00240
00241
00242
00243
00244 if (sqrDist < (ScalarType)0)
00245 {
00246 sqrDist = (ScalarType)0;
00247 }
00248 dist=sqrt(sqrDist);
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 template <class ScalarType>
00260 void SegmentPointSquaredDistance( const Segment3<ScalarType> &s,
00261 const Point3<ScalarType> & p,
00262 Point3< ScalarType > &closest,
00263 ScalarType &sqr_dist)
00264 {
00265 Point3<ScalarType> e = s.P1()-s.P0();
00266 ScalarType eSquaredNorm = e.SquaredNorm();
00267 if (eSquaredNorm < std::numeric_limits<ScalarType>::min())
00268 {
00269 closest=s.MidPoint();
00270 sqr_dist=SquaredDistance(closest,p);
00271 }
00272 else
00273 {
00274 ScalarType t = ((p-s.P0())*e)/eSquaredNorm;
00275 if(t<0) t = 0;
00276 else if(t>1) t = 1;
00277 closest = s.P0()+e*t;
00278 sqr_dist = SquaredDistance(p,closest);
00279 assert(!math::IsNAN(sqr_dist));
00280 }
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290 template <class ScalarType>
00291 void SegmentPointDistance( Segment3<ScalarType> s,
00292 const Point3<ScalarType> & p,
00293 Point3< ScalarType > &clos,
00294 ScalarType &dist)
00295 {
00296 SegmentPointSquaredDistance(s,p,clos,dist);
00297 dist=sqrt(dist);
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309 template <class ScalarType>
00310 void SegmentSegmentDistance(const vcg::Segment3<ScalarType> &s0,
00311 const vcg::Segment3<ScalarType> &s1,
00312 ScalarType &dist,
00313 bool ¶llel,
00314 vcg::Point3<ScalarType> &closest0,
00315 vcg::Point3<ScalarType> &closest1)
00316
00317 {
00318 typedef typename vcg::Point3<ScalarType> CoordType;
00319
00320 vcg::Line3<ScalarType> l0,l1;
00321
00323 l0.SetOrigin(s0.P0());
00324 l0.SetDirection((s0.P1()-s0.P0()).Normalize());
00325
00326 l1.SetOrigin(s1.P0());
00327 l1.SetDirection((s1.P1()-s1.P0()).Normalize());
00328
00330 ScalarType line_dist;
00331 CoordType closest_test0,closest_test1;
00332 LineLineDistance(l0,l1,parallel,line_dist,closest_test0,closest_test1);
00334 if (parallel)
00335 {
00337 ScalarType dist_test;
00338 CoordType clos_test;
00339
00340
00342 SegmentPointSquaredDistance(s0,s1.P0(),clos_test,dist);
00343 closest0=clos_test;
00344 closest1=s1.P0();
00346 SegmentPointSquaredDistance(s0,s1.P1(),clos_test,dist_test);
00347 if (dist_test<dist)
00348 {
00349 dist=dist_test;
00350 closest0=clos_test;
00351 closest1=s1.P1();
00352 }
00353 SegmentPointSquaredDistance(s1,s0.P0(),clos_test,dist_test);
00354 if (dist_test<dist)
00355 {
00356 dist=dist_test;
00357 closest0=s0.P0();
00358 closest1=clos_test;
00359 }
00360 SegmentPointSquaredDistance(s1,s0.P1(),clos_test,dist_test);
00361 if (dist_test<dist)
00362 {
00363 dist=dist_test;
00364 closest0=s0.P1();
00365 closest1=clos_test;
00366 }
00367 dist=sqrt(dist);
00368 return;
00369 }
00370
00374 ScalarType sqr_dist0;
00375 SegmentPointSquaredDistance(s0,closest_test0,closest0,sqr_dist0);
00376 ScalarType sqr_dist1;
00377 SegmentPointSquaredDistance(s1,closest_test1,closest1,sqr_dist1);
00378
00380 dist=(closest0-closest1).Norm();
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390 template<class ScalarType>
00391 void TrianglePointDistance(const vcg::Triangle3<ScalarType> &t,
00392 const typename vcg::Point3<ScalarType> & q,
00393 ScalarType & dist,
00394 typename vcg::Point3<ScalarType> & closest )
00395 {
00396 typedef typename vcg::Point3<ScalarType> CoordType;
00397
00398 CoordType clos[3];
00399 ScalarType distv[3];
00400 CoordType clos_proj;
00401 ScalarType distproj;
00402
00404 vcg::Plane3<ScalarType> plane;
00405 plane.Init(t.P(0),t.P(1),t.P(2));
00406 clos_proj=plane.Projection(q);
00407
00409 CoordType n=(t.P(1)-t.P(0))^(t.P(2)-t.P(0));
00410 CoordType n0=(t.P(0)-clos_proj)^(t.P(1)-clos_proj);
00411 CoordType n1=(t.P(1)-clos_proj)^(t.P(2)-clos_proj);
00412 CoordType n2=(t.P(2)-clos_proj)^(t.P(0)-clos_proj);
00413 distproj=(clos_proj-q).Norm();
00414 if (((n*n0)>=0)&&((n*n1)>=0)&&((n*n2)>=0))
00415 {
00416 closest=clos_proj;
00417 dist=distproj;
00418 return;
00419 }
00420
00421
00422
00423 vcg::Segment3<ScalarType> e0=vcg::Segment3<ScalarType>(t.P(0),t.P(1));
00424 vcg::Segment3<ScalarType> e1=vcg::Segment3<ScalarType>(t.P(1),t.P(2));
00425 vcg::Segment3<ScalarType> e2=vcg::Segment3<ScalarType>(t.P(2),t.P(0));
00426 SegmentPointDistance(e0,q,clos[0],distv[0]);
00427 SegmentPointDistance(e1,q,clos[1],distv[1]);
00428 SegmentPointDistance(e2,q,clos[2],distv[2]);
00429
00430
00431
00432
00433
00434
00435
00436 int min=0;
00437
00439 for (int i=1;i<3;i++)
00440 {
00441 if (distv[i]<distv[min])
00442 min=i;
00443 }
00444
00445 closest=clos[min];
00446 dist=distv[min];
00447 }
00448
00449
00450
00451
00452
00453
00454
00455
00456 template<class ScalarType>
00457 void TriangleSegmentDistance(const vcg::Triangle3<ScalarType> &t,
00458 const vcg::Segment3<ScalarType> &s,
00459 ScalarType & dist)
00460 {
00461 dist=std::numeric_limits<ScalarType>::max();
00463 ScalarType a,b;
00464 typedef typename vcg::Point3<ScalarType> CoordType;
00465
00466 bool intersect=IntersectionSegmentTriangle<vcg::Triangle3<ScalarType> >(s,t,a,b);
00467 if (intersect)
00468 {
00469 dist=0;
00470 return;
00471 }
00473 vcg::Plane3<ScalarType> pl3;
00474 pl3.Init(t.P(0),t.P(1),t.P(2));
00475 CoordType pj0=pl3.Projection(s.P(0));
00476 CoordType pj1=pl3.Projection(s.P(1));
00478 ScalarType dpj0=(pj0-s.P(0)).Norm();
00479 ScalarType dpj1=(pj1-s.P(1)).Norm();
00480
00482 CoordType bary0,bary1;
00483 bool Inside0=vcg::InterpolationParameters(t,pj0,bary0);
00484 bool Inside1=vcg::InterpolationParameters(t,pj1,bary1);
00485 if (Inside0&&Inside1)
00486 {
00487 dist=std::min(dpj0,dpj1);
00488 return;
00489 }
00491 if (Inside0)
00492 dist=dpj0;
00493 if (Inside1)
00494 dist=dpj1;
00495
00497 for (int i=0;i<3;i++)
00498 {
00499 vcg::Segment3<ScalarType> edge=vcg::Segment3<ScalarType>(t.P0(i),t.P0((i+1)%3));
00500 ScalarType test_dist;
00501 CoordType clos1,clos2;
00502 bool parallel;
00503 vcg::SegmentSegmentDistance<ScalarType>(s,edge,test_dist,parallel,clos1,clos2);
00504 if (test_dist<dist)
00505 dist=test_dist;
00506 }
00507 }
00508
00509
00510
00511
00512
00513
00514
00515 template<class ScalarType>
00516 void TriangleTriangleDistance(const vcg::Triangle3<ScalarType> &t0,
00517 const vcg::Triangle3<ScalarType> &t1,
00518 ScalarType &dist)
00519 {
00520 const ScalarType loc_EPSILON=(vcg::DoubleArea(t0)+vcg::DoubleArea(t1))*(ScalarType)0.0000001;
00521 dist=std::numeric_limits<ScalarType>::max();
00522
00525 for (int i=0;i<3;i++)
00526 {
00527 vcg::Segment3<ScalarType> edge=vcg::Segment3<ScalarType>(t0.P0(i),t0.P0((i+1)%3));
00528 ScalarType test_dist;
00529 vcg::TriangleSegmentDistance<ScalarType>(t1,edge,test_dist);
00530 if (test_dist<loc_EPSILON)
00531 {
00532 dist=0;
00533 return;
00534 }
00535 if (test_dist<dist)
00536 dist=test_dist;
00537 }
00539 for (int i=0;i<3;i++)
00540 {
00541 vcg::Segment3<ScalarType> edge=vcg::Segment3<ScalarType>(t1.P0(i),t1.P0((i+1)%3));
00542 ScalarType test_dist;
00543 vcg::TriangleSegmentDistance<ScalarType>(t0,edge,test_dist);
00544 if (test_dist<loc_EPSILON)
00545 {
00546 dist=0;
00547 return;
00548 }
00549 if (test_dist<dist)
00550 dist=test_dist;
00551 }
00552 }
00553
00554 }
00555
00556 #endif