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
This commit is contained in:
Paolo Cignoni 2012-07-06 15:24:04 +00:00
parent 58eced0506
commit 7ffb878913
3 changed files with 90 additions and 164 deletions

View File

@ -91,7 +91,7 @@ namespace vcg {
// UGrid<MESH::FaceContainer >, ma non sono riuscito a definirlo implicitamente // UGrid<MESH::FaceContainer >, ma non sono riuscito a definirlo implicitamente
template <class MESH, class GRID> template <class MESH, class GRID>
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, const typename GRID::ScalarType & _maxDist, typename GRID::ScalarType & _minDist,
typename GRID::CoordType &_closestPt, typename GRID::CoordType & _normf, typename GRID::CoordType &_closestPt, typename GRID::CoordType & _normf,
typename GRID::CoordType & _ip) typename GRID::CoordType & _ip)
@ -101,7 +101,7 @@ namespace vcg {
typedef FaceTmark<MESH> MarkerFace; typedef FaceTmark<MESH> MarkerFace;
MarkerFace mf(&mesh); MarkerFace mf(&mesh);
vcg::face::PointDistanceFunctor<ScalarType> FDistFunct; vcg::face::PointDistanceEPFunctor<ScalarType> FDistFunct;
_minDist=_maxDist; _minDist=_maxDist;
typename MESH::FaceType* bestf= gr.GetClosest(FDistFunct, mf, _p, _maxDist, _minDist, _closestPt); typename MESH::FaceType* bestf= gr.GetClosest(FDistFunct, mf, _p, _maxDist, _minDist, _closestPt);
@ -120,21 +120,8 @@ namespace vcg {
return (0); return (0);
} }
/*template <class MESH, class GRID>
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<typename GRID::ScalarType> _ip;
typedef FaceTmark<MESH> MarkerFace;
MarkerFace mf;
mf.SetMesh(&mesh);
vcg::face::PointDistanceFunctor FDistFunct;
typename MESH::FaceType* bestf= gr.GetClosest(FDistFunct,mf,_p,_maxDist,_minDist,_closestPt) );
}*/
template <class MESH, class GRID> template <class MESH, class GRID>
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, const typename GRID::ScalarType & _maxDist,typename GRID::ScalarType & _minDist,
typename GRID::CoordType &_closestPt) typename GRID::CoordType &_closestPt)
{ {
@ -143,7 +130,22 @@ namespace vcg {
typedef FaceTmark<MESH> MarkerFace; typedef FaceTmark<MESH> MarkerFace;
MarkerFace mf; MarkerFace mf;
mf.SetMesh(&mesh); mf.SetMesh(&mesh);
vcg::face::PointDistanceFunctor<ScalarType> PDistFunct; vcg::face::PointDistanceBaseFunctor<ScalarType> PDistFunct;
_minDist=_maxDist;
return (gr.GetClosest(PDistFunct,mf,_p,_maxDist,_minDist,_closestPt));
}
template <class MESH, class GRID>
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<ScalarType> Point3x;
typedef FaceTmark<MESH> MarkerFace;
MarkerFace mf;
mf.SetMesh(&mesh);
vcg::face::PointDistanceEPFunctor<ScalarType> PDistFunct;
_minDist=_maxDist; _minDist=_maxDist;
return (gr.GetClosest(PDistFunct,mf,_p,_maxDist,_minDist,_closestPt)); return (gr.GetClosest(PDistFunct,mf,_p,_maxDist,_minDist,_closestPt));
} }
@ -214,14 +216,14 @@ namespace vcg {
} }
template <class MESH, class GRID, class OBJPTRCONTAINER,class DISTCONTAINER, class POINTCONTAINER> template <class MESH, class GRID, class OBJPTRCONTAINER,class DISTCONTAINER, class POINTCONTAINER>
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, const typename GRID::CoordType & _p, const typename GRID::ScalarType & _maxDist,
OBJPTRCONTAINER & _objectPtrs,DISTCONTAINER & _distances, POINTCONTAINER & _points) OBJPTRCONTAINER & _objectPtrs,DISTCONTAINER & _distances, POINTCONTAINER & _points)
{ {
typedef FaceTmark<MESH> MarkerFace; typedef FaceTmark<MESH> MarkerFace;
MarkerFace mf; MarkerFace mf;
mf.SetMesh(&mesh); mf.SetMesh(&mesh);
vcg::face::PointDistanceFunctor<typename MESH::ScalarType> FDistFunct; vcg::face::PointDistanceEPFunctor<typename MESH::ScalarType> FDistFunct;
return (gr.GetKClosest /*<vcg::face::PointDistanceFunctor, MarkerFace,OBJPTRCONTAINER,DISTCONTAINER,POINTCONTAINER>*/ return (gr.GetKClosest /*<vcg::face::PointDistanceFunctor, MarkerFace,OBJPTRCONTAINER,DISTCONTAINER,POINTCONTAINER>*/
(FDistFunct,mf,_k,_p,_maxDist,_objectPtrs,_distances,_points)); (FDistFunct,mf,_k,_p,_maxDist,_objectPtrs,_distances,_points));
} }
@ -256,7 +258,7 @@ namespace vcg {
} }
template <class MESH, class GRID, class OBJPTRCONTAINER, class DISTCONTAINER, class POINTCONTAINER> template <class MESH, class GRID, class OBJPTRCONTAINER, class DISTCONTAINER, class POINTCONTAINER>
unsigned int GetInSphereFace(MESH & mesh, unsigned int GetInSphereFaceBase(MESH & mesh,
GRID & gr, GRID & gr,
const typename GRID::CoordType & _p, const typename GRID::CoordType & _p,
const typename GRID::ScalarType & _r, const typename GRID::ScalarType & _r,
@ -267,7 +269,7 @@ namespace vcg {
typedef FaceTmark<MESH> MarkerFace; typedef FaceTmark<MESH> MarkerFace;
MarkerFace mf; MarkerFace mf;
mf.SetMesh(&mesh); mf.SetMesh(&mesh);
typedef vcg::face::PointDistanceFunctor<typename MESH::ScalarType> FDistFunct; typedef vcg::face::PointDistanceBaseFunctor<typename MESH::ScalarType> FDistFunct;
return (gr.GetInSphere/*<FDistFunct,MarkerFace,OBJPTRCONTAINER,DISTCONTAINER,POINTCONTAINER>*/ return (gr.GetInSphere/*<FDistFunct,MarkerFace,OBJPTRCONTAINER,DISTCONTAINER,POINTCONTAINER>*/
(FDistFunct(),mf,_p,_r,_objectPtrs,_distances,_points)); (FDistFunct(),mf,_p,_r,_objectPtrs,_distances,_points));
} }
@ -413,20 +415,20 @@ namespace vcg {
//**ITERATORS DEFINITION**// //**ITERATORS DEFINITION**//
template <class GRID,class MESH> template <class GRID,class MESH>
class ClosestFaceIterator:public vcg::ClosestIterator<GRID, class ClosestFaceEPIterator:public vcg::ClosestIterator<GRID,
vcg::face::PointDistanceFunctor<typename MESH::ScalarType>, FaceTmark<MESH> > vcg::face::PointDistanceEPFunctor<typename MESH::ScalarType>, FaceTmark<MESH> >
{ {
public: public:
typedef GRID GridType; typedef GRID GridType;
typedef MESH MeshType; typedef MESH MeshType;
typedef FaceTmark<MESH> MarkerFace; typedef FaceTmark<MESH> MarkerFace;
typedef vcg::face::PointDistanceFunctor<typename MESH::ScalarType> PDistFunct; typedef vcg::face::PointDistanceEPFunctor<typename MESH::ScalarType> PDistFunct;
typedef vcg::ClosestIterator<GRID,PDistFunct, FaceTmark<MESH> > ClosestBaseType; typedef vcg::ClosestIterator<GRID,PDistFunct, FaceTmark<MESH> > ClosestBaseType;
typedef typename MESH::FaceType FaceType; typedef typename MESH::FaceType FaceType;
typedef typename MESH::ScalarType ScalarType; typedef typename MESH::ScalarType ScalarType;
//ClosestFaceIterator(GridType &_Si):ClosestBaseType(_Si,PDistFunct<FaceType,ScalarType>()){} //ClosestFaceIterator(GridType &_Si):ClosestBaseType(_Si,PDistFunct<FaceType,ScalarType>()){}
ClosestFaceIterator(GridType &_Si):ClosestBaseType(_Si,PDistFunct()){} ClosestFaceEPIterator(GridType &_Si):ClosestBaseType(_Si,PDistFunct()){}
// Commented out: it seems unuseful and make gcc complain. p. // Commented out: it seems unuseful and make gcc complain. p.
void SetMesh(MeshType *m) void SetMesh(MeshType *m)

View File

@ -397,7 +397,7 @@ void IntersectionBallMesh( IndexingType * grid, TriMeshType & m, const vcg::Sph
if(tol == 0) tol = M_PI * ball.Radius() * ball.Radius() / 100000; 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) for(cfi =closestsF.begin(); cfi != closestsF.end(); ++cfi)
if(!(**cfi).IsD() && IntersectionSphereTriangle<ScalarType>(ball ,(**cfi), witness , &info)) if(!(**cfi).IsD() && IntersectionSphereTriangle<ScalarType>(ball ,(**cfi), witness , &info))
closests.push_back(&(**cfi)); closests.push_back(&(**cfi));

View File

@ -19,42 +19,6 @@
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. * * 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<ScalarType> of math.h of vcglib
Revision 1.7 2005/09/14 09:58:32 pietroni
removed vcg::math::Min<ScalarType> definition generate warnings
Revision 1.6 2005/09/14 09:03:54 pietroni
added definition of vcg::math::Min<ScalarType> 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 #ifndef __VCGLIB_FACE_DISTANCE
@ -68,54 +32,36 @@ created
namespace vcg { namespace vcg {
namespace face{ namespace face{
/* /*
Point face distance Basic Wrapper for getting point-triangular face distance
trova il punto <p> sulla faccia piu' vicino a <q>, con possibilit<EFBFBD> di distance is unsigned;
rejection veloce su se la distanza trovata <EFBFBD> maggiore di <rejdist>
Commenti del 12/11/02 return true if the closest point <q> on <f> is nearer than the passed <dist>;
Funziona solo se la faccia e di quelle di tipo E (con edge e piano per faccia gia' calcolati) return false otherwiswe (and q is not valid)
algoritmo:
1) si calcola la proiezione <p> 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
Note sulla robustezza: This wrapper requires that your face has
il calcolo del prodotto vettore e` la cosa piu` delicata: - Per Face Flags well initialized
possibili fallimenti quando a^b ~= 0 - Per Face EdgePlane component initialized.
1) doveva essere <= 0 e viene positivo (q era fuori o sulla linea dell'edge) Initialization must be done with:
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)
tri::UpdateEdges<MeshType>::Set(yourMesh);
*/ */
template <class FaceType> template <class FaceType>
bool PointDistance( const FaceType &f, bool PointDistanceEP( const FaceType &f,
const vcg::Point3<typename FaceType::ScalarType> & q, const vcg::Point3<typename FaceType::ScalarType> & q,
typename FaceType::ScalarType & dist, typename FaceType::ScalarType & dist,
vcg::Point3<typename FaceType::ScalarType> & p ) vcg::Point3<typename FaceType::ScalarType> & p )
{ {
typedef typename FaceType::ScalarType ScalarType; typedef typename FaceType::ScalarType ScalarType;
const ScalarType EPS = ScalarType( 0.000001); const ScalarType EPS = ScalarType( 0.000001);
//const ScalarType EPSILON = 0.00000001;
ScalarType b,b0,b1,b2; 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 ScalarType d = SignedDistancePlanePoint( f.cPlane(), q );
// NOTA: aggiunto un '-d' in fondo Paolo C. if( d>dist || d<-dist ) return false;
Point3<ScalarType> t = f.cPlane().Direction(); Point3<ScalarType> t = f.cPlane().Direction();
t[0] *= -d; p = q - t*d; // p is the projection of q on the face plane
t[1] *= -d; // Now Choose the best plane and test to see if p is inside the triangle
t[2] *= -d;
p = q; p += t;
switch( f.Flags() & (FaceType::NORMX|FaceType::NORMY|FaceType::NORMZ) ) switch( f.Flags() & (FaceType::NORMX|FaceType::NORMY|FaceType::NORMZ) )
{ {
@ -141,13 +87,8 @@ namespace vcg {
if(dist>b2) { dist = b2; return true; } if(dist>b2) { dist = b2; return true; }
else return false; else return false;
} }
// sono tutti e tre > 0 quindi dovrebbe essere dentro; // if all these tests failed the projection p should be inside.
// per sicurezza se il piu' piccolo dei tre e' < epsilon (scalato rispetto all'area della faccia // Some further tests for more robustness...
// 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)) if( (b=std::min(b0,std::min(b1,b2)) ) < EPS*DoubleArea(f))
{ {
ScalarType bt; ScalarType bt;
@ -156,7 +97,6 @@ namespace vcg {
else { assert(b==b2); else { assert(b==b2);
bt = PSDist(q,f.V(0)->cP(),f.V(1)->cP(),p); 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; } if(dist>bt) { dist = bt; return true; }
else return false; else return false;
} }
@ -192,7 +132,6 @@ namespace vcg {
else { assert(b==b2); else { assert(b==b2);
bt = PSDist(q,f.V(0)->cP(),f.V(1)->cP(),p); 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(dist>bt) { dist = bt; return true; }
else return false; else return false;
} }
@ -228,22 +167,20 @@ namespace vcg {
else { assert(b==b2); else { assert(b==b2);
bt = PSDist(q,f.V(0)->cP(),f.V(1)->cP(),p); 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(dist>bt) { dist = bt; return true; }
else return false; else return false;
} }
break; break;
} } // end switch
dist = ScalarType(fabs(d)); dist = ScalarType(fabs(d));
//dist = Distance(p,q);
return true; return true;
} }
template <class S> template <class S>
class PointDistanceFunctor { class PointDistanceEPFunctor {
public: public:
typedef S ScalarType; typedef S ScalarType;
typedef Point3<ScalarType> QueryType; typedef Point3<ScalarType> QueryType;
@ -254,7 +191,7 @@ namespace vcg {
const Point3<typename FACETYPE::ScalarType> fp = Point3<typename FACETYPE::ScalarType>::Construct(p); const Point3<typename FACETYPE::ScalarType> fp = Point3<typename FACETYPE::ScalarType>::Construct(p);
Point3<typename FACETYPE::ScalarType> fq; Point3<typename FACETYPE::ScalarType> fq;
typename FACETYPE::ScalarType md = (typename FACETYPE::ScalarType)(minDist); 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); minDist = (SCALARTYPE)(md);
q = Point3<SCALARTYPE>::Construct(fq); q = Point3<SCALARTYPE>::Construct(fq);
return (ret); return (ret);
@ -301,8 +238,6 @@ namespace vcg {
/// BASIC VERSION of the Point-face distance that does not require the EdgePlane Additional data. /// 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. /// 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 <class FaceType> template <class FaceType>
bool PointDistanceBase( bool PointDistanceBase(
@ -312,12 +247,6 @@ namespace vcg {
vcg::Point3<typename FaceType::ScalarType> & p ) vcg::Point3<typename FaceType::ScalarType> & p )
{ {
typedef typename FaceType::ScalarType ScalarType; 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<ScalarType>(0,0,0)) // to correctly manage the case of degenerate triangles we consider them as segments. if(f.cN()==Point3<ScalarType>(0,0,0)) // to correctly manage the case of degenerate triangles we consider them as segments.
{ {
@ -340,7 +269,7 @@ namespace vcg {
return true; return true;
} }
Plane3<ScalarType> fPlane; Plane3<ScalarType,true> fPlane;
fPlane.Init(f.cP(0),f.cN()); fPlane.Init(f.cP(0),f.cN());
const ScalarType EPS = ScalarType( 0.000001); const ScalarType EPS = ScalarType( 0.000001);
ScalarType b,b0,b1,b2; ScalarType b,b0,b1,b2;
@ -349,13 +278,8 @@ namespace vcg {
if( d>dist || d<-dist ) // Risultato peggiore: niente di fatto if( d>dist || d<-dist ) // Risultato peggiore: niente di fatto
return false; return false;
// Calcolo del punto sul piano // Projection of query point onto the triangle plane
// NOTA: aggiunto un '-d' in fondo Paolo C. p = q - fPlane.Direction()*d;
Point3<ScalarType> t = fPlane.Direction();
t[0] *= -d;
t[1] *= -d;
t[2] *= -d;
p = q; p += t;
Point3<ScalarType> fEdge[3]; Point3<ScalarType> fEdge[3];
fEdge[0] = f.cP(1); fEdge[0] -= f.cP(0); fEdge[0] = f.cP(1); fEdge[0] -= f.cP(0);