distance3.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *   
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
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 * Computes the minimum distance between a 3D box and a point
00036 * @param[in] p                          The input point
00037 * @param[in] b                          The input bounding box
00038 * return                        The distance
00039 * This function returns 0 for points Inside the bbox while the next one return the distance from the surface
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 * Computes the minimum distance between a 3D box and a point
00058 * @param[in] p                          The input point
00059 * @param[in] b                          The input bounding box
00060 * @param[out] dist                      The distance
00061 * Note that this function with respect to the previous one compute the distance between a point
00062 * and the 'surface' of a Box3. 
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 * Computes the minimum distance between a sphere and a point
00097 * @param[in] p                          The input point
00098 * @param[in] sphere             The input sphere
00099 * @param[out] dist                      The distance
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 * Computes the minimum distance between two spheres
00112 * @param[in] sphere0                            The input sphere
00113 * @param[in] sphere1                            The input sphere
00114 * @param[out] dist                      The distance
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 * Computes the minimum squared distance between a between a point and a plane
00129 * @param[in] pl                 The input line
00130 * @param[in] p          The input point
00131 * @param[out] closest   The closest point
00132 * @param[out] dist              The squared distance
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 * Computes the minimum squared distance between a between a point and a plane
00147 * @param[in] pl                 The input line
00148 * @param[in] p          The input point
00149 * @param[out] closest   The closest point
00150 * @param[out] dist              The squared distance
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 * Computes the minimum squared distance between a between a point and a line
00165 * @param[in] l                          The input line
00166 * @param[in] p                          The input point
00167 * @param[out] closest   The closest point
00168 * @param[out] dist              The squared distance
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 * Computes the minimum  distance between a between a point and a line
00180 * @param[in] l                          The input line
00181 * @param[in] p                          The input point
00182 * @param[out] closest                           The closest point
00183 * @param[out] dist                      The distance
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 * Computes the minimum  distance between two lines
00195 * @param[in] mLine0                             The input line0
00196 * @param[in] mLine1                             The input line1
00197 * @param[out] parallel          true if the two lines are parallel
00198 * @param[mClosestPoint0]  the closest point on line0
00199 * @param[mClosestPoint1]  the closest point on line1
00200 */
00201 template <class ScalarType>
00202 void LineLineDistance(const vcg::Line3<ScalarType> &mLine0,
00203                                                                                         const vcg::Line3<ScalarType> &mLine1,
00204                                                                                         bool &parallel,
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         // Lines are not parallel.
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         // Lines are parallel, select any closest pair of points.
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     /*mLine0Parameter = s0;
00241     mLine1Parameter = s1;*/
00242 
00243     // Account for numerical round-off errors.
00244     if (sqrDist < (ScalarType)0)
00245     {
00246         sqrDist = (ScalarType)0;
00247     }
00248     dist=sqrt(sqrDist);
00249 }
00250 
00251 
00252 /*
00253 * Computes the minimum distance between a segment and a point
00254 * @param[in] segment    The input segment
00255 * @param[in] p                          The input point
00256 * @param[in] clos                       The closest point
00257 * @param[in] sqr_dist The squared distance
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 * Computes the minimum distance between a segment and a point
00285 * @param[in] segment    The input segment
00286 * @param[in] p                          The input point
00287 * @param[in] clos                       The closest point
00288 * @param[in] dist The distance
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 * Computes the minimum distance between two segments
00302 * @param[in] s0                         The input segment0
00303 * @param[in] s1                         The input segment1
00304 * @param[out] parallel          true if the two segments are parallel
00305 * @param[out] dist              the distance
00306 * @param[closest0]  the closest point on segment0
00307 * @param[closest1]  the closest point on segment1
00308 */
00309 template <class ScalarType>
00310 void SegmentSegmentDistance(const vcg::Segment3<ScalarType> &s0,
00311                                                                                                                 const vcg::Segment3<ScalarType> &s1,
00312                                                                                                                 ScalarType &dist,
00313                                                                                                                 bool &parallel,
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     //CoordType to_test[4]={s1.P0(),s1.P1(),s0.P0(),s1.P1()};
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  /* @brief Computes the distance between a triangle and a point.
00384  *
00385  * @param t         reference to the triangle
00386  * @param q         point location
00387  * @param dist      distance from p to t
00388  * @param closest   perpendicular projection of p onto t
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         //distance from the edges
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         /*clos[0]=ClosestPoint<ScalarType>( e0, q);
00430         clos[1]=ClosestPoint<ScalarType>( e1, q);
00431         clos[2]=ClosestPoint<ScalarType>( e2, q);
00432         */
00433         //distv[0]=(clos[0]-q).Norm();
00434         //distv[1]=(clos[1]-q).Norm();
00435         //distv[2]=(clos[2]-q).Norm();
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 * return the distance between a triangle and a segment
00452 * @param[in] t                          The input triangle
00453 * @param[in] s                          The input segment
00454 * @param[out] dist              the distance
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 * return the minimum distance between two triangles
00511 * @param[in] t0                         The input triangle0
00512 * @param[in] t1                         The input triangle1
00513 * @param[out] dist              the distance
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


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:30:35