2004-05-12 20:50:25 +02:00
/****************************************************************************
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
* Copyright ( C ) 2004 \ / ) \ / *
* Visual Computing Lab / \ / | *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved . *
* *
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* *
* This program is distributed in the hope that it will be useful , *
* but WITHOUT ANY WARRANTY ; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the *
* GNU General Public License ( http : //www.gnu.org/licenses/gpl.txt) *
* for more details . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/****************************************************************************
History
$ Log : not supported by cvs2svn $
2007-05-04 18:44:06 +02:00
Revision 1.10 2006 / 01 / 22 10 : 06 : 23 cignoni
Corrected use of Area with the unambiguous DoubleArea
2006-01-22 11:06:23 +01:00
Revision 1.9 2005 / 09 / 28 19 : 35 : 06 m_di_benedetto
Added class PointDistanceFunctor .
2005-09-28 21:35:06 +02:00
Revision 1.8 2005 / 09 / 14 12 : 58 : 44 pietroni
changed min calls to Min < ScalarType > of math . h of vcglib
2005-09-14 14:58:44 +02:00
Revision 1.7 2005 / 09 / 14 09 : 58 : 32 pietroni
removed vcg : : math : : Min < ScalarType > definition generate warnings
2005-09-14 11:58:32 +02:00
Revision 1.6 2005 / 09 / 14 09 : 03 : 54 pietroni
2005-09-14 14:58:44 +02:00
added definition of vcg : : math : : Min < ScalarType > function
2005-09-14 11:58:32 +02:00
2005-09-14 11:03:54 +02:00
Revision 1.5 2005 / 02 / 02 16 : 44 : 34 pietroni
1 warning corrected added casting in const ScalarType EPSILON = ScalarType ( 0.000001 ) ;
2005-02-02 17:44:34 +01:00
Revision 1.4 2005 / 01 / 28 12 : 00 : 33 cignoni
small gcc compiling issues for namespaces
2005-01-28 13:00:33 +01:00
Revision 1.3 2005 / 01 / 24 15 : 35 : 25 cignoni
Removed a ' using namespace '
2005-01-24 16:35:25 +01:00
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
2005-01-21 18:11:03 +01:00
Revision 1.1 2004 / 05 / 12 18 : 50 : 25 ganovelli
created
2004-05-12 20:50:25 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifndef __VCGLIB_FACE_DISTANCE
# define __VCGLIB_FACE_DISTANCE
2005-09-14 14:58:44 +02:00
# include <vcg/math/base.h>
2004-05-12 20:50:25 +02:00
# include <vcg/space/point3.h>
2010-03-03 01:35:20 +01:00
# include <vcg/space/segment3.h>
2010-10-15 17:19:12 +02:00
# include <vcg/space/distance3.h>
2005-01-21 18:11:03 +01:00
2004-05-12 20:50:25 +02:00
namespace vcg {
2005-01-21 18:11:03 +01:00
namespace face {
2004-05-12 20:50:25 +02:00
/*
Point face distance
2008-09-24 11:15:38 +02:00
trova il punto < p > sulla faccia piu ' vicino a < q > , con possibilit <EFBFBD> di
rejection veloce su se la distanza trovata <EFBFBD> maggiore di < rejdist >
2004-05-12 20:50:25 +02:00
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 < 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 :
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 )
*/
template < class FaceType >
2005-01-21 18:11:03 +01:00
bool PointDistance ( const FaceType & f ,
2005-01-28 13:00:33 +01:00
const vcg : : Point3 < typename FaceType : : ScalarType > & q ,
2004-05-12 20:50:25 +02:00
typename FaceType : : ScalarType & dist ,
2005-01-28 13:00:33 +01:00
vcg : : Point3 < typename FaceType : : ScalarType > & p )
2004-05-12 20:50:25 +02:00
{
typedef typename FaceType : : ScalarType ScalarType ;
2005-09-14 14:58:44 +02:00
2009-07-15 18:25:25 +02:00
const ScalarType EPS = ScalarType ( 0.000001 ) ;
//const ScalarType EPSILON = 0.00000001;
2004-05-12 20:50:25 +02:00
ScalarType b , b0 , b1 , b2 ;
// Calcolo distanza punto piano
2012-01-23 07:47:31 +01:00
ScalarType d = SignedDistancePlanePoint ( f . cPlane ( ) , q ) ;
2004-05-12 20:50:25 +02:00
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.
2007-05-04 18:44:06 +02:00
Point3 < ScalarType > t = f . cPlane ( ) . Direction ( ) ;
2004-05-12 20:50:25 +02:00
t [ 0 ] * = - d ;
t [ 1 ] * = - d ;
t [ 2 ] * = - d ;
p = q ; p + = t ;
switch ( f . Flags ( ) & ( FaceType : : NORMX | FaceType : : NORMY | FaceType : : NORMZ ) )
{
case FaceType : : NORMX :
2007-05-04 18:44:06 +02:00
b0 = f . cEdge ( 1 ) [ 1 ] * ( p [ 2 ] - f . cP ( 1 ) [ 2 ] ) - f . cEdge ( 1 ) [ 2 ] * ( p [ 1 ] - f . cP ( 1 ) [ 1 ] ) ;
2004-05-12 20:50:25 +02:00
if ( b0 < = 0 )
{
b0 = PSDist ( q , f . V ( 1 ) - > cP ( ) , f . V ( 2 ) - > cP ( ) , p ) ;
if ( dist > b0 ) { dist = b0 ; return true ; }
else return false ;
}
2007-05-04 18:44:06 +02:00
b1 = f . cEdge ( 2 ) [ 1 ] * ( p [ 2 ] - f . cP ( 2 ) [ 2 ] ) - f . cEdge ( 2 ) [ 2 ] * ( p [ 1 ] - f . cP ( 2 ) [ 1 ] ) ;
2004-05-12 20:50:25 +02:00
if ( b1 < = 0 )
{
b1 = PSDist ( q , f . V ( 2 ) - > cP ( ) , f . V ( 0 ) - > cP ( ) , p ) ;
if ( dist > b1 ) { dist = b1 ; return true ; }
else return false ;
}
2007-05-04 18:44:06 +02:00
b2 = f . cEdge ( 0 ) [ 1 ] * ( p [ 2 ] - f . cP ( 0 ) [ 2 ] ) - f . cEdge ( 0 ) [ 2 ] * ( p [ 1 ] - f . cP ( 0 ) [ 1 ] ) ;
2004-05-12 20:50:25 +02:00
if ( b2 < = 0 )
{
b2 = PSDist ( q , f . V ( 0 ) - > cP ( ) , f . V ( 1 ) - > cP ( ) , p ) ;
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.
2010-07-14 10:09:28 +02:00
if ( ( b = std : : min ( b0 , std : : min ( b1 , b2 ) ) ) < EPS * DoubleArea ( f ) )
2004-05-12 20:50:25 +02:00
{
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 ) ;
2010-07-14 10:09:28 +02:00
else { assert ( b = = b2 ) ;
bt = PSDist ( q , f . V ( 0 ) - > cP ( ) , f . V ( 1 ) - > cP ( ) , p ) ;
}
2009-07-15 18:25:25 +02:00
//printf("Warning area:%g %g %g %g thr:%g bt:%g\n",Area(), b0,b1,b2,EPS*Area(),bt);
2004-05-12 20:50:25 +02:00
if ( dist > bt ) { dist = bt ; return true ; }
else return false ;
}
break ;
case FaceType : : NORMY :
2007-05-04 18:44:06 +02:00
b0 = f . cEdge ( 1 ) [ 2 ] * ( p [ 0 ] - f . cP ( 1 ) [ 0 ] ) - f . cEdge ( 1 ) [ 0 ] * ( p [ 2 ] - f . cP ( 1 ) [ 2 ] ) ;
2004-05-12 20:50:25 +02:00
if ( b0 < = 0 )
{
b0 = PSDist ( q , f . V ( 1 ) - > cP ( ) , f . V ( 2 ) - > cP ( ) , p ) ;
if ( dist > b0 ) { dist = b0 ; return true ; }
else return false ;
}
2007-05-04 18:44:06 +02:00
b1 = f . cEdge ( 2 ) [ 2 ] * ( p [ 0 ] - f . cP ( 2 ) [ 0 ] ) - f . cEdge ( 2 ) [ 0 ] * ( p [ 2 ] - f . cP ( 2 ) [ 2 ] ) ;
2004-05-12 20:50:25 +02:00
if ( b1 < = 0 )
{
b1 = PSDist ( q , f . V ( 2 ) - > cP ( ) , f . V ( 0 ) - > cP ( ) , p ) ;
if ( dist > b1 ) { dist = b1 ; return true ; }
else return false ;
}
2007-05-04 18:44:06 +02:00
b2 = f . cEdge ( 0 ) [ 2 ] * ( p [ 0 ] - f . cP ( 0 ) [ 0 ] ) - f . cEdge ( 0 ) [ 0 ] * ( p [ 2 ] - f . cP ( 0 ) [ 2 ] ) ;
2004-05-12 20:50:25 +02:00
if ( b2 < = 0 )
{
b2 = PSDist ( q , f . V ( 0 ) - > cP ( ) , f . V ( 1 ) - > cP ( ) , p ) ;
if ( dist > b2 ) { dist = b2 ; return true ; }
else return false ;
}
2010-09-22 00:09:13 +02:00
if ( ( b = math : : Min < ScalarType > ( b0 , b1 , b2 ) ) < EPS * DoubleArea ( f ) )
2004-05-12 20:50:25 +02:00
{
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 ) ;
2010-07-14 10:09:28 +02:00
else { assert ( b = = b2 ) ;
bt = PSDist ( q , f . V ( 0 ) - > cP ( ) , f . V ( 1 ) - > cP ( ) , p ) ;
}
2004-05-12 20:50:25 +02:00
//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 ; }
else return false ;
}
break ;
case FaceType : : NORMZ :
2007-05-04 18:44:06 +02:00
b0 = f . cEdge ( 1 ) [ 0 ] * ( p [ 1 ] - f . cP ( 1 ) [ 1 ] ) - f . cEdge ( 1 ) [ 1 ] * ( p [ 0 ] - f . cP ( 1 ) [ 0 ] ) ;
2004-05-12 20:50:25 +02:00
if ( b0 < = 0 )
{
b0 = PSDist ( q , f . V ( 1 ) - > cP ( ) , f . V ( 2 ) - > cP ( ) , p ) ;
if ( dist > b0 ) { dist = b0 ; return true ; }
else return false ;
}
2007-05-04 18:44:06 +02:00
b1 = f . cEdge ( 2 ) [ 0 ] * ( p [ 1 ] - f . cP ( 2 ) [ 1 ] ) - f . cEdge ( 2 ) [ 1 ] * ( p [ 0 ] - f . cP ( 2 ) [ 0 ] ) ;
2004-05-12 20:50:25 +02:00
if ( b1 < = 0 )
{
b1 = PSDist ( q , f . V ( 2 ) - > cP ( ) , f . V ( 0 ) - > cP ( ) , p ) ;
if ( dist > b1 ) { dist = b1 ; return true ; }
else return false ;
}
2007-05-04 18:44:06 +02:00
b2 = f . cEdge ( 0 ) [ 0 ] * ( p [ 1 ] - f . cP ( 0 ) [ 1 ] ) - f . cEdge ( 0 ) [ 1 ] * ( p [ 0 ] - f . cP ( 0 ) [ 0 ] ) ;
2004-05-12 20:50:25 +02:00
if ( b2 < = 0 )
{
b2 = PSDist ( q , f . V ( 0 ) - > cP ( ) , f . V ( 1 ) - > cP ( ) , p ) ;
if ( dist > b2 ) { dist = b2 ; return true ; }
else return false ;
}
2010-09-22 00:09:13 +02:00
if ( ( b = math : : Min < ScalarType > ( b0 , b1 , b2 ) ) < EPS * DoubleArea ( f ) )
2004-05-12 20:50:25 +02:00
{
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 ) ;
2010-07-14 10:09:28 +02:00
else { assert ( b = = b2 ) ;
bt = PSDist ( q , f . V ( 0 ) - > cP ( ) , f . V ( 1 ) - > cP ( ) , p ) ;
}
2004-05-12 20:50:25 +02:00
//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 ; }
else return false ;
}
break ;
}
dist = ScalarType ( fabs ( d ) ) ;
//dist = Distance(p,q);
return true ;
}
2005-09-28 21:35:06 +02:00
2008-09-24 10:41:04 +02:00
template < class S >
2005-09-28 21:35:06 +02:00
class PointDistanceFunctor {
public :
2008-09-24 11:15:38 +02:00
typedef S ScalarType ;
typedef Point3 < ScalarType > QueryType ;
2008-09-24 10:41:04 +02:00
static inline const Point3 < ScalarType > & Pos ( const QueryType & qt ) { return qt ; }
2005-09-28 21:35:06 +02:00
template < class FACETYPE , class SCALARTYPE >
inline bool operator ( ) ( const FACETYPE & f , const Point3 < SCALARTYPE > & p , SCALARTYPE & minDist , Point3 < SCALARTYPE > & q ) {
const Point3 < typename FACETYPE : : ScalarType > fp = Point3 < typename FACETYPE : : ScalarType > : : Construct ( p ) ;
Point3 < typename FACETYPE : : ScalarType > fq ;
typename FACETYPE : : ScalarType md = ( typename FACETYPE : : ScalarType ) ( minDist ) ;
const bool ret = PointDistance ( f , fp , md , fq ) ;
minDist = ( SCALARTYPE ) ( md ) ;
q = Point3 < SCALARTYPE > : : Construct ( fq ) ;
return ( ret ) ;
}
} ;
2009-05-23 22:12:58 +02:00
template < class S >
class PointNormalDistanceFunctor {
public :
typedef typename S : : ScalarType ScalarType ;
typedef S QueryType ;
static inline const Point3 < ScalarType > & Pos ( const QueryType & qt ) { return qt . P ( ) ; }
static ScalarType & Alpha ( ) { static ScalarType alpha = 1.0 ; return alpha ; }
static ScalarType & Beta ( ) { static ScalarType beta = 1.0 ; return beta ; }
static ScalarType & Gamma ( ) { static ScalarType gamma = 1.0 ; return gamma ; }
static ScalarType & InterPoint ( ) { static ScalarType interpoint = 1.0 ; return interpoint ; }
template < class FACETYPE , class SCALARTYPE >
inline bool operator ( ) ( const FACETYPE & f , const typename FACETYPE : : VertexType & p ,
SCALARTYPE & minDist , Point3 < SCALARTYPE > & q )
{
const Point3 < typename FACETYPE : : ScalarType > fp = Point3 < typename FACETYPE : : ScalarType > : : Construct ( p . cP ( ) ) ;
const Point3 < typename FACETYPE : : ScalarType > fn = Point3 < typename FACETYPE : : ScalarType > : : Construct ( p . cN ( ) ) ;
Point3 < typename FACETYPE : : ScalarType > fq ;
typename FACETYPE : : ScalarType md = ( typename FACETYPE : : ScalarType ) ( minDist ) ;
const bool ret = PointDistance ( f , fp , md , fq ) ;
SCALARTYPE dev = InterPoint ( ) * ( pow ( ( ScalarType ) ( 1 - f . cN ( ) . dot ( fn ) ) , ( ScalarType ) Beta ( ) ) / ( Gamma ( ) * md + 0.1 ) ) ;
if ( md + dev < minDist ) {
minDist = ( SCALARTYPE ) ( md + dev ) ;
q = Point3 < SCALARTYPE > : : Construct ( fq ) ;
//q.N() = f.N();
return ( ret ) ;
}
return false ;
}
} ;
2008-06-04 15:27:10 +02:00
/// 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.
2011-11-21 09:56:52 +01:00
/// it assumes that the face has Normalized Normal.
2008-06-04 15:27:10 +02:00
// UpdateNormals::PerFaceNormalized(m)
template < class FaceType >
bool PointDistanceBase (
const FaceType & f , /// the face to be tested
const vcg : : Point3 < typename FaceType : : ScalarType > & q , /// the point tested
typename FaceType : : ScalarType & dist , /// bailout distance. It must be initialized with the max admittable value.
vcg : : Point3 < typename FaceType : : ScalarType > & p )
{
typedef typename FaceType : : ScalarType ScalarType ;
2009-04-19 23:20:08 +02:00
// 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 )
2010-03-03 01:35:20 +01:00
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
2012-03-14 16:59:42 +01:00
if ( f . cN ( ) = = Point3 < ScalarType > ( 0 , 0 , 0 ) ) // to correctly manage the case of degenerate triangles we consider them as segments.
{
Box3 < ScalarType > bb ;
f . GetBBox ( bb ) ;
Segment3 < ScalarType > degenTri ( bb . min , bb . max ) ;
Point3 < ScalarType > closest ;
ScalarType d ;
if ( bb . Diag ( ) > 0 )
vcg : : SegmentPointDistance < ScalarType > ( degenTri , q , closest , d ) ;
else // very degenerate triangle (just a point)
{
closest = bb . min ;
d = Distance ( q , closest ) ;
}
if ( d > dist ) return false ;
dist = d ;
p = closest ;
assert ( ! math : : IsNAN ( dist ) ) ;
return true ;
}
2009-04-19 23:20:08 +02:00
2008-06-04 15:27:10 +02:00
Plane3 < ScalarType > fPlane ;
fPlane . Init ( f . cP ( 0 ) , f . cN ( ) ) ;
2010-03-03 01:35:20 +01:00
const ScalarType EPS = ScalarType ( 0.000001 ) ;
2008-06-04 15:27:10 +02:00
ScalarType b , b0 , b1 , b2 ;
// Calcolo distanza punto piano
2012-01-18 12:44:42 +01:00
ScalarType d = SignedDistancePlanePoint ( fPlane , q ) ;
2008-06-04 15:27:10 +02:00
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 < ScalarType > t = fPlane . Direction ( ) ;
t [ 0 ] * = - d ;
t [ 1 ] * = - d ;
t [ 2 ] * = - d ;
p = q ; p + = t ;
Point3 < ScalarType > fEdge [ 3 ] ;
fEdge [ 0 ] = f . cP ( 1 ) ; fEdge [ 0 ] - = f . cP ( 0 ) ;
fEdge [ 1 ] = f . cP ( 2 ) ; fEdge [ 1 ] - = f . cP ( 1 ) ;
fEdge [ 2 ] = f . cP ( 0 ) ; fEdge [ 2 ] - = f . cP ( 2 ) ;
/*
This piece of code is part of the EdgePlane initialization structure : note that the edges are scaled ! .
if ( nx > ny & & nx > nz ) { f . Flags ( ) | = FaceType : : NORMX ; d = 1 / f . Plane ( ) . Direction ( ) [ 0 ] ; }
else if ( ny > nz ) { f . Flags ( ) | = FaceType : : NORMY ; d = 1 / f . Plane ( ) . Direction ( ) [ 1 ] ; }
else { f . Flags ( ) | = FaceType : : NORMZ ; d = 1 / f . Plane ( ) . Direction ( ) [ 2 ] ; }
f . Edge ( 0 ) * = d ; f . Edge ( 1 ) * = d ; f . Edge ( 2 ) * = d ;
So we must apply the same scaling according to the plane orientation , eg in the case of NORMX
2011-11-21 09:56:52 +01:00
scaleFactor = 1 / fPlane . Direction ( ) [ 0 ] ;
fEdge [ 0 ] * = d ; fEdge [ 1 ] * = d ; fEdge [ 2 ] * = d ;
2008-06-04 15:27:10 +02:00
*/
2011-11-21 09:56:52 +01:00
int bestAxis ;
if ( fabs ( f . cN ( ) [ 0 ] ) > fabs ( f . cN ( ) [ 1 ] ) )
{
if ( fabs ( f . cN ( ) [ 0 ] ) > fabs ( f . cN ( ) [ 2 ] ) ) bestAxis = 0 ;
else bestAxis = 2 ;
} else {
if ( fabs ( f . cN ( ) [ 1 ] ) > fabs ( f . cN ( ) [ 2 ] ) ) bestAxis = 1 ; /* 1 > 0 ? 2 */
else bestAxis = 2 ; /* 2 > 1 ? 2 */
}
2008-06-04 15:27:10 +02:00
ScalarType scaleFactor ;
2011-11-21 09:56:52 +01:00
switch ( bestAxis )
2008-06-04 15:27:10 +02:00
{
2011-11-21 09:56:52 +01:00
case 0 : /************* X AXIS **************/
2008-06-04 15:27:10 +02:00
scaleFactor = 1 / fPlane . Direction ( ) [ 0 ] ;
2008-06-13 08:03:27 +02:00
fEdge [ 0 ] * = scaleFactor ; fEdge [ 1 ] * = scaleFactor ; fEdge [ 2 ] * = scaleFactor ;
2008-06-04 15:27:10 +02:00
b0 = fEdge [ 1 ] [ 1 ] * ( p [ 2 ] - f . cP ( 1 ) [ 2 ] ) - fEdge [ 1 ] [ 2 ] * ( p [ 1 ] - f . cP ( 1 ) [ 1 ] ) ;
if ( b0 < = 0 )
{
b0 = PSDist ( q , f . V ( 1 ) - > cP ( ) , f . V ( 2 ) - > cP ( ) , p ) ;
if ( dist > b0 ) { dist = b0 ; return true ; }
else return false ;
}
b1 = fEdge [ 2 ] [ 1 ] * ( p [ 2 ] - f . cP ( 2 ) [ 2 ] ) - fEdge [ 2 ] [ 2 ] * ( p [ 1 ] - f . cP ( 2 ) [ 1 ] ) ;
if ( b1 < = 0 )
{
b1 = PSDist ( q , f . V ( 2 ) - > cP ( ) , f . V ( 0 ) - > cP ( ) , p ) ;
if ( dist > b1 ) { dist = b1 ; return true ; }
else return false ;
}
b2 = fEdge [ 0 ] [ 1 ] * ( p [ 2 ] - f . cP ( 0 ) [ 2 ] ) - fEdge [ 0 ] [ 2 ] * ( p [ 1 ] - f . cP ( 0 ) [ 1 ] ) ;
if ( b2 < = 0 )
{
b2 = PSDist ( q , f . V ( 0 ) - > cP ( ) , f . V ( 1 ) - > cP ( ) , p ) ;
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.
2010-09-22 00:09:13 +02:00
if ( ( b = vcg : : math : : Min < ScalarType > ( b0 , b1 , b2 ) ) < EPS * DoubleArea ( f ) )
2008-06-04 15:27:10 +02:00
{
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 if ( 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 ; }
else return false ;
}
break ;
2011-11-21 09:56:52 +01:00
case 1 : /************* Y AXIS **************/
2008-06-04 15:27:10 +02:00
scaleFactor = 1 / fPlane . Direction ( ) [ 1 ] ;
2008-06-13 08:03:27 +02:00
fEdge [ 0 ] * = scaleFactor ; fEdge [ 1 ] * = scaleFactor ; fEdge [ 2 ] * = scaleFactor ;
2008-06-04 15:27:10 +02:00
b0 = fEdge [ 1 ] [ 2 ] * ( p [ 0 ] - f . cP ( 1 ) [ 0 ] ) - fEdge [ 1 ] [ 0 ] * ( p [ 2 ] - f . cP ( 1 ) [ 2 ] ) ;
if ( b0 < = 0 )
{
b0 = PSDist ( q , f . V ( 1 ) - > cP ( ) , f . V ( 2 ) - > cP ( ) , p ) ;
if ( dist > b0 ) { dist = b0 ; return true ; }
else return false ;
}
b1 = fEdge [ 2 ] [ 2 ] * ( p [ 0 ] - f . cP ( 2 ) [ 0 ] ) - fEdge [ 2 ] [ 0 ] * ( p [ 2 ] - f . cP ( 2 ) [ 2 ] ) ;
if ( b1 < = 0 )
{
b1 = PSDist ( q , f . V ( 2 ) - > cP ( ) , f . V ( 0 ) - > cP ( ) , p ) ;
if ( dist > b1 ) { dist = b1 ; return true ; }
else return false ;
}
b2 = fEdge [ 0 ] [ 2 ] * ( p [ 0 ] - f . cP ( 0 ) [ 0 ] ) - fEdge [ 0 ] [ 0 ] * ( p [ 2 ] - f . cP ( 0 ) [ 2 ] ) ;
if ( b2 < = 0 )
{
b2 = PSDist ( q , f . V ( 0 ) - > cP ( ) , f . V ( 1 ) - > cP ( ) , p ) ;
if ( dist > b2 ) { dist = b2 ; return true ; }
else return false ;
}
2010-09-22 00:09:13 +02:00
if ( ( b = vcg : : math : : Min < ScalarType > ( b0 , b1 , b2 ) ) < EPS * DoubleArea ( f ) )
2008-06-04 15:27:10 +02:00
{
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 if ( 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 ; }
else return false ;
}
break ;
2011-11-21 09:56:52 +01:00
case 2 : /************* Z AXIS **************/
2008-06-04 15:27:10 +02:00
scaleFactor = 1 / fPlane . Direction ( ) [ 2 ] ;
2008-06-13 08:03:27 +02:00
fEdge [ 0 ] * = scaleFactor ; fEdge [ 1 ] * = scaleFactor ; fEdge [ 2 ] * = scaleFactor ;
2008-06-04 15:27:10 +02:00
b0 = fEdge [ 1 ] [ 0 ] * ( p [ 1 ] - f . cP ( 1 ) [ 1 ] ) - fEdge [ 1 ] [ 1 ] * ( p [ 0 ] - f . cP ( 1 ) [ 0 ] ) ;
if ( b0 < = 0 )
{
b0 = PSDist ( q , f . V ( 1 ) - > cP ( ) , f . V ( 2 ) - > cP ( ) , p ) ;
if ( dist > b0 ) { dist = b0 ; return true ; }
else return false ;
}
b1 = fEdge [ 2 ] [ 0 ] * ( p [ 1 ] - f . cP ( 2 ) [ 1 ] ) - fEdge [ 2 ] [ 1 ] * ( p [ 0 ] - f . cP ( 2 ) [ 0 ] ) ;
if ( b1 < = 0 )
{
b1 = PSDist ( q , f . V ( 2 ) - > cP ( ) , f . V ( 0 ) - > cP ( ) , p ) ;
if ( dist > b1 ) { dist = b1 ; return true ; }
else return false ;
}
b2 = fEdge [ 0 ] [ 0 ] * ( p [ 1 ] - f . cP ( 0 ) [ 1 ] ) - fEdge [ 0 ] [ 1 ] * ( p [ 0 ] - f . cP ( 0 ) [ 0 ] ) ;
if ( b2 < = 0 )
{
b2 = PSDist ( q , f . V ( 0 ) - > cP ( ) , f . V ( 1 ) - > cP ( ) , p ) ;
if ( dist > b2 ) { dist = b2 ; return true ; }
else return false ;
}
2010-09-22 00:09:13 +02:00
if ( ( b = vcg : : math : : Min < ScalarType > ( b0 , b1 , b2 ) ) < EPS * DoubleArea ( f ) )
2008-06-04 15:27:10 +02:00
{
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 if ( 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 ; }
else return false ;
}
break ;
2009-04-19 23:20:08 +02:00
default : assert ( 0 ) ; // if you get this assert it means that you forgot to set the required UpdateFlags<MeshType>::FaceProjection(m);
2008-06-04 15:27:10 +02:00
}
dist = ScalarType ( fabs ( d ) ) ;
//dist = Distance(p,q);
return true ;
}
2008-09-24 10:41:04 +02:00
template < class S >
class PointDistanceBaseFunctor {
2008-06-04 15:27:10 +02:00
public :
2008-09-24 11:15:38 +02:00
typedef S ScalarType ;
2008-09-24 10:41:04 +02:00
typedef Point3 < ScalarType > QueryType ;
static inline const Point3 < ScalarType > & Pos ( const Point3 < ScalarType > & qt ) { return qt ; }
2008-06-04 15:27:10 +02:00
template < class FACETYPE , class SCALARTYPE >
inline bool operator ( ) ( const FACETYPE & f , const Point3 < SCALARTYPE > & p , SCALARTYPE & minDist , Point3 < SCALARTYPE > & q ) {
const Point3 < typename FACETYPE : : ScalarType > fp = Point3 < typename FACETYPE : : ScalarType > : : Construct ( p ) ;
Point3 < typename FACETYPE : : ScalarType > fq ;
typename FACETYPE : : ScalarType md = ( typename FACETYPE : : ScalarType ) ( minDist ) ;
const bool ret = PointDistanceBase ( f , fp , md , fq ) ;
minDist = ( SCALARTYPE ) ( md ) ;
q = Point3 < SCALARTYPE > : : Construct ( fq ) ;
return ( ret ) ;
}
} ;
2005-01-21 18:11:03 +01:00
} // end namespace face
2004-05-12 20:50:25 +02:00
} // end namespace vcg
# endif