2005-03-14 18:04:24 +01: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 $
|
2005-10-15 14:58:13 +02:00
|
|
|
Revision 1.2 2005/10/13 14:59:57 ganovelli
|
|
|
|
versione con svd
|
|
|
|
|
2005-10-13 16:59:57 +02:00
|
|
|
Revision 1.1 2005/03/14 17:04:24 ganovelli
|
|
|
|
created
|
|
|
|
|
2005-03-14 18:04:24 +01:00
|
|
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#ifndef __VCGLIB_FITTING3
|
|
|
|
#define __VCGLIB_FITTING3
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
#include <vcg/space/plane3.h>
|
2005-10-13 16:59:57 +02:00
|
|
|
#include <vcg/math/matrix44.h>
|
|
|
|
#include <vcg/math/matrix33.h>
|
|
|
|
#include <vcg/math/lin_algebra.h>
|
2005-03-14 18:04:24 +01:00
|
|
|
|
|
|
|
|
|
|
|
namespace vcg {
|
|
|
|
|
2005-10-13 16:59:57 +02:00
|
|
|
template <class S>
|
2008-07-21 10:34:31 +02:00
|
|
|
Point3<S> PlaneFittingPoints( std::vector< Point3<S> > & samples,Plane3<S> &p){
|
2005-10-13 16:59:57 +02:00
|
|
|
|
|
|
|
int j;
|
|
|
|
Matrix44<S> m;m.SetZero();
|
2005-10-15 14:58:13 +02:00
|
|
|
typename std::vector< Point3<S> > ::iterator i;
|
2005-10-13 16:59:57 +02:00
|
|
|
|
2008-10-27 15:48:14 +01:00
|
|
|
Point3<S> c; c.SetZero();
|
2005-10-13 16:59:57 +02:00
|
|
|
for(i = samples.begin(); i != samples.end(); ++i)
|
|
|
|
c+=*i;
|
|
|
|
c/=samples.size();
|
|
|
|
|
|
|
|
for(i = samples.begin(); i != samples.end(); ++i){
|
|
|
|
Point3<S> p = (*i)-c;
|
|
|
|
for(j = 0 ; j < 3;++j)
|
|
|
|
*(Point3<S>*)&m[j][0] += p * p[j];
|
|
|
|
}
|
|
|
|
|
|
|
|
m[0][3]= m[1][3]=m[2][3]=0.0;
|
|
|
|
m[3][3]= 1.0;
|
|
|
|
m[3][0]= m[3][1]=m[3][2]=0.0;
|
|
|
|
|
|
|
|
int n;
|
|
|
|
Matrix44<S> res;
|
|
|
|
Point4<S> e;
|
|
|
|
Point3<S> d;
|
|
|
|
Jacobi(m,e,res,n);
|
|
|
|
|
2008-07-21 10:34:31 +02:00
|
|
|
//Sort eigenvalues (tarinisort)
|
|
|
|
e[0] = fabs(e[0]);
|
|
|
|
e[1] = fabs(e[1]);
|
|
|
|
e[2] = fabs(e[2]);
|
|
|
|
Point3<S> eval;
|
|
|
|
int maxi,mini,medi;
|
|
|
|
if (e[1] > e[0]) { maxi=1; mini=0; } else { maxi=0; mini=1;}
|
|
|
|
if (e[maxi] < e[2]) maxi=2; else if(e[mini] > e[2]) mini=2;
|
|
|
|
medi = 3 - maxi -mini;
|
|
|
|
eval = Point3<S>(e[mini], e[medi], e[maxi]);
|
|
|
|
|
|
|
|
d[0]=res[0][mini];
|
|
|
|
d[1]=res[1][mini];
|
|
|
|
d[2]=res[2][mini];
|
2005-10-13 16:59:57 +02:00
|
|
|
|
make point2 derived Eigen's Matrix, and a set of minimal fixes to make meshlab compile
with both old and new version. The fixes include:
- dot product: vec0 * vec1 => vec0.dot(vec1) (I added .dot() to the old Point classes too)
- Transpose: Transpose is an Eigen type, so we cannot keep it if Eigen is used. Therefore
I added a .tranpose() to old matrix classes, and modified most of the Transpose() to transpose()
both in vcg and meshlab. In fact, transpose() are free with Eigen, it simply returns a transpose
expression without copies. On the other be carefull: m = m.transpose() won't work as expected,
here me must evaluate to a temporary: m = m.transpose().eval(); However, this operation in very
rarely needed: you transpose at the same sime you set m, or you use m.transpose() directly.
- the last issue is Normalize which both modifies *this and return a ref to it. This behavior
don't make sense anymore when using expression template, e.g., in (a+b).Normalize(), the type
of a+b if not a Point (or whatever Vector types), it an expression of the addition of 2 points,
so we cannot modify the value of *this, since there is no value. Therefore I've already changed
all those .Normalize() of expressions to the Eigen's version .normalized().
- Finally I've changed the Zero to SetZero in the old Point classes too.
2008-10-28 01:59:46 +01:00
|
|
|
p.SetOffset(c.dot(d)/d.Norm());
|
2005-10-13 16:59:57 +02:00
|
|
|
p.SetDirection(d/d.Norm());
|
|
|
|
|
2008-07-21 10:34:31 +02:00
|
|
|
return eval;
|
2005-10-13 16:59:57 +02:00
|
|
|
}
|
|
|
|
|
2005-03-14 18:04:24 +01:00
|
|
|
template<class S>
|
|
|
|
inline double FIT_VExp( const Point3<S> & x, const int i )
|
|
|
|
{
|
|
|
|
assert(i>=0);
|
|
|
|
assert(i<4);
|
|
|
|
if(i==0) return 1;
|
|
|
|
else return x[i-1];
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Fitting di piani: trova il piano che meglio approssima
|
|
|
|
l'insieme di punti dato
|
|
|
|
*/
|
2005-10-13 16:59:57 +02:00
|
|
|
template<class S>
|
|
|
|
bool PlaneFittingPointsOld( std::vector< Point3<S> > & samples, Plane3<S> & p )
|
2005-03-14 18:04:24 +01:00
|
|
|
{
|
2005-10-13 16:59:57 +02:00
|
|
|
Point3<S> d;
|
2005-03-14 18:04:24 +01:00
|
|
|
|
2005-10-13 16:59:57 +02:00
|
|
|
const int N = 4;
|
2005-03-14 18:04:24 +01:00
|
|
|
S P[N][N]; // A = s' . s
|
|
|
|
S U[N][N];
|
|
|
|
int i,j,k,n;
|
|
|
|
|
2005-10-13 16:59:57 +02:00
|
|
|
n = (int)samples.size();
|
2005-03-14 18:04:24 +01:00
|
|
|
if(n<3)
|
|
|
|
return false;
|
|
|
|
|
2005-10-13 16:59:57 +02:00
|
|
|
//printf("\n p_prima: %f %f %f %f \n",p.Offset(),p.Direction()[0],p.Direction()[1],p.Direction()[2]);
|
|
|
|
|
2005-03-14 18:04:24 +01:00
|
|
|
for(i=0;i<N;++i)
|
|
|
|
{
|
|
|
|
for(j=i;j<N;++j)
|
|
|
|
{
|
|
|
|
P[i][j] = 0;
|
|
|
|
for(k=0;k<n;++k)
|
|
|
|
P[i][j] += FIT_VExp(samples[k],i) * FIT_VExp(samples[k],j);
|
|
|
|
}
|
|
|
|
for(j=0;j<i;++j)
|
|
|
|
P[i][j] = P[j][i];
|
|
|
|
}
|
2005-10-13 16:59:57 +02:00
|
|
|
|
|
|
|
//printf("D \n");
|
|
|
|
//for(i=0;i<N;++i){
|
|
|
|
// printf("\n");
|
|
|
|
// for(j=0;j<N;++j)
|
|
|
|
// printf("%2.3f\t",P[i][j]);
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
Matrix44<S> m;
|
|
|
|
for(i=0;i<N;++i)
|
|
|
|
for(j=0;j<N;++j)
|
|
|
|
m[i][j]=P[i][j];
|
|
|
|
|
|
|
|
|
2008-10-27 15:48:14 +01:00
|
|
|
// Point4<S> s;s.SetZero();
|
2005-10-13 16:59:57 +02:00
|
|
|
//
|
|
|
|
// s.Normalize();
|
|
|
|
// printf("\n RES %f %f %f %f \n",s[0],s[1],s[2],s[3]);
|
|
|
|
//printf("\n GJ \n");
|
|
|
|
// for(i=0;i<N;++i){
|
|
|
|
// printf("\n");
|
|
|
|
// for(j=0;j<N;++j)
|
|
|
|
// printf("%2.3f\t",m[i][j]);
|
|
|
|
// }
|
2005-03-14 18:04:24 +01:00
|
|
|
for(i=0;i<N;++i)
|
|
|
|
{
|
|
|
|
U[i][i] = 1.0;
|
|
|
|
for(j=0;j<i;++j)
|
|
|
|
U[i][j] = 0.0;
|
|
|
|
for(j=i+1;j<N;++j)
|
|
|
|
{
|
|
|
|
if(P[i][i]==0.0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
U[i][j] = P[i][j]/P[i][i];
|
|
|
|
for(k=j;k<N;++k)
|
|
|
|
P[j][k] -= U[i][j]*P[i][k];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-13 16:59:57 +02:00
|
|
|
//printf("\n U \n");
|
|
|
|
//for(i=0;i<N;++i){
|
|
|
|
// printf("\n");
|
|
|
|
// for(j=0;j<N;++j)
|
|
|
|
// printf("%2.3f\t",U[i][j]);
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
S norm = Point3<S>(U[1][2]*U[2][3]-U[1][3],-U[2][3],1).Norm();
|
|
|
|
|
|
|
|
p.SetDirection(Point3<S>(U[1][2]*U[2][3]-U[1][3],-U[2][3],1));
|
|
|
|
p.SetOffset(-(U[0][2]*U[2][3]-U[0][3]+U[0][1]*U[1][3]-U[0][1]*U[1][2]*U[2][3])/norm);
|
|
|
|
|
|
|
|
|
|
|
|
//printf("\n p: %f %f %f %f \n",p.Offset(),p.Direction()[0],p.Direction()[1],p.Direction()[2]);
|
|
|
|
|
2005-03-14 18:04:24 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} // end namespace
|
|
|
|
|
2005-10-15 14:58:13 +02:00
|
|
|
#endif
|