From 7ffb8789134103b363581aa9ff1ca73cda5aa2e1 Mon Sep 17 00:00:00 2001 From: cignoni Date: Fri, 6 Jul 2012 15:24:04 +0000 Subject: [PATCH] SIGNIFICANT CHANGE About the point to mesh distance functionalities Now the two different 'path' for this distance computation (with or without the precomputation of planes and edges for triangular faces) are well distinct and with different names: PointDistanceEP and PointDistanceBase See the sample/trimesh_closest sample for more details --- vcg/complex/algorithms/closest.h | 52 +++---- vcg/complex/algorithms/intersection.h | 2 +- vcg/simplex/face/distance.h | 200 ++++++++------------------ 3 files changed, 90 insertions(+), 164 deletions(-) diff --git a/vcg/complex/algorithms/closest.h b/vcg/complex/algorithms/closest.h index 65c078e0..6dcfed64 100644 --- a/vcg/complex/algorithms/closest.h +++ b/vcg/complex/algorithms/closest.h @@ -91,7 +91,7 @@ namespace vcg { // UGrid, ma non sono riuscito a definirlo implicitamente template - typename MESH::FaceType * GetClosestFace( MESH & mesh, GRID & gr, const typename GRID::CoordType & _p, + typename MESH::FaceType * GetClosestFaceEP( MESH & mesh, GRID & gr, const typename GRID::CoordType & _p, const typename GRID::ScalarType & _maxDist, typename GRID::ScalarType & _minDist, typename GRID::CoordType &_closestPt, typename GRID::CoordType & _normf, typename GRID::CoordType & _ip) @@ -101,7 +101,7 @@ namespace vcg { typedef FaceTmark MarkerFace; MarkerFace mf(&mesh); - vcg::face::PointDistanceFunctor FDistFunct; + vcg::face::PointDistanceEPFunctor FDistFunct; _minDist=_maxDist; typename MESH::FaceType* bestf= gr.GetClosest(FDistFunct, mf, _p, _maxDist, _minDist, _closestPt); @@ -120,21 +120,8 @@ namespace vcg { return (0); } - /*template - typename MESH::FaceType * GetClosestFace( MESH & mesh,GRID & gr,const typename GRID::CoordType & _p, - const typename GRID::ScalarType & _maxDist,typename GRID::ScalarType & _minDist, - typename GRID::CoordType &_closestPt,typename GRID::CoordType & _normf) - { - Point3 _ip; - typedef FaceTmark MarkerFace; - MarkerFace mf; - mf.SetMesh(&mesh); - vcg::face::PointDistanceFunctor FDistFunct; - typename MESH::FaceType* bestf= gr.GetClosest(FDistFunct,mf,_p,_maxDist,_minDist,_closestPt) ); - }*/ - template - typename MESH::FaceType * GetClosestFace( MESH & mesh,GRID & gr,const typename GRID::CoordType & _p, + typename MESH::FaceType * GetClosestFaceBase( MESH & mesh,GRID & gr,const typename GRID::CoordType & _p, const typename GRID::ScalarType & _maxDist,typename GRID::ScalarType & _minDist, typename GRID::CoordType &_closestPt) { @@ -143,7 +130,22 @@ namespace vcg { typedef FaceTmark MarkerFace; MarkerFace mf; mf.SetMesh(&mesh); - vcg::face::PointDistanceFunctor PDistFunct; + vcg::face::PointDistanceBaseFunctor PDistFunct; + _minDist=_maxDist; + return (gr.GetClosest(PDistFunct,mf,_p,_maxDist,_minDist,_closestPt)); + } + + template + typename MESH::FaceType * GetClosestFaceEP( MESH & mesh,GRID & gr,const typename GRID::CoordType & _p, + const typename GRID::ScalarType & _maxDist,typename GRID::ScalarType & _minDist, + typename GRID::CoordType &_closestPt) + { + typedef typename GRID::ScalarType ScalarType; + typedef Point3 Point3x; + typedef FaceTmark MarkerFace; + MarkerFace mf; + mf.SetMesh(&mesh); + vcg::face::PointDistanceEPFunctor PDistFunct; _minDist=_maxDist; return (gr.GetClosest(PDistFunct,mf,_p,_maxDist,_minDist,_closestPt)); } @@ -214,14 +216,14 @@ namespace vcg { } template - unsigned int GetKClosestFace(MESH & mesh,GRID & gr, const unsigned int _k, + unsigned int GetKClosestFaceEP(MESH & mesh,GRID & gr, const unsigned int _k, const typename GRID::CoordType & _p, const typename GRID::ScalarType & _maxDist, OBJPTRCONTAINER & _objectPtrs,DISTCONTAINER & _distances, POINTCONTAINER & _points) { typedef FaceTmark MarkerFace; MarkerFace mf; mf.SetMesh(&mesh); - vcg::face::PointDistanceFunctor FDistFunct; + vcg::face::PointDistanceEPFunctor FDistFunct; return (gr.GetKClosest /**/ (FDistFunct,mf,_k,_p,_maxDist,_objectPtrs,_distances,_points)); } @@ -256,7 +258,7 @@ namespace vcg { } template - unsigned int GetInSphereFace(MESH & mesh, + unsigned int GetInSphereFaceBase(MESH & mesh, GRID & gr, const typename GRID::CoordType & _p, const typename GRID::ScalarType & _r, @@ -267,7 +269,7 @@ namespace vcg { typedef FaceTmark MarkerFace; MarkerFace mf; mf.SetMesh(&mesh); - typedef vcg::face::PointDistanceFunctor FDistFunct; + typedef vcg::face::PointDistanceBaseFunctor FDistFunct; return (gr.GetInSphere/**/ (FDistFunct(),mf,_p,_r,_objectPtrs,_distances,_points)); } @@ -413,20 +415,20 @@ namespace vcg { //**ITERATORS DEFINITION**// template - class ClosestFaceIterator:public vcg::ClosestIterator, FaceTmark > + class ClosestFaceEPIterator:public vcg::ClosestIterator, FaceTmark > { public: typedef GRID GridType; typedef MESH MeshType; typedef FaceTmark MarkerFace; - typedef vcg::face::PointDistanceFunctor PDistFunct; + typedef vcg::face::PointDistanceEPFunctor PDistFunct; typedef vcg::ClosestIterator > ClosestBaseType; typedef typename MESH::FaceType FaceType; typedef typename MESH::ScalarType ScalarType; //ClosestFaceIterator(GridType &_Si):ClosestBaseType(_Si,PDistFunct()){} - ClosestFaceIterator(GridType &_Si):ClosestBaseType(_Si,PDistFunct()){} + ClosestFaceEPIterator(GridType &_Si):ClosestBaseType(_Si,PDistFunct()){} // Commented out: it seems unuseful and make gcc complain. p. void SetMesh(MeshType *m) diff --git a/vcg/complex/algorithms/intersection.h b/vcg/complex/algorithms/intersection.h index 21603540..16b75e4b 100644 --- a/vcg/complex/algorithms/intersection.h +++ b/vcg/complex/algorithms/intersection.h @@ -397,7 +397,7 @@ void IntersectionBallMesh( IndexingType * grid, TriMeshType & m, const vcg::Sph if(tol == 0) tol = M_PI * ball.Radius() * ball.Radius() / 100000; - vcg::tri::GetInSphereFace(m,*grid, ball.Center(), ball.Radius(),closestsF,distances,witnesses); + vcg::tri::GetInSphereFaceBase(m,*grid, ball.Center(), ball.Radius(),closestsF,distances,witnesses); for(cfi =closestsF.begin(); cfi != closestsF.end(); ++cfi) if(!(**cfi).IsD() && IntersectionSphereTriangle(ball ,(**cfi), witness , &info)) closests.push_back(&(**cfi)); diff --git a/vcg/simplex/face/distance.h b/vcg/simplex/face/distance.h index a3480580..57e9e603 100644 --- a/vcg/simplex/face/distance.h +++ b/vcg/simplex/face/distance.h @@ -19,42 +19,6 @@ * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * -****************************************************************************/ -/**************************************************************************** - History - -$Log: not supported by cvs2svn $ -Revision 1.10 2006/01/22 10:06:23 cignoni -Corrected use of Area with the unambiguous DoubleArea - -Revision 1.9 2005/09/28 19:35:06 m_di_benedetto -Added class PointDistanceFunctor. - -Revision 1.8 2005/09/14 12:58:44 pietroni -changed min calls to Min of math.h of vcglib - -Revision 1.7 2005/09/14 09:58:32 pietroni -removed vcg::math::Min definition generate warnings - -Revision 1.6 2005/09/14 09:03:54 pietroni -added definition of vcg::math::Min function - -Revision 1.5 2005/02/02 16:44:34 pietroni -1 warning corrected added casting in const ScalarType EPSILON = ScalarType( 0.000001); - -Revision 1.4 2005/01/28 12:00:33 cignoni -small gcc compiling issues for namespaces - -Revision 1.3 2005/01/24 15:35:25 cignoni -Removed a 'using namespace' - -Revision 1.2 2005/01/21 17:11:03 pietroni -changed Dist Function to PointDistance... the function is on vcg::face::PointDistance this file will contain all distance functions between a face and othe entities - -Revision 1.1 2004/05/12 18:50:25 ganovelli -created - - ****************************************************************************/ #ifndef __VCGLIB_FACE_DISTANCE @@ -68,54 +32,36 @@ created namespace vcg { namespace face{ /* - Point face distance - trova il punto

sulla faccia piu' vicino a , con possibilit� di - rejection veloce su se la distanza trovata � maggiore di + Basic Wrapper for getting point-triangular face distance + distance is unsigned; - Commenti del 12/11/02 - Funziona solo se la faccia e di quelle di tipo E (con edge e piano per faccia gia' calcolati) - algoritmo: - 1) si calcola la proiezione

di q sul piano della faccia - 2) se la distanza punto piano e' > rejdist ritorna - 3) si lavora sul piano migliore e si cerca di capire se il punto sta dentro il triangolo: - a) prodotto vettore tra edge triangolo (v[i+1]-v[i]) e (p-v[i]) - b) se il risultato e' negativo (gira in senso orario) allora il punto - sta fuori da quella parte e si fa la distanza punto segmento. - c) se il risultato sempre positivo allora sta dentro il triangolo - 4) e si restituisce la distanza punto /piano gia` calcolata + return true if the closest point on is nearer than the passed ; + return false otherwiswe (and q is not valid) - Note sulla robustezza: - il calcolo del prodotto vettore e` la cosa piu` delicata: - possibili fallimenti quando a^b ~= 0 - 1) doveva essere <= 0 e viene positivo (q era fuori o sulla linea dell'edge) - allora capita che si faccia la distanza punto piano anziche` la distanza punto seg - 2) doveva essere > 0 e viene <=0 (q era dentro il triangolo) + This wrapper requires that your face has + - Per Face Flags well initialized + - Per Face EdgePlane component initialized. + Initialization must be done with: -*/ - template - bool PointDistance( const FaceType &f, - const vcg::Point3 & q, - typename FaceType::ScalarType & dist, - vcg::Point3 & p ) - { - typedef typename FaceType::ScalarType ScalarType; - - const ScalarType EPS = ScalarType( 0.000001); + tri::UpdateEdges::Set(yourMesh); + */ + template + bool PointDistanceEP( const FaceType &f, + const vcg::Point3 & q, + typename FaceType::ScalarType & dist, + vcg::Point3 & p ) + { + typedef typename FaceType::ScalarType ScalarType; + const ScalarType EPS = ScalarType( 0.000001); - //const ScalarType EPSILON = 0.00000001; ScalarType b,b0,b1,b2; - // Calcolo distanza punto piano - ScalarType d = SignedDistancePlanePoint( f.cPlane(), q ); - if( d>dist || d<-dist ) // Risultato peggiore: niente di fatto - return false; - // Calcolo del punto sul piano - // NOTA: aggiunto un '-d' in fondo Paolo C. + ScalarType d = SignedDistancePlanePoint( f.cPlane(), q ); + if( d>dist || d<-dist ) return false; + Point3 t = f.cPlane().Direction(); - t[0] *= -d; - t[1] *= -d; - t[2] *= -d; - p = q; p += t; + p = q - t*d; // p is the projection of q on the face plane + // Now Choose the best plane and test to see if p is inside the triangle switch( f.Flags() & (FaceType::NORMX|FaceType::NORMY|FaceType::NORMZ) ) { @@ -141,24 +87,18 @@ namespace vcg { if(dist>b2) { dist = b2; return true; } else return false; } - // sono tutti e tre > 0 quindi dovrebbe essere dentro; - // per sicurezza se il piu' piccolo dei tre e' < epsilon (scalato rispetto all'area della faccia - // per renderlo dimension independent.) allora si usa ancora la distanza punto - // segmento che e' piu robusta della punto piano, e si fa dalla parte a cui siamo piu' - // vicini (come prodotto vettore) - // Nota: si potrebbe rendere un pochino piu' veloce sostituendo Area() - // con il prodotto vettore dei due edge in 2d lungo il piano migliore. - if( (b=std::min(b0,std::min(b1,b2)) ) < EPS*DoubleArea(f)) - { - ScalarType bt; - if(b==b0) bt = PSDist(q,f.V(1)->cP(),f.V(2)->cP(),p); - else if(b==b1) bt = PSDist(q,f.V(2)->cP(),f.V(0)->cP(),p); - else { assert(b==b2); - bt = PSDist(q,f.V(0)->cP(),f.V(1)->cP(),p); - } - //printf("Warning area:%g %g %g %g thr:%g bt:%g\n",Area(), b0,b1,b2,EPS*Area(),bt); - if(dist>bt) { dist = bt; return true; } - else return false; + // if all these tests failed the projection p should be inside. + // Some further tests for more robustness... + if( (b=std::min(b0,std::min(b1,b2)) ) < EPS*DoubleArea(f)) + { + ScalarType bt; + if(b==b0) bt = PSDist(q,f.V(1)->cP(),f.V(2)->cP(),p); + else if(b==b1) bt = PSDist(q,f.V(2)->cP(),f.V(0)->cP(),p); + else { assert(b==b2); + bt = PSDist(q,f.V(0)->cP(),f.V(1)->cP(),p); + } + if(dist>bt) { dist = bt; return true; } + else return false; } break; @@ -184,16 +124,15 @@ namespace vcg { if(dist>b2) { dist = b2; return true; } else return false; } - if( (b=math::Min(b0,b1,b2)) < EPS*DoubleArea(f)) - { - ScalarType bt; - if(b==b0) bt = PSDist(q,f.V(1)->cP(),f.V(2)->cP(),p); - else if(b==b1) bt = PSDist(q,f.V(2)->cP(),f.V(0)->cP(),p); - else { assert(b==b2); - bt = PSDist(q,f.V(0)->cP(),f.V(1)->cP(),p); - } - //printf("Warning area:%g %g %g %g thr:%g bt:%g\n",Area(), b0,b1,b2,EPSILON*Area(),bt); - if(dist>bt) { dist = bt; return true; } + if( (b=math::Min(b0,b1,b2)) < EPS*DoubleArea(f)) + { + ScalarType bt; + if(b==b0) bt = PSDist(q,f.V(1)->cP(),f.V(2)->cP(),p); + else if(b==b1) bt = PSDist(q,f.V(2)->cP(),f.V(0)->cP(),p); + else { assert(b==b2); + bt = PSDist(q,f.V(0)->cP(),f.V(1)->cP(),p); + } + if(dist>bt) { dist = bt; return true; } else return false; } break; @@ -220,30 +159,28 @@ namespace vcg { if(dist>b2) { dist = b2; return true; } else return false; } - if( (b=math::Min(b0,b1,b2)) < EPS*DoubleArea(f)) - { - ScalarType bt; - if(b==b0) bt = PSDist(q,f.V(1)->cP(),f.V(2)->cP(),p); - else if(b==b1) bt = PSDist(q,f.V(2)->cP(),f.V(0)->cP(),p); - else { assert(b==b2); - bt = PSDist(q,f.V(0)->cP(),f.V(1)->cP(),p); - } - //printf("Warning area:%g %g %g %g thr:%g bt:%g\n",Area(), b0,b1,b2,EPSILON*Area(),bt); - - if(dist>bt) { dist = bt; return true; } + if( (b=math::Min(b0,b1,b2)) < EPS*DoubleArea(f)) + { + ScalarType bt; + if(b==b0) bt = PSDist(q,f.V(1)->cP(),f.V(2)->cP(),p); + else if(b==b1) bt = PSDist(q,f.V(2)->cP(),f.V(0)->cP(),p); + else { assert(b==b2); + bt = PSDist(q,f.V(0)->cP(),f.V(1)->cP(),p); + } + + if(dist>bt) { dist = bt; return true; } else return false; } break; - } + } // end switch dist = ScalarType(fabs(d)); - //dist = Distance(p,q); return true; } template - class PointDistanceFunctor { + class PointDistanceEPFunctor { public: typedef S ScalarType; typedef Point3 QueryType; @@ -254,7 +191,7 @@ namespace vcg { const Point3 fp = Point3::Construct(p); Point3 fq; typename FACETYPE::ScalarType md = (typename FACETYPE::ScalarType)(minDist); - const bool ret = PointDistance(f, fp, md, fq); + const bool ret = PointDistanceEP(f, fp, md, fq); minDist = (SCALARTYPE)(md); q = Point3::Construct(fq); return (ret); @@ -301,8 +238,6 @@ namespace vcg { /// BASIC VERSION of the Point-face distance that does not require the EdgePlane Additional data. /// Given a face and a point, returns the closest point of the face to p. - /// it assumes that the face has Normalized Normal. - // UpdateNormals::PerFaceNormalized(m) template bool PointDistanceBase( @@ -312,12 +247,6 @@ namespace vcg { vcg::Point3 & p ) { typedef typename FaceType::ScalarType ScalarType; - // remember that the macro NDEBUG is defined when you want to optimize a lot. - #ifndef NDEBUG - static int staticCnt=0; // small piece of code that sometime check that face normals are really normalized - if((staticCnt++%100)==0) - assert((f.cN().SquaredNorm() ==0) || (f.cN().SquaredNorm() > 0.9999 && f.cN().SquaredNorm()<1.0001)); // if you get this assert you have forgot to make a UpdateNormals::PerFaceNormalized(m) - #endif if(f.cN()==Point3(0,0,0)) // to correctly manage the case of degenerate triangles we consider them as segments. { @@ -340,22 +269,17 @@ namespace vcg { return true; } - Plane3 fPlane; + Plane3 fPlane; fPlane.Init(f.cP(0),f.cN()); - const ScalarType EPS = ScalarType( 0.000001); + const ScalarType EPS = ScalarType( 0.000001); ScalarType b,b0,b1,b2; // Calcolo distanza punto piano ScalarType d = SignedDistancePlanePoint( fPlane, q ); if( d>dist || d<-dist ) // Risultato peggiore: niente di fatto return false; - // Calcolo del punto sul piano - // NOTA: aggiunto un '-d' in fondo Paolo C. - Point3 t = fPlane.Direction(); - t[0] *= -d; - t[1] *= -d; - t[2] *= -d; - p = q; p += t; + // Projection of query point onto the triangle plane + p = q - fPlane.Direction()*d; Point3 fEdge[3]; fEdge[0] = f.cP(1); fEdge[0] -= f.cP(0); @@ -421,7 +345,7 @@ namespace vcg { // vicini (come prodotto vettore) // Nota: si potrebbe rendere un pochino piu' veloce sostituendo Area() // con il prodotto vettore dei due edge in 2d lungo il piano migliore. - if( (b=vcg::math::Min(b0,b1,b2)) < EPS*DoubleArea(f)) + if( (b=vcg::math::Min(b0,b1,b2)) < EPS*DoubleArea(f)) { ScalarType bt; if(b==b0) bt = PSDist(q,f.V(1)->cP(),f.V(2)->cP(),p);