CRITICAL CHANGE: the commonly used function Normal() used to compute the normal of a triangle has been changed into TriangleNormal()

This commit is contained in:
Paolo Cignoni 2014-11-12 00:04:26 +00:00
parent 3bc278c224
commit 16f4795588
1 changed files with 74 additions and 88 deletions

View File

@ -8,7 +8,7 @@
* \ *
* All rights reserved. *
* *
* This program is free software; you can redistribute it and/or modify *
* 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. *
@ -35,27 +35,27 @@ namespace vcg {
/** \addtogroup space */
/*@{*/
/**
Templated class for storing a generic triangle in a 3D space.
/**
Templated class for storing a generic triangle in a 3D space.
Note the relation with the Face class of TriMesh complex, both classes provide the P(i) access functions to their points and therefore they share the algorithms on it (e.g. area, normal etc...)
*/
template <class ScalarTriangleType> class Triangle3
{
public:
typedef ScalarTriangleType ScalarType;
typedef Point3< ScalarType > CoordType;
/// The bounding box type
typedef Box3<ScalarType> BoxType;
typedef Point3< ScalarType > CoordType;
/// The bounding box type
typedef Box3<ScalarType> BoxType;
/*********************************************
blah
blah
**/
Triangle3(){}
Triangle3(const CoordType & c0,const CoordType & c1,const CoordType & c2){_v[0]=c0;_v[1]=c1;_v[2]=c2;}
Triangle3(){}
Triangle3(const CoordType & c0,const CoordType & c1,const CoordType & c2){_v[0]=c0;_v[1]=c1;_v[2]=c2;}
protected:
/// Vector of vertex pointer incident in the face
Point3<ScalarType> _v[3];
/// Vector of vertex pointer incident in the face
Point3<ScalarType> _v[3];
public:
/// Shortcut per accedere ai punti delle facce
@ -79,7 +79,7 @@ public:
/// Returns the normal to the plane passing through p0,p1,p2
template<class TriangleType>
Point3<typename TriangleType::ScalarType> Normal(const TriangleType &t)
Point3<typename TriangleType::ScalarType> TriangleNormal(const TriangleType &t)
{
return (( t.cP(1) - t.cP(0)) ^ (t.cP(2) - t.cP(0)));
}
@ -89,24 +89,10 @@ Point3Type Normal( Point3Type const &p0, Point3Type const & p1, Point3Type cons
return (( p1 - p0) ^ (p2 - p0));
}
/// Like the above, it returns the normal to the plane passing through p0,p1,p2, but normalized.
template<class TriangleType>
typename TriangleType::CoordType NormalizedNormal(const TriangleType &t)
{
return (( t.cP(1) - t.cP(0)) ^ (t.cP(2) - t.cP(0))).Normalize();
}
template<class Point3Type>
Point3Type NormalizedNormal( Point3Type const &p0, Point3Type const & p1, Point3Type const & p2)
{
return (( p1 - p0) ^ (p2 - p0)).Normalize();
}
/********************** Interpolation **********************/
// The function to computing barycentric coords of a point inside a triangle.
// it requires the knowledge of what is the direction that is more orthogonal to the face plane.
// it requires the knowledge of what is the direction that is more orthogonal to the face plane.
// ScalarType nx = math::Abs((*fi).cN()[0]);
// ScalarType ny = math::Abs((*fi).cN()[1]);
// ScalarType nz = math::Abs((*fi).cN()[2]);
@ -120,41 +106,41 @@ Point3Type NormalizedNormal( Point3Type const &p0, Point3Type const & p1, Point
template<class TriangleType, class ScalarType>
bool InterpolationParameters(const TriangleType t, const int Axis, const Point3<ScalarType> & P, Point3<ScalarType> & L)
{
typedef Point2<ScalarType> P2;
if(Axis==0) return InterpolationParameters2( P2(t.cP(0)[1],t.cP(0)[2]), P2(t.cP(1)[1],t.cP(1)[2]), P2(t.cP(2)[1],t.cP(2)[2]), P2(P[1],P[2]), L);
if(Axis==1) return InterpolationParameters2( P2(t.cP(0)[0],t.cP(0)[2]), P2(t.cP(1)[0],t.cP(1)[2]), P2(t.cP(2)[0],t.cP(2)[2]), P2(P[0],P[2]), L);
if(Axis==2) return InterpolationParameters2( P2(t.cP(0)[0],t.cP(0)[1]), P2(t.cP(1)[0],t.cP(1)[1]), P2(t.cP(2)[0],t.cP(2)[1]), P2(P[0],P[1]), L);
return false;
typedef Point2<ScalarType> P2;
if(Axis==0) return InterpolationParameters2( P2(t.cP(0)[1],t.cP(0)[2]), P2(t.cP(1)[1],t.cP(1)[2]), P2(t.cP(2)[1],t.cP(2)[2]), P2(P[1],P[2]), L);
if(Axis==1) return InterpolationParameters2( P2(t.cP(0)[0],t.cP(0)[2]), P2(t.cP(1)[0],t.cP(1)[2]), P2(t.cP(2)[0],t.cP(2)[2]), P2(P[0],P[2]), L);
if(Axis==2) return InterpolationParameters2( P2(t.cP(0)[0],t.cP(0)[1]), P2(t.cP(1)[0],t.cP(1)[1]), P2(t.cP(2)[0],t.cP(2)[1]), P2(P[0],P[1]), L);
return false;
}
/// Handy Wrapper of the above one that uses the passed normal N to choose the right orientation
template<class TriangleType, class ScalarType>
bool InterpolationParameters(const TriangleType t, const Point3<ScalarType> & N, const Point3<ScalarType> & P, Point3<ScalarType> & L)
{
if(fabs(N[0])>fabs(N[1]))
{
{
if(fabs(N[0])>fabs(N[2]))
return InterpolationParameters(t,0,P,L); /* 0 > 1 ? 2 */
else
return InterpolationParameters(t,2,P,L); /* 2 > 1 ? 2 */
}
else
{
return InterpolationParameters(t,0,P,L); /* 0 > 1 ? 2 */
else
return InterpolationParameters(t,2,P,L); /* 2 > 1 ? 2 */
}
else
{
if(fabs(N[1])>fabs(N[2]))
return InterpolationParameters(t,1,P,L); /* 1 > 0 ? 2 */
else
return InterpolationParameters(t,2,P,L); /* 2 > 1 ? 2 */
}
return InterpolationParameters(t,1,P,L); /* 1 > 0 ? 2 */
else
return InterpolationParameters(t,2,P,L); /* 2 > 1 ? 2 */
}
}
// Function that computes the barycentric coords of a 2D triangle.
template<class ScalarType>
bool InterpolationParameters2(const Point2<ScalarType> &V1,
const Point2<ScalarType> &V2,
const Point2<ScalarType> &V3,
const Point2<ScalarType> &P, Point3<ScalarType> &L)
const Point2<ScalarType> &V2,
const Point2<ScalarType> &V3,
const Point2<ScalarType> &P, Point3<ScalarType> &L)
{
vcg::Triangle2<ScalarType> t2=vcg::Triangle2<ScalarType>(V1,V2,V3);
return (t2.InterpolationParameters(P,L.X(),L.Y(),L.Z() ));
vcg::Triangle2<ScalarType> t2=vcg::Triangle2<ScalarType>(V1,V2,V3);
return (t2.InterpolationParameters(P,L.X(),L.Y(),L.Z() ));
}
/// Handy Wrapper of the above one that calculate the normal on the triangle
@ -169,25 +155,25 @@ bool InterpolationParameters(const TriangleType t, const Point3<ScalarType> & P,
/********************** Quality **********************/
/// Compute a shape quality measure of the triangle composed by points p0,p1,p2
/// It Returns 2*AreaTri/(MaxEdge^2),
/// the range is range [0.0, 0.866]
/// It Returns 2*AreaTri/(MaxEdge^2),
/// the range is range [0.0, 0.866]
/// e.g. Equilateral triangle sqrt(3)/2, halfsquare: 1/2, ... up to a line that has zero quality.
template<class P3ScalarType>
P3ScalarType Quality( Point3<P3ScalarType> const &p0, Point3<P3ScalarType> const & p1, Point3<P3ScalarType> const & p2)
{
Point3<P3ScalarType> d10=p1-p0;
Point3<P3ScalarType> d20=p2-p0;
Point3<P3ScalarType> d12=p1-p2;
Point3<P3ScalarType> x = d10^d20;
Point3<P3ScalarType> d10=p1-p0;
Point3<P3ScalarType> d20=p2-p0;
Point3<P3ScalarType> d12=p1-p2;
Point3<P3ScalarType> x = d10^d20;
P3ScalarType a = Norm( x );
if(a==0) return 0; // Area zero triangles have surely quality==0;
P3ScalarType b = SquaredNorm( d10 );
P3ScalarType a = Norm( x );
if(a==0) return 0; // Area zero triangles have surely quality==0;
P3ScalarType b = SquaredNorm( d10 );
if(b==0) return 0; // Again: area zero triangles have surely quality==0;
P3ScalarType t = b;
t = SquaredNorm( d20 ); if ( b<t ) b = t;
t = SquaredNorm( d12 ); if ( b<t ) b = t;
return a/b;
P3ScalarType t = b;
t = SquaredNorm( d20 ); if ( b<t ) b = t;
t = SquaredNorm( d12 ); if ( b<t ) b = t;
return a/b;
}
@ -199,54 +185,54 @@ typename TriangleType::ScalarType QualityFace(const TriangleType &t)
}
/// Compute a shape quality measure of the triangle composed by points p0,p1,p2
/// It Returns inradius/circumradius
/// the range is range [0, 1]
/// the range is range [0, 1]
/// e.g. Equilateral triangle 1, halfsquare: 0.81, ... up to a line that has zero quality.
template<class P3ScalarType>
P3ScalarType QualityRadii(Point3<P3ScalarType> const &p0,
Point3<P3ScalarType> const &p1,
Point3<P3ScalarType> const &p2) {
Point3<P3ScalarType> const &p1,
Point3<P3ScalarType> const &p2) {
P3ScalarType a=(p1-p0).Norm();
P3ScalarType b=(p2-p0).Norm();
P3ScalarType c=(p1-p2).Norm();
P3ScalarType a=(p1-p0).Norm();
P3ScalarType b=(p2-p0).Norm();
P3ScalarType c=(p1-p2).Norm();
P3ScalarType sum = (a + b + c)*0.5;
P3ScalarType area2 = sum*(a+b-sum)*(a+c-sum)*(b+c-sum);
if(area2 <= 0) return 0;
//circumradius: (a*b*c)/(4*sqrt(area2))
//inradius: (a*b*c)/(4*circumradius*sum) => sqrt(area2)/sum;
return (8*area2)/(a*b*c*sum);
P3ScalarType sum = (a + b + c)*0.5;
P3ScalarType area2 = sum*(a+b-sum)*(a+c-sum)*(b+c-sum);
if(area2 <= 0) return 0;
//circumradius: (a*b*c)/(4*sqrt(area2))
//inradius: (a*b*c)/(4*circumradius*sum) => sqrt(area2)/sum;
return (8*area2)/(a*b*c*sum);
}
/// Compute a shape quality measure of the triangle composed by points p0,p1,p2
/// It Returns mean ratio 2sqrt(a, b)/(a+b) where a+b are the eigenvalues of the M^tM of the
/// transformation matrix into a regular simplex
/// the range is range [0, 1]
/// the range is range [0, 1]
template<class P3ScalarType>
P3ScalarType QualityMeanRatio(Point3<P3ScalarType> const &p0,
Point3<P3ScalarType> const &p1,
Point3<P3ScalarType> const &p2) {
Point3<P3ScalarType> const &p1,
Point3<P3ScalarType> const &p2) {
P3ScalarType a=(p1-p0).Norm();
P3ScalarType b=(p2-p0).Norm();
P3ScalarType c=(p1-p2).Norm();
P3ScalarType sum = (a + b + c)*0.5; //semiperimeter
P3ScalarType area2 = sum*(a+b-sum)*(a+c-sum)*(b+c-sum);
if(area2 <= 0) return 0;
return (4.0*sqrt(3.0)*sqrt(area2))/(a*a + b*b + c*c);
P3ScalarType a=(p1-p0).Norm();
P3ScalarType b=(p2-p0).Norm();
P3ScalarType c=(p1-p2).Norm();
P3ScalarType sum = (a + b + c)*0.5; //semiperimeter
P3ScalarType area2 = sum*(a+b-sum)*(a+c-sum)*(b+c-sum);
if(area2 <= 0) return 0;
return (4.0*sqrt(3.0)*sqrt(area2))/(a*a + b*b + c*c);
}
/// Return the Double of area of the triangle
// NOTE the old Area function has been removed to intentionally
// NOTE the old Area function has been removed to intentionally
// cause compiling error that will help people to check their code...
// A some people used Area assuming that it returns the double and some not.
// A some people used Area assuming that it returns the double and some not.
// So please check your codes!!!
// And please DO NOT Insert any Area named function here!
template<class TriangleType>
typename TriangleType::ScalarType DoubleArea(const TriangleType &t)
typename TriangleType::ScalarType DoubleArea(const TriangleType &t)
{
return Norm( (t.cP(1) - t.cP(0)) ^ (t.cP(2) - t.cP(0)) );
}
@ -254,20 +240,20 @@ typename TriangleType::ScalarType DoubleArea(const TriangleType &t)
template<class TriangleType>
typename TriangleType::ScalarType CosWedge(const TriangleType &t, int k)
{
typename TriangleType::CoordType
typename TriangleType::CoordType
e0 = t.cP((k+1)%3) - t.cP(k),
e1 = t.cP((k+2)%3) - t.cP(k);
return (e0*e1)/(e0.Norm()*e1.Norm());
}
template<class TriangleType>
Point3<typename TriangleType::ScalarType> Barycenter(const TriangleType &t)
Point3<typename TriangleType::ScalarType> Barycenter(const TriangleType &t)
{
return ((t.cP(0)+t.cP(1)+t.cP(2))/(typename TriangleType::ScalarType) 3.0);
}
template<class TriangleType>
typename TriangleType::ScalarType Perimeter(const TriangleType &t)
typename TriangleType::ScalarType Perimeter(const TriangleType &t)
{
return Distance(t.cP(0),t.cP(1))+
Distance(t.cP(1),t.cP(2))+