Removed useless include
This commit is contained in:
parent
998312b65e
commit
6f7e2872af
|
@ -31,9 +31,9 @@ ps: the name of the variables are out of vcg standard but like the one
|
||||||
used in the paper pseudocode.
|
used in the paper pseudocode.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <vcg/complex/complex.h>
|
||||||
#include <vcg/space/point_matching.h>
|
#include <vcg/space/point_matching.h>
|
||||||
#include <vcg/complex/algorithms/closest.h>
|
#include <vcg/complex/algorithms/closest.h>
|
||||||
#include <vcg/complex/complex.h>
|
|
||||||
#include <wrap/io_trimesh/export_ply.h>
|
#include <wrap/io_trimesh/export_ply.h>
|
||||||
|
|
||||||
// note: temporary (callback.h should be moved inside vcg)
|
// note: temporary (callback.h should be moved inside vcg)
|
||||||
|
@ -150,191 +150,191 @@ private:
|
||||||
void GetBBox(vcg::Box3<ScalarType> & b){b.Add(pos);}
|
void GetBBox(vcg::Box3<ScalarType> & b){b.Add(pos);}
|
||||||
};
|
};
|
||||||
|
|
||||||
GridType *ugrid; // griglia
|
GridType *ugrid; // griglia
|
||||||
vcg::GridStaticPtr<typename MeshType::VertexType, ScalarType > ugridQ;
|
vcg::GridStaticPtr<typename MeshType::VertexType, ScalarType > ugridQ;
|
||||||
vcg::GridStaticPtr<typename MeshType::VertexType, ScalarType > ugridP;
|
vcg::GridStaticPtr<typename MeshType::VertexType, ScalarType > ugridP;
|
||||||
|
|
||||||
bool SelectCoplanarBase(); // on P
|
bool SelectCoplanarBase(); // on P
|
||||||
bool FindCongruent() ; // of base B, on Q, with approximation delta
|
bool FindCongruent() ; // of base B, on Q, with approximation delta
|
||||||
void ComputeR1R2(ScalarType d1,ScalarType d2);
|
void ComputeR1R2(ScalarType d1,ScalarType d2);
|
||||||
|
|
||||||
bool IsTransfCongruent(FourPoints fp,vcg::Matrix44<ScalarType> & mat, float & trerr);
|
bool IsTransfCongruent(FourPoints fp,vcg::Matrix44<ScalarType> & mat, float & trerr);
|
||||||
int EvaluateSample(Candidate & fp, CoordType & tp, CoordType & np, const float & angle);
|
int EvaluateSample(Candidate & fp, CoordType & tp, CoordType & np, const float & angle);
|
||||||
void EvaluateAlignment(Candidate & fp);
|
void EvaluateAlignment(Candidate & fp);
|
||||||
void TestAlignment(Candidate & fp);
|
void TestAlignment(Candidate & fp);
|
||||||
|
|
||||||
/* debug tools */
|
/* debug tools */
|
||||||
public:
|
public:
|
||||||
std::vector<vcg::Matrix44f> allTr;// tutte le trasformazioni provate
|
std::vector<vcg::Matrix44f> allTr;// tutte le trasformazioni provate
|
||||||
FILE * db;
|
FILE * db;
|
||||||
char namemesh1[255],namemesh2[255];
|
char namemesh1[255],namemesh2[255];
|
||||||
int n_base;
|
int n_base;
|
||||||
void InitDebug(const char * name1, const char * name2){
|
void InitDebug(const char * name1, const char * name2){
|
||||||
db = fopen("debugPCS.txt","w");
|
db = fopen("debugPCS.txt","w");
|
||||||
sprintf(&namemesh1[0],"%s",name1);
|
sprintf(&namemesh1[0],"%s",name1);
|
||||||
sprintf(&namemesh2[0],"%s",name2);
|
sprintf(&namemesh2[0],"%s",name2);
|
||||||
n_base = 0;
|
n_base = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FinishDebug(){
|
void FinishDebug(){
|
||||||
fclose(db);
|
fclose(db);
|
||||||
}
|
}
|
||||||
//void SaveALN(char * name,vcg::Matrix44f mat ){
|
//void SaveALN(char * name,vcg::Matrix44f mat ){
|
||||||
// FILE * o = fopen(name,"w");
|
// FILE * o = fopen(name,"w");
|
||||||
// fprintf(o,"2\n%s\n#\n",namemesh1);
|
// fprintf(o,"2\n%s\n#\n",namemesh1);
|
||||||
// for(int i = 0 ; i < 4; ++i)
|
// for(int i = 0 ; i < 4; ++i)
|
||||||
// fprintf(o,"%f %f %f %f\n",mat[i][0],mat[i][1],mat[i][2],mat[i][3]);
|
// fprintf(o,"%f %f %f %f\n",mat[i][0],mat[i][1],mat[i][2],mat[i][3]);
|
||||||
// fprintf(o,"%s\n#\n",namemesh2);
|
// fprintf(o,"%s\n#\n",namemesh2);
|
||||||
// fprintf(o,"1.0 0.0 0.0 0.0 \n");
|
// fprintf(o,"1.0 0.0 0.0 0.0 \n");
|
||||||
// fprintf(o,"0.0 1.0 0.0 0.0 \n");
|
// fprintf(o,"0.0 1.0 0.0 0.0 \n");
|
||||||
// fprintf(o,"0.0 0.0 1.0 0.0 \n");
|
// fprintf(o,"0.0 0.0 1.0 0.0 \n");
|
||||||
// fprintf(o,"0.0 0.0 0.0 1.0 \n");
|
// fprintf(o,"0.0 0.0 0.0 1.0 \n");
|
||||||
|
|
||||||
// fclose(o);
|
// fclose(o);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class MeshType>
|
template <class MeshType>
|
||||||
void FourPCS<MeshType>:: Init(MeshType &_P,MeshType &_Q)
|
void FourPCS<MeshType>:: Init(MeshType &_P,MeshType &_Q)
|
||||||
{
|
{
|
||||||
P = &_P;Q=&_Q;
|
P = &_P;Q=&_Q;
|
||||||
ugridQ.Set(Q->vert.begin(),Q->vert.end());
|
ugridQ.Set(Q->vert.begin(),Q->vert.end());
|
||||||
ugridP.Set(P->vert.begin(),P->vert.end());
|
ugridP.Set(P->vert.begin(),P->vert.end());
|
||||||
|
|
||||||
float ratio = 800 / (float) Q->vert.size();
|
float ratio = 800 / (float) Q->vert.size();
|
||||||
for(int vi = 0; vi < Q->vert.size(); ++vi)
|
for(int vi = 0; vi < Q->vert.size(); ++vi)
|
||||||
if(rand()/(float) RAND_MAX < ratio)
|
if(rand()/(float) RAND_MAX < ratio)
|
||||||
mapsub.push_back(vi);
|
mapsub.push_back(vi);
|
||||||
|
|
||||||
for(int vi = 0; vi < P->vert.size(); ++vi)
|
for(int vi = 0; vi < P->vert.size(); ++vi)
|
||||||
if(rand()/(float) RAND_MAX < ratio)
|
if(rand()/(float) RAND_MAX < ratio)
|
||||||
subsetP.push_back(&P->vert[vi]);
|
subsetP.push_back(&P->vert[vi]);
|
||||||
|
|
||||||
// estimate neigh distance
|
// estimate neigh distance
|
||||||
float avD = 0.0;
|
float avD = 0.0;
|
||||||
for(int i = 0 ; i < 100; ++i){
|
for(int i = 0 ; i < 100; ++i){
|
||||||
int ri = rand()/(float) RAND_MAX * Q->vert.size() -1;
|
int ri = rand()/(float) RAND_MAX * Q->vert.size() -1;
|
||||||
std::vector< CoordType > samples,d_samples;
|
std::vector< CoordType > samples,d_samples;
|
||||||
std::vector<ScalarType > dists;
|
std::vector<ScalarType > dists;
|
||||||
std::vector<VertexType* > ress;
|
std::vector<VertexType* > ress;
|
||||||
vcg::tri::GetKClosestVertex<
|
vcg::tri::GetKClosestVertex<
|
||||||
MeshType,
|
MeshType,
|
||||||
vcg::GridStaticPtr<typename MeshType::VertexType, ScalarType>,
|
vcg::GridStaticPtr<typename MeshType::VertexType, ScalarType>,
|
||||||
std::vector<VertexType*>,
|
std::vector<VertexType*>,
|
||||||
std::vector<ScalarType>,
|
std::vector<ScalarType>,
|
||||||
std::vector< CoordType > >(*Q,ugridQ,2,Q->vert[ri].cP(),Q->bbox.Diag(), ress,dists, samples);
|
std::vector< CoordType > >(*Q,ugridQ,2,Q->vert[ri].cP(),Q->bbox.Diag(), ress,dists, samples);
|
||||||
assert(ress.size() == 2);
|
assert(ress.size() == 2);
|
||||||
avD+=dists[1];
|
avD+=dists[1];
|
||||||
}
|
}
|
||||||
avD /=100; // average vertex-vertex distance
|
avD /=100; // average vertex-vertex distance
|
||||||
avD /= sqrt(ratio); // take into account the ratio
|
avD /= sqrt(ratio); // take into account the ratio
|
||||||
|
|
||||||
par.delta = avD * par.delta;
|
par.delta = avD * par.delta;
|
||||||
side = P->bbox.Dim()[P->bbox.MaxDim()]*par.f; //rough implementation
|
side = P->bbox.Dim()[P->bbox.MaxDim()]*par.f; //rough implementation
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class MeshType>
|
template <class MeshType>
|
||||||
bool
|
bool
|
||||||
FourPCS<MeshType>::SelectCoplanarBase(){
|
FourPCS<MeshType>::SelectCoplanarBase(){
|
||||||
|
|
||||||
vcg::tri::UpdateBounding<MeshType>::Box(*P);
|
vcg::tri::UpdateBounding<MeshType>::Box(*P);
|
||||||
|
|
||||||
// choose the inter point distance
|
// choose the inter point distance
|
||||||
ScalarType dtol = side*0.1; //rough implementation
|
ScalarType dtol = side*0.1; //rough implementation
|
||||||
|
|
||||||
//choose the first two points
|
//choose the first two points
|
||||||
int i = 0,ch;
|
int i = 0,ch;
|
||||||
|
|
||||||
// first point random
|
// first point random
|
||||||
ch = (rand()/(float)RAND_MAX)*(P->vert.size()-2);
|
ch = (rand()/(float)RAND_MAX)*(P->vert.size()-2);
|
||||||
B[0] = P->vert[ch].P();
|
B[0] = P->vert[ch].P();
|
||||||
//printf("B[0] %d\n",ch);
|
//printf("B[0] %d\n",ch);
|
||||||
// second a point at distance d+-dtol
|
// second a point at distance d+-dtol
|
||||||
for(i = 0; i < P->vert.size(); ++i){
|
for(i = 0; i < P->vert.size(); ++i){
|
||||||
ScalarType dd = (P->vert[i].P() - B[0]).Norm();
|
ScalarType dd = (P->vert[i].P() - B[0]).Norm();
|
||||||
if( ( dd < side + dtol) && (dd > side - dtol)){
|
if( ( dd < side + dtol) && (dd > side - dtol)){
|
||||||
B[1] = P->vert[i].P();
|
B[1] = P->vert[i].P();
|
||||||
//printf("B[1] %d\n",i);
|
//printf("B[1] %d\n",i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(i == P->vert.size())
|
if(i == P->vert.size())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// third point at distance d from B[1] and forming a right angle
|
// third point at distance d from B[1] and forming a right angle
|
||||||
int best = -1; ScalarType bestv=std::numeric_limits<float>::max();
|
int best = -1; ScalarType bestv=std::numeric_limits<float>::max();
|
||||||
for(i = 0; i < P->vert.size(); ++i){
|
for(i = 0; i < P->vert.size(); ++i){
|
||||||
int id = rand()/(float)RAND_MAX * (P->vert.size()-1);
|
int id = rand()/(float)RAND_MAX * (P->vert.size()-1);
|
||||||
ScalarType dd = (P->vert[id].P() - B[1]).Norm();
|
ScalarType dd = (P->vert[id].P() - B[1]).Norm();
|
||||||
if( ( dd < side + dtol) && (dd > side - dtol)){
|
if( ( dd < side + dtol) && (dd > side - dtol)){
|
||||||
ScalarType angle = fabs( ( P->vert[id].P()-B[1]).normalized().dot((B[1]-B[0]).normalized()));
|
ScalarType angle = fabs( ( P->vert[id].P()-B[1]).normalized().dot((B[1]-B[0]).normalized()));
|
||||||
if( angle < bestv){
|
if( angle < bestv){
|
||||||
bestv = angle;
|
bestv = angle;
|
||||||
best = id;
|
best = id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(best == -1)
|
if(best == -1)
|
||||||
return false;
|
return false;
|
||||||
B[2] = P->vert[best].P();
|
B[2] = P->vert[best].P();
|
||||||
//printf("B[2] %d\n",best);
|
//printf("B[2] %d\n",best);
|
||||||
|
|
||||||
CoordType n = ((B[0]-B[1]).normalized() ^ (B[2]-B[1]).normalized()).normalized();
|
CoordType n = ((B[0]-B[1]).normalized() ^ (B[2]-B[1]).normalized()).normalized();
|
||||||
CoordType B4 = B[1] + (B[0]-B[1]) + (B[2]-B[1]);
|
CoordType B4 = B[1] + (B[0]-B[1]) + (B[2]-B[1]);
|
||||||
VertexType * v =0;
|
VertexType * v =0;
|
||||||
ScalarType radius = dtol*4.0;
|
ScalarType radius = dtol*4.0;
|
||||||
|
|
||||||
std::vector<typename MeshType::VertexType*> closests;
|
std::vector<typename MeshType::VertexType*> closests;
|
||||||
std::vector<ScalarType> distances;
|
std::vector<ScalarType> distances;
|
||||||
std::vector<CoordType> points;
|
std::vector<CoordType> points;
|
||||||
|
|
||||||
vcg::tri::GetInSphereVertex<
|
vcg::tri::GetInSphereVertex<
|
||||||
MeshType,
|
MeshType,
|
||||||
vcg::GridStaticPtr<typename MeshType::VertexType, ScalarType >,
|
vcg::GridStaticPtr<typename MeshType::VertexType, ScalarType >,
|
||||||
std::vector<typename MeshType::VertexType*>,
|
std::vector<typename MeshType::VertexType*>,
|
||||||
std::vector<ScalarType>,
|
std::vector<ScalarType>,
|
||||||
std::vector<CoordType>
|
std::vector<CoordType>
|
||||||
>(*P,ugridP,B4,radius,closests,distances,points);
|
>(*P,ugridP,B4,radius,closests,distances,points);
|
||||||
|
|
||||||
if(closests.empty())
|
if(closests.empty())
|
||||||
return false;
|
return false;
|
||||||
best = -1; bestv=std::numeric_limits<float>::max();
|
best = -1; bestv=std::numeric_limits<float>::max();
|
||||||
for(i = 0; i <closests.size(); ++i){
|
for(i = 0; i <closests.size(); ++i){
|
||||||
ScalarType angle = fabs((closests[i]->P() - B[1]).normalized().dot(n));
|
ScalarType angle = fabs((closests[i]->P() - B[1]).normalized().dot(n));
|
||||||
if( angle < bestv){
|
if( angle < bestv){
|
||||||
bestv = angle;
|
bestv = angle;
|
||||||
best = i;
|
best = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
B[3] = closests[best]->P();
|
B[3] = closests[best]->P();
|
||||||
|
|
||||||
//printf("B[3] %d\n", (typename MeshType::VertexType*)closests[best] - &(*P->vert.begin()));
|
//printf("B[3] %d\n", (typename MeshType::VertexType*)closests[best] - &(*P->vert.begin()));
|
||||||
|
|
||||||
// compute r1 and r2
|
// compute r1 and r2
|
||||||
CoordType x;
|
CoordType x;
|
||||||
std::swap(B[1],B[2]);
|
std::swap(B[1],B[2]);
|
||||||
IntersectionLineLine(B[0],B[1],B[2],B[3],x);
|
IntersectionLineLine(B[0],B[1],B[2],B[3],x);
|
||||||
|
|
||||||
r1 = (x - B[0]).dot(B[1]-B[0]) / (B[1]-B[0]).SquaredNorm();
|
r1 = (x - B[0]).dot(B[1]-B[0]) / (B[1]-B[0]).SquaredNorm();
|
||||||
r2 = (x - B[2]).dot(B[3]-B[2]) / (B[3]-B[2]).SquaredNorm();
|
r2 = (x - B[2]).dot(B[3]-B[2]) / (B[3]-B[2]).SquaredNorm();
|
||||||
|
|
||||||
if( ((B[0]+(B[1]-B[0])*r1)-(B[2]+(B[3]-B[2])*r2)).Norm() > par.delta )
|
if( ((B[0]+(B[1]-B[0])*r1)-(B[2]+(B[3]-B[2])*r2)).Norm() > par.delta )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
radius =side*0.5;
|
radius =side*0.5;
|
||||||
std::vector< CoordType > samples,d_samples;
|
std::vector< CoordType > samples,d_samples;
|
||||||
std::vector<ScalarType > dists;
|
std::vector<ScalarType > dists;
|
||||||
|
|
||||||
for(int i = 0 ; i< 4; ++i){
|
for(int i = 0 ; i< 4; ++i){
|
||||||
vcg::tri::GetKClosestVertex<
|
vcg::tri::GetKClosestVertex<
|
||||||
MeshType,
|
MeshType,
|
||||||
vcg::GridStaticPtr<typename MeshType::VertexType, ScalarType >,
|
vcg::GridStaticPtr<typename MeshType::VertexType, ScalarType >,
|
||||||
std::vector<VertexType*>,
|
std::vector<VertexType*>,
|
||||||
std::vector<ScalarType>,
|
std::vector<ScalarType>,
|
||||||
std::vector< CoordType > >(*P,ugridP, par.feetsize ,B[i],radius, ExtB[i],dists, samples);
|
std::vector< CoordType > >(*P,ugridP, par.feetsize ,B[i],radius, ExtB[i],dists, samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
//for(int i = 0 ; i< 4; ++i)
|
//for(int i = 0 ; i< 4; ++i)
|
||||||
// printf("%d ",ExtB[i].size());
|
// printf("%d ",ExtB[i].size());
|
||||||
|
@ -372,144 +372,144 @@ bool FourPCS<MeshType>::IsTransfCongruent(FourPoints fp, vcg::Matrix44<ScalarTyp
|
||||||
template <class MeshType>
|
template <class MeshType>
|
||||||
void
|
void
|
||||||
FourPCS<MeshType>::ComputeR1R2(ScalarType d1,ScalarType d2){
|
FourPCS<MeshType>::ComputeR1R2(ScalarType d1,ScalarType d2){
|
||||||
int vi,vj;
|
int vi,vj;
|
||||||
R1.clear();
|
R1.clear();
|
||||||
//R2.clear();
|
//R2.clear();
|
||||||
int start = clock();
|
int start = clock();
|
||||||
for(vi = 0; vi < mapsub.size(); ++vi) for(vj = vi; vj < mapsub.size(); ++vj){
|
for(vi = 0; vi < mapsub.size(); ++vi) for(vj = vi; vj < mapsub.size(); ++vj){
|
||||||
ScalarType d = ((Q->vert[mapsub[vi]]).P()-(Q->vert[mapsub[vj]]).P()).Norm();
|
ScalarType d = ((Q->vert[mapsub[vi]]).P()-(Q->vert[mapsub[vj]]).P()).Norm();
|
||||||
if( (d < d1+ side*0.5) && (d > d1-side*0.5))
|
if( (d < d1+ side*0.5) && (d > d1-side*0.5))
|
||||||
{
|
{
|
||||||
R1.push_back(Couple(mapsub[vi],mapsub[vj],d ));
|
R1.push_back(Couple(mapsub[vi],mapsub[vj],d ));
|
||||||
R1.push_back(Couple(mapsub[vj],mapsub[vi],d));
|
R1.push_back(Couple(mapsub[vj],mapsub[vi],d));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//for( vi = 0; vi < mapsub.size(); ++ vi ) for( vj = vi ; vj < mapsub.size(); ++ vj ){
|
//for( vi = 0; vi < mapsub.size(); ++ vi ) for( vj = vi ; vj < mapsub.size(); ++ vj ){
|
||||||
// ScalarType d = ((Q->vert[mapsub[vi]]).P()-(Q->vert[mapsub[vj]]).P()).Norm();
|
// ScalarType d = ((Q->vert[mapsub[vi]]).P()-(Q->vert[mapsub[vj]]).P()).Norm();
|
||||||
// if( (d < d2+side*0.5) && (d > d2-side*0.5))
|
// if( (d < d2+side*0.5) && (d > d2-side*0.5))
|
||||||
// {
|
// {
|
||||||
// R2.push_back(Couple(mapsub[vi],mapsub[vj],d));
|
// R2.push_back(Couple(mapsub[vi],mapsub[vj],d));
|
||||||
// R2.push_back(Couple(mapsub[vj],mapsub[vi],d));
|
// R2.push_back(Couple(mapsub[vj],mapsub[vi],d));
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
std::sort(R1.begin(),R1.end());
|
std::sort(R1.begin(),R1.end());
|
||||||
// std::sort(R2.begin(),R2.end());
|
// std::sort(R2.begin(),R2.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class MeshType>
|
template <class MeshType>
|
||||||
bool FourPCS<MeshType>::FindCongruent() { // of base B, on Q, with approximation delta
|
bool FourPCS<MeshType>::FindCongruent() { // of base B, on Q, with approximation delta
|
||||||
bool done = false;
|
bool done = false;
|
||||||
std::vector<EPoint> R2inv;
|
std::vector<EPoint> R2inv;
|
||||||
int n_closests = 0, n_congr = 0;
|
int n_closests = 0, n_congr = 0;
|
||||||
int ac =0 ,acf = 0,tr = 0,trf =0;
|
int ac =0 ,acf = 0,tr = 0,trf =0;
|
||||||
ScalarType d1,d2;
|
ScalarType d1,d2;
|
||||||
d1 = (B[1]-B[0]).Norm();
|
d1 = (B[1]-B[0]).Norm();
|
||||||
d2 = (B[3]-B[2]).Norm();
|
d2 = (B[3]-B[2]).Norm();
|
||||||
|
|
||||||
int start = clock();
|
int start = clock();
|
||||||
//int vi,vj;
|
//int vi,vj;
|
||||||
|
|
||||||
typename PMesh::VertexIterator vii;
|
typename PMesh::VertexIterator vii;
|
||||||
typename std::vector<Couple>::iterator bR1,eR1,bR2,eR2,ite,cite;
|
typename std::vector<Couple>::iterator bR1,eR1,bR2,eR2,ite,cite;
|
||||||
bR1 = std::lower_bound<typename std::vector<Couple>::iterator,Couple>(R1.begin(),R1.end(),Couple(d1-par.delta*2.0));
|
bR1 = std::lower_bound<typename std::vector<Couple>::iterator,Couple>(R1.begin(),R1.end(),Couple(d1-par.delta*2.0));
|
||||||
eR1 = std::lower_bound<typename std::vector<Couple>::iterator,Couple>(R1.begin(),R1.end(),Couple(d1+par.delta*2.0));
|
eR1 = std::lower_bound<typename std::vector<Couple>::iterator,Couple>(R1.begin(),R1.end(),Couple(d1+par.delta*2.0));
|
||||||
bR2 = std::lower_bound<typename std::vector<Couple>::iterator,Couple>(R1.begin(),R1.end(),Couple(d2-par.delta*2.0));
|
bR2 = std::lower_bound<typename std::vector<Couple>::iterator,Couple>(R1.begin(),R1.end(),Couple(d2-par.delta*2.0));
|
||||||
eR2 = std::lower_bound<typename std::vector<Couple>::iterator,Couple>(R1.begin(),R1.end(),Couple(d2+par.delta*2.0));
|
eR2 = std::lower_bound<typename std::vector<Couple>::iterator,Couple>(R1.begin(),R1.end(),Couple(d2+par.delta*2.0));
|
||||||
|
|
||||||
// in [bR1,eR1) there are all the pairs ad a distance d1 +- par.delta
|
// in [bR1,eR1) there are all the pairs ad a distance d1 +- par.delta
|
||||||
// in [bR1,eR1) there are all the pairs ad a distance d2 +- par.delta
|
// in [bR1,eR1) there are all the pairs ad a distance d2 +- par.delta
|
||||||
|
|
||||||
if(bR1 == R1.end()) return false;// if there are no such pairs return
|
if(bR1 == R1.end()) return false;// if there are no such pairs return
|
||||||
if(bR2 == R1.end()) return false; // if there are no such pairs return
|
if(bR2 == R1.end()) return false; // if there are no such pairs return
|
||||||
|
|
||||||
// put [bR1,eR1) in a mesh to have the search operator for free (lazy me)
|
// put [bR1,eR1) in a mesh to have the search operator for free (lazy me)
|
||||||
Invr.Clear();
|
Invr.Clear();
|
||||||
int i = &(*bR1)-&(*R1.begin());
|
int i = &(*bR1)-&(*R1.begin());
|
||||||
for(ite = bR1; ite != eR1;++ite){
|
for(ite = bR1; ite != eR1;++ite){
|
||||||
vii = vcg::tri::Allocator<PMesh>::AddVertices(Invr,1);
|
vii = vcg::tri::Allocator<PMesh>::AddVertices(Invr,1);
|
||||||
(*vii).P() = Q->vert[R1[i][0]].P() + (Q->vert[R1[i][1]].P()-Q->vert[R1[i][0]].P()) * r1;
|
(*vii).P() = Q->vert[R1[i][0]].P() + (Q->vert[R1[i][1]].P()-Q->vert[R1[i][0]].P()) * r1;
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
if(Invr.vert.empty() ) return false;
|
if(Invr.vert.empty() ) return false;
|
||||||
|
|
||||||
// index remaps a vertex of Invr to its corresponding point in R1
|
// index remaps a vertex of Invr to its corresponding point in R1
|
||||||
typename PMesh::template PerVertexAttributeHandle<int> id = vcg::tri::Allocator<PMesh>::template AddPerVertexAttribute<int>(Invr,std::string("index"));
|
typename PMesh::template PerVertexAttributeHandle<int> id = vcg::tri::Allocator<PMesh>::template AddPerVertexAttribute<int>(Invr,std::string("index"));
|
||||||
i = &(*bR1)-&(*R1.begin());
|
i = &(*bR1)-&(*R1.begin());
|
||||||
for(vii = Invr.vert.begin(); vii != Invr.vert.end();++vii,++i) id[vii] = i;
|
for(vii = Invr.vert.begin(); vii != Invr.vert.end();++vii,++i) id[vii] = i;
|
||||||
|
|
||||||
vcg::tri::UpdateBounding<PMesh>::Box(Invr);
|
vcg::tri::UpdateBounding<PMesh>::Box(Invr);
|
||||||
// printf("Invr size %d\n",Invr.vn);
|
// printf("Invr size %d\n",Invr.vn);
|
||||||
|
|
||||||
ugrid = new GridType();
|
ugrid = new GridType();
|
||||||
ugrid->Set(Invr.vert.begin(),Invr.vert.end());
|
ugrid->Set(Invr.vert.begin(),Invr.vert.end());
|
||||||
|
|
||||||
i = &(*bR2)-&(*R1.begin());
|
i = &(*bR2)-&(*R1.begin());
|
||||||
// R2inv contains all the points generated by the couples in R2 (with the reference to remap into R2)
|
// R2inv contains all the points generated by the couples in R2 (with the reference to remap into R2)
|
||||||
for(ite = bR2; ite != eR2;++ite){
|
for(ite = bR2; ite != eR2;++ite){
|
||||||
R2inv.push_back( EPoint( Q->vert[R1[i][0]].P() + (Q->vert[R1[i][1]].P()-Q->vert[R1[i][0]].P()) * r2,i));
|
R2inv.push_back( EPoint( Q->vert[R1[i][0]].P() + (Q->vert[R1[i][1]].P()-Q->vert[R1[i][0]].P()) * r2,i));
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
n_closests = 0; n_congr = 0; ac =0 ; acf = 0; tr = 0; trf = 0;
|
n_closests = 0; n_congr = 0; ac =0 ; acf = 0; tr = 0; trf = 0;
|
||||||
printf("R2Inv.size = %d \n",R2inv.size());
|
printf("R2Inv.size = %d \n",R2inv.size());
|
||||||
for(uint i = 0 ; i < R2inv.size() ; ++i){
|
for(uint i = 0 ; i < R2inv.size() ; ++i){
|
||||||
|
|
||||||
std::vector<typename PMesh::VertexType*> closests;
|
std::vector<typename PMesh::VertexType*> closests;
|
||||||
|
|
||||||
// for each point in R2inv get all the points in R1 closer than par.delta
|
// for each point in R2inv get all the points in R1 closer than par.delta
|
||||||
vcg::Matrix44<ScalarType> mat;
|
vcg::Matrix44<ScalarType> mat;
|
||||||
vcg::Box3f bb;
|
vcg::Box3f bb;
|
||||||
bb.Add(R2inv[i].pos+vcg::Point3f(par.delta * 0.1,par.delta * 0.1 , par.delta * 0.1 ));
|
bb.Add(R2inv[i].pos+vcg::Point3f(par.delta * 0.1,par.delta * 0.1 , par.delta * 0.1 ));
|
||||||
bb.Add(R2inv[i].pos-vcg::Point3f(par.delta * 0.1,par.delta* 0.1 , par.delta* 0.1));
|
bb.Add(R2inv[i].pos-vcg::Point3f(par.delta * 0.1,par.delta* 0.1 , par.delta* 0.1));
|
||||||
|
|
||||||
vcg::tri::GetInBoxVertex<PMesh,GridType,std::vector<typename PMesh::VertexType*> >
|
vcg::tri::GetInBoxVertex<PMesh,GridType,std::vector<typename PMesh::VertexType*> >
|
||||||
(Invr,*ugrid,bb,closests);
|
(Invr,*ugrid,bb,closests);
|
||||||
|
|
||||||
n_closests+=closests.size();
|
n_closests+=closests.size();
|
||||||
for(uint ip = 0; ip < closests.size(); ++ip){
|
for(uint ip = 0; ip < closests.size(); ++ip){
|
||||||
FourPoints p;
|
FourPoints p;
|
||||||
p[0] = Q->vert[R1[id[closests[ip]]][0]].P();
|
p[0] = Q->vert[R1[id[closests[ip]]][0]].P();
|
||||||
p[1] = Q->vert[R1[id[closests[ip]]][1]].P();
|
p[1] = Q->vert[R1[id[closests[ip]]][1]].P();
|
||||||
p[2] = Q->vert[R1[ R2inv[i].pi][0]].P();
|
p[2] = Q->vert[R1[ R2inv[i].pi][0]].P();
|
||||||
p[3] = Q->vert[R1[ R2inv[i].pi][1]].P();
|
p[3] = Q->vert[R1[ R2inv[i].pi][1]].P();
|
||||||
|
|
||||||
float trerr;
|
float trerr;
|
||||||
n_base++;
|
n_base++;
|
||||||
if(!IsTransfCongruent(p,mat,trerr)) {
|
if(!IsTransfCongruent(p,mat,trerr)) {
|
||||||
trf++;
|
trf++;
|
||||||
//char name[255];
|
//char name[255];
|
||||||
//sprintf(name,"faileTR_%d_%f.aln",n_base,trerr);
|
//sprintf(name,"faileTR_%d_%f.aln",n_base,trerr);
|
||||||
//fprintf(db,"TransCongruent %s\n", name);
|
//fprintf(db,"TransCongruent %s\n", name);
|
||||||
//SaveALN(name, mat);
|
//SaveALN(name, mat);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
tr++;
|
tr++;
|
||||||
n_congr++;
|
n_congr++;
|
||||||
U.push_back(Candidate(p,mat));
|
U.push_back(Candidate(p,mat));
|
||||||
EvaluateAlignment(U.back());
|
EvaluateAlignment(U.back());
|
||||||
U.back().base = bases.size()-1;
|
U.back().base = bases.size()-1;
|
||||||
|
|
||||||
if( U.back().score > par.scoreFeet){
|
if( U.back().score > par.scoreFeet){
|
||||||
TestAlignment(U.back());
|
TestAlignment(U.back());
|
||||||
if(U.back().score > par.scoreAln)
|
if(U.back().score > par.scoreAln)
|
||||||
{
|
{
|
||||||
done = true; break;
|
done = true; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//char name[255];
|
//char name[255];
|
||||||
//sprintf(name,"passed_score_%5d_%d.aln",U.back().score,n_base);
|
//sprintf(name,"passed_score_%5d_%d.aln",U.back().score,n_base);
|
||||||
//fprintf(db,"OK TransCongruent %s, score: %d \n", name,U.back().score);
|
//fprintf(db,"OK TransCongruent %s, score: %d \n", name,U.back().score);
|
||||||
//SaveALN(name, mat);
|
//SaveALN(name, mat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete ugrid;
|
delete ugrid;
|
||||||
vcg::tri::Allocator<PMesh>::DeletePerVertexAttribute(Invr,id);
|
vcg::tri::Allocator<PMesh>::DeletePerVertexAttribute(Invr,id);
|
||||||
printf("n_closests %5d = (An %5d ) + ( Tr %5d ) + (OK) %5d\n",n_closests,acf,trf,n_congr);
|
printf("n_closests %5d = (An %5d ) + ( Tr %5d ) + (OK) %5d\n",n_closests,acf,trf,n_congr);
|
||||||
|
|
||||||
return done;
|
return done;
|
||||||
// printf("done n_closests %d congr %d in %f s\n ",n_closests,n_congr,(clock()-start)/(float)CLOCKS_PER_SEC);
|
// printf("done n_closests %d congr %d in %f s\n ",n_closests,n_congr,(clock()-start)/(float)CLOCKS_PER_SEC);
|
||||||
// printf("angle:%d %d, trasf %d %d\n",ac,acf,tr,trf);
|
// printf("angle:%d %d, trasf %d %d\n",ac,acf,tr,trf);
|
||||||
}
|
}
|
||||||
|
@ -550,28 +550,28 @@ int FourPCS<MeshType>::EvaluateSample(Candidate & fp, CoordType & tp, CoordType
|
||||||
template <class MeshType>
|
template <class MeshType>
|
||||||
void
|
void
|
||||||
FourPCS<MeshType>::EvaluateAlignment(Candidate & fp){
|
FourPCS<MeshType>::EvaluateAlignment(Candidate & fp){
|
||||||
int n_delta_close = 0;
|
int n_delta_close = 0;
|
||||||
for(int i = 0 ; i< 4; ++i) {
|
for(int i = 0 ; i< 4; ++i) {
|
||||||
for(uint j = 0; j < ExtB[i].size();++j){
|
for(uint j = 0; j < ExtB[i].size();++j){
|
||||||
CoordType np = ExtB[i][j]->cN();;
|
CoordType np = ExtB[i][j]->cN();;
|
||||||
CoordType tp = ExtB[i][j]->P();
|
CoordType tp = ExtB[i][j]->P();
|
||||||
n_delta_close+=EvaluateSample(fp,tp,np,0.9);
|
n_delta_close+=EvaluateSample(fp,tp,np,0.9);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fp.score = n_delta_close;
|
fp.score = n_delta_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class MeshType>
|
template <class MeshType>
|
||||||
void
|
void
|
||||||
FourPCS<MeshType>::TestAlignment(Candidate & fp){
|
FourPCS<MeshType>::TestAlignment(Candidate & fp){
|
||||||
radius = par.delta;
|
radius = par.delta;
|
||||||
int n_delta_close = 0;
|
int n_delta_close = 0;
|
||||||
for(uint j = 0; j < subsetP.size();++j){
|
for(uint j = 0; j < subsetP.size();++j){
|
||||||
CoordType np = subsetP[j]->N();
|
CoordType np = subsetP[j]->N();
|
||||||
CoordType tp = subsetP[j]->P();
|
CoordType tp = subsetP[j]->P();
|
||||||
n_delta_close+=EvaluateSample(fp,tp,np,0.6);
|
n_delta_close+=EvaluateSample(fp,tp,np,0.6);
|
||||||
}
|
}
|
||||||
fp.score = n_delta_close;
|
fp.score = n_delta_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -579,50 +579,50 @@ template <class MeshType>
|
||||||
bool
|
bool
|
||||||
FourPCS<MeshType>:: Align( int L, vcg::Matrix44f & result, vcg::CallBackPos * cb ){ // main loop
|
FourPCS<MeshType>:: Align( int L, vcg::Matrix44f & result, vcg::CallBackPos * cb ){ // main loop
|
||||||
|
|
||||||
int bestv = 0;
|
int bestv = 0;
|
||||||
bool found;
|
bool found;
|
||||||
int n_tries = 0;
|
int n_tries = 0;
|
||||||
U.clear();
|
U.clear();
|
||||||
|
|
||||||
if(L==0)
|
if(L==0)
|
||||||
{
|
{
|
||||||
L = (log(1.0-0.9999) / log(1.0-pow((float)par.f,3.f)))+1;
|
L = (log(1.0-0.9999) / log(1.0-pow((float)par.f,3.f)))+1;
|
||||||
printf("using %d bases\n",L);
|
printf("using %d bases\n",L);
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputeR1R2(side*1.4,side*1.4);
|
ComputeR1R2(side*1.4,side*1.4);
|
||||||
|
|
||||||
for(int t = 0; t < L; ++t ){
|
for(int t = 0; t < L; ++t ){
|
||||||
do{
|
do{
|
||||||
n_tries = 0;
|
n_tries = 0;
|
||||||
do{
|
do{
|
||||||
n_tries++;
|
n_tries++;
|
||||||
found = SelectCoplanarBase();
|
found = SelectCoplanarBase();
|
||||||
}
|
}
|
||||||
while(!found && (n_tries <50));
|
while(!found && (n_tries <50));
|
||||||
if(!found) {
|
if(!found) {
|
||||||
par.f*=0.98;
|
par.f*=0.98;
|
||||||
side = P->bbox.Dim()[P->bbox.MaxDim()]*par.f; //rough implementation
|
side = P->bbox.Dim()[P->bbox.MaxDim()]*par.f; //rough implementation
|
||||||
ComputeR1R2(side*1.4,side*1.4);
|
ComputeR1R2(side*1.4,side*1.4);
|
||||||
}
|
}
|
||||||
} while (!found && (par.f >0.1));
|
} while (!found && (par.f >0.1));
|
||||||
|
|
||||||
if(par.f <0.1) {
|
if(par.f <0.1) {
|
||||||
printf("FAILED");
|
printf("FAILED");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bases.push_back(B);
|
bases.push_back(B);
|
||||||
if(cb) cb(t*100/L,"trying bases");
|
if(cb) cb(t*100/L,"trying bases");
|
||||||
if(FindCongruent())
|
if(FindCongruent())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(U.empty()) return false;
|
if(U.empty()) return false;
|
||||||
|
|
||||||
std::sort(U.begin(),U.end());
|
std::sort(U.begin(),U.end());
|
||||||
|
|
||||||
bestv = -std::numeric_limits<float>::max();
|
bestv = -std::numeric_limits<float>::max();
|
||||||
iwinner = 0;
|
iwinner = 0;
|
||||||
|
|
||||||
for(int i = 0 ; i < U.size() ;++i)
|
for(int i = 0 ; i < U.size() ;++i)
|
||||||
{
|
{
|
||||||
|
@ -635,15 +635,15 @@ FourPCS<MeshType>:: Align( int L, vcg::Matrix44f & result, vcg::CallBackPos *
|
||||||
|
|
||||||
printf("Best score: %d \n", bestv);
|
printf("Best score: %d \n", bestv);
|
||||||
|
|
||||||
winner = U[iwinner];
|
winner = U[iwinner];
|
||||||
result = winner.T;
|
result = winner.T;
|
||||||
|
|
||||||
// deallocations
|
// deallocations
|
||||||
Invr.Clear();
|
Invr.Clear();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tri
|
} // namespace tri
|
||||||
} // namespace vcg
|
} // namespace vcg
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <wrap/callback.h>
|
|
||||||
#include <vcg/complex/algorithms/update/topology.h>
|
#include <vcg/complex/algorithms/update/topology.h>
|
||||||
#include <vcg/complex/algorithms/update/flag.h>
|
#include <vcg/complex/algorithms/update/flag.h>
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#ifndef __VCG_TRIVIAL_WALKER
|
#ifndef __VCG_TRIVIAL_WALKER
|
||||||
#define __VCG_TRIVIAL_WALKER
|
#define __VCG_TRIVIAL_WALKER
|
||||||
#include <wrap/callback.h>
|
|
||||||
|
|
||||||
namespace vcg {
|
namespace vcg {
|
||||||
|
|
||||||
|
@ -56,36 +55,36 @@ public:
|
||||||
//else return numeric_limits<float>::quiet_NaN( );
|
//else return numeric_limits<float>::quiet_NaN( );
|
||||||
}
|
}
|
||||||
|
|
||||||
VOX_TYPE &V(const int &x,const int &y,const int &z) {
|
VOX_TYPE &V(const int &x,const int &y,const int &z) {
|
||||||
return Vol[x+y*sz[0]+z*sz[0]*sz[1]];
|
return Vol[x+y*sz[0]+z*sz[0]*sz[1]];
|
||||||
}
|
}
|
||||||
|
|
||||||
VOX_TYPE &V(const Point3i &pi) {
|
VOX_TYPE &V(const Point3i &pi) {
|
||||||
return Vol[ pi[0] + pi[1]*sz[0] + pi[2]*sz[0]*sz[1] ];
|
return Vol[ pi[0] + pi[1]*sz[0] + pi[2]*sz[0]*sz[1] ];
|
||||||
}
|
}
|
||||||
|
|
||||||
const VOX_TYPE &cV(const int &x,const int &y,const int &z) const {
|
const VOX_TYPE &cV(const int &x,const int &y,const int &z) const {
|
||||||
return Vol[x+y*sz[0]+z*sz[0]*sz[1]];
|
return Vol[x+y*sz[0]+z*sz[0]*sz[1]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef enum { XAxis=0,YAxis=1,ZAxis=2} VolumeAxis;
|
typedef enum { XAxis=0,YAxis=1,ZAxis=2} VolumeAxis;
|
||||||
|
|
||||||
template < class VertexPointerType, VolumeAxis AxisVal >
|
template < class VertexPointerType, VolumeAxis AxisVal >
|
||||||
void GetIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointerType &v, const float thr)
|
void GetIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointerType &v, const float thr)
|
||||||
{
|
{
|
||||||
float f1 = V(p1).V()-thr;
|
float f1 = V(p1).V()-thr;
|
||||||
float f2 = V(p2).V()-thr;
|
float f2 = V(p2).V()-thr;
|
||||||
float u = (float) f1/(f1-f2);
|
float u = (float) f1/(f1-f2);
|
||||||
if(AxisVal==XAxis) v->P().X() = (float) p1.X()*(1-u) + u*p2.X();
|
if(AxisVal==XAxis) v->P().X() = (float) p1.X()*(1-u) + u*p2.X();
|
||||||
else v->P().X() = (float) p1.X();
|
else v->P().X() = (float) p1.X();
|
||||||
if(AxisVal==YAxis) v->P().Y() = (float) p1.Y()*(1-u) + u*p2.Y();
|
if(AxisVal==YAxis) v->P().Y() = (float) p1.Y()*(1-u) + u*p2.Y();
|
||||||
else v->P().Y() = (float) p1.Y();
|
else v->P().Y() = (float) p1.Y();
|
||||||
if(AxisVal==ZAxis) v->P().Z() = (float) p1.Z()*(1-u) + u*p2.Z();
|
if(AxisVal==ZAxis) v->P().Z() = (float) p1.Z()*(1-u) + u*p2.Z();
|
||||||
else v->P().Z() = (float) p1.Z();
|
else v->P().Z() = (float) p1.Z();
|
||||||
|
|
||||||
if(VoxelType::HasNormal()) v->N() = V(p1).N()*(1-u) + V(p2).N()*u;
|
if(VoxelType::HasNormal()) v->N() = V(p1).N()*(1-u) + V(p2).N()*u;
|
||||||
}
|
}
|
||||||
|
|
||||||
template < class VertexPointerType >
|
template < class VertexPointerType >
|
||||||
void GetXIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointerType &v, const float thr)
|
void GetXIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointerType &v, const float thr)
|
||||||
|
@ -157,16 +156,16 @@ private:
|
||||||
_bbox = Box3i(Point3i(0,0,0),volume.ISize());
|
_bbox = Box3i(Point3i(0,0,0),volume.ISize());
|
||||||
_slice_dimension = _bbox.DimX()*_bbox.DimZ();
|
_slice_dimension = _bbox.DimX()*_bbox.DimZ();
|
||||||
|
|
||||||
_x_cs = new VertexIndex[ _slice_dimension ];
|
_x_cs = new VertexIndex[ _slice_dimension ];
|
||||||
_y_cs = new VertexIndex[ _slice_dimension ];
|
_y_cs = new VertexIndex[ _slice_dimension ];
|
||||||
_z_cs = new VertexIndex[ _slice_dimension ];
|
_z_cs = new VertexIndex[ _slice_dimension ];
|
||||||
_x_ns = new VertexIndex[ _slice_dimension ];
|
_x_ns = new VertexIndex[ _slice_dimension ];
|
||||||
_z_ns = new VertexIndex[ _slice_dimension ];
|
_z_ns = new VertexIndex[ _slice_dimension ];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
~TrivialWalker()
|
~TrivialWalker()
|
||||||
{_thr=0;}
|
{_thr=0;}
|
||||||
|
|
||||||
template<class EXTRACTOR_TYPE>
|
template<class EXTRACTOR_TYPE>
|
||||||
void BuildMesh(MeshType &mesh, VolumeType &volume, EXTRACTOR_TYPE &extractor, const float threshold, vcg::CallBackPos * cb=0)
|
void BuildMesh(MeshType &mesh, VolumeType &volume, EXTRACTOR_TYPE &extractor, const float threshold, vcg::CallBackPos * cb=0)
|
||||||
|
@ -178,148 +177,148 @@ private:
|
||||||
_thr=threshold;
|
_thr=threshold;
|
||||||
vcg::Point3i p1, p2;
|
vcg::Point3i p1, p2;
|
||||||
|
|
||||||
Begin();
|
Begin();
|
||||||
extractor.Initialize();
|
extractor.Initialize();
|
||||||
for (int j=_bbox.min.Y(); j<(_bbox.max.Y()-1)-1; j+=1)
|
for (int j=_bbox.min.Y(); j<(_bbox.max.Y()-1)-1; j+=1)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(cb && ((j%10)==0) ) cb(j*_bbox.DimY()/100.0,"Marching volume");
|
if(cb && ((j%10)==0) ) cb(j*_bbox.DimY()/100.0,"Marching volume");
|
||||||
|
|
||||||
for (int i=_bbox.min.X(); i<(_bbox.max.X()-1)-1; i+=1)
|
for (int i=_bbox.min.X(); i<(_bbox.max.X()-1)-1; i+=1)
|
||||||
{
|
{
|
||||||
for (int k=_bbox.min.Z(); k<(_bbox.max.Z()-1)-1; k+=1)
|
for (int k=_bbox.min.Z(); k<(_bbox.max.Z()-1)-1; k+=1)
|
||||||
{
|
{
|
||||||
p1.X()=i; p1.Y()=j; p1.Z()=k;
|
p1.X()=i; p1.Y()=j; p1.Z()=k;
|
||||||
p2.X()=i+1; p2.Y()=j+1; p2.Z()=k+1;
|
p2.X()=i+1; p2.Y()=j+1; p2.Z()=k+1;
|
||||||
extractor.ProcessCell(p1, p2);
|
extractor.ProcessCell(p1, p2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NextSlice();
|
NextSlice();
|
||||||
}
|
}
|
||||||
extractor.Finalize();
|
extractor.Finalize();
|
||||||
_volume = NULL;
|
_volume = NULL;
|
||||||
_mesh = NULL;
|
_mesh = NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
float V(int pi, int pj, int pk)
|
float V(int pi, int pj, int pk)
|
||||||
{
|
{
|
||||||
return _volume->Val(pi, pj, pk)-_thr;
|
return _volume->Val(pi, pj, pk)-_thr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Exist(const vcg::Point3i &p0, const vcg::Point3i &p1, VertexPointer &v)
|
bool Exist(const vcg::Point3i &p0, const vcg::Point3i &p1, VertexPointer &v)
|
||||||
{
|
{
|
||||||
int pos = p0.X()+p0.Z()*_bbox.max.X();
|
int pos = p0.X()+p0.Z()*_bbox.max.X();
|
||||||
int vidx;
|
int vidx;
|
||||||
|
|
||||||
if (p0.X()!=p1.X()) // punti allineati lungo l'asse X
|
if (p0.X()!=p1.X()) // punti allineati lungo l'asse X
|
||||||
vidx = (p0.Y()==_current_slice) ? _x_cs[pos] : _x_ns[pos];
|
vidx = (p0.Y()==_current_slice) ? _x_cs[pos] : _x_ns[pos];
|
||||||
else if (p0.Y()!=p1.Y()) // punti allineati lungo l'asse Y
|
else if (p0.Y()!=p1.Y()) // punti allineati lungo l'asse Y
|
||||||
vidx = _y_cs[pos];
|
vidx = _y_cs[pos];
|
||||||
else if (p0.Z()!=p1.Z()) // punti allineati lungo l'asse Z
|
else if (p0.Z()!=p1.Z()) // punti allineati lungo l'asse Z
|
||||||
vidx = (p0.Y()==_current_slice)? _z_cs[pos] : _z_ns[pos];
|
vidx = (p0.Y()==_current_slice)? _z_cs[pos] : _z_ns[pos];
|
||||||
else
|
else
|
||||||
assert(false);
|
assert(false);
|
||||||
|
|
||||||
v = (vidx!=-1)? &_mesh->vert[vidx] : NULL;
|
v = (vidx!=-1)? &_mesh->vert[vidx] : NULL;
|
||||||
return v!=NULL;
|
return v!=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetXIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
|
void GetXIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
|
||||||
{
|
{
|
||||||
int i = p1.X() - _bbox.min.X();
|
int i = p1.X() - _bbox.min.X();
|
||||||
int z = p1.Z() - _bbox.min.Z();
|
int z = p1.Z() - _bbox.min.Z();
|
||||||
VertexIndex index = i+z*_bbox.max.X();
|
VertexIndex index = i+z*_bbox.max.X();
|
||||||
VertexIndex pos;
|
VertexIndex pos;
|
||||||
if (p1.Y()==_current_slice)
|
if (p1.Y()==_current_slice)
|
||||||
{
|
{
|
||||||
if ((pos=_x_cs[index])==-1)
|
if ((pos=_x_cs[index])==-1)
|
||||||
{
|
{
|
||||||
_x_cs[index] = (VertexIndex) _mesh->vert.size();
|
_x_cs[index] = (VertexIndex) _mesh->vert.size();
|
||||||
pos = _x_cs[index];
|
pos = _x_cs[index];
|
||||||
Allocator<MeshType>::AddVertices( *_mesh, 1 );
|
Allocator<MeshType>::AddVertices( *_mesh, 1 );
|
||||||
v = &_mesh->vert[pos];
|
v = &_mesh->vert[pos];
|
||||||
_volume->GetXIntercept(p1, p2, v, _thr);
|
_volume->GetXIntercept(p1, p2, v, _thr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p1.Y()==_current_slice+1)
|
if (p1.Y()==_current_slice+1)
|
||||||
{
|
{
|
||||||
if ((pos=_x_ns[index])==-1)
|
if ((pos=_x_ns[index])==-1)
|
||||||
{
|
{
|
||||||
_x_ns[index] = (VertexIndex) _mesh->vert.size();
|
_x_ns[index] = (VertexIndex) _mesh->vert.size();
|
||||||
pos = _x_ns[index];
|
pos = _x_ns[index];
|
||||||
Allocator<MeshType>::AddVertices( *_mesh, 1 );
|
Allocator<MeshType>::AddVertices( *_mesh, 1 );
|
||||||
v = &_mesh->vert[pos];
|
v = &_mesh->vert[pos];
|
||||||
_volume->GetXIntercept(p1, p2, v,_thr);
|
_volume->GetXIntercept(p1, p2, v,_thr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(pos >=0 && size_t(pos)< _mesh->vert.size());
|
assert(pos >=0 && size_t(pos)< _mesh->vert.size());
|
||||||
v = &_mesh->vert[pos];
|
v = &_mesh->vert[pos];
|
||||||
}
|
}
|
||||||
void GetYIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
|
void GetYIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
|
||||||
{
|
{
|
||||||
int i = p1.X() - _bbox.min.X();
|
int i = p1.X() - _bbox.min.X();
|
||||||
int z = p1.Z() - _bbox.min.Z();
|
int z = p1.Z() - _bbox.min.Z();
|
||||||
VertexIndex index = i+z*_bbox.max.X();
|
VertexIndex index = i+z*_bbox.max.X();
|
||||||
VertexIndex pos;
|
VertexIndex pos;
|
||||||
if ((pos=_y_cs[index])==-1)
|
if ((pos=_y_cs[index])==-1)
|
||||||
{
|
{
|
||||||
_y_cs[index] = (VertexIndex) _mesh->vert.size();
|
_y_cs[index] = (VertexIndex) _mesh->vert.size();
|
||||||
pos = _y_cs[index];
|
pos = _y_cs[index];
|
||||||
Allocator<MeshType>::AddVertices( *_mesh, 1);
|
Allocator<MeshType>::AddVertices( *_mesh, 1);
|
||||||
v = &_mesh->vert[ pos ];
|
v = &_mesh->vert[ pos ];
|
||||||
_volume->GetYIntercept(p1, p2, v,_thr);
|
_volume->GetYIntercept(p1, p2, v,_thr);
|
||||||
}
|
}
|
||||||
v = &_mesh->vert[pos];
|
v = &_mesh->vert[pos];
|
||||||
}
|
}
|
||||||
void GetZIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
|
void GetZIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
|
||||||
{
|
{
|
||||||
int i = p1.X() - _bbox.min.X();
|
int i = p1.X() - _bbox.min.X();
|
||||||
int z = p1.Z() - _bbox.min.Z();
|
int z = p1.Z() - _bbox.min.Z();
|
||||||
VertexIndex index = i+z*_bbox.max.X();
|
VertexIndex index = i+z*_bbox.max.X();
|
||||||
VertexIndex pos;
|
VertexIndex pos;
|
||||||
if (p1.Y()==_current_slice)
|
if (p1.Y()==_current_slice)
|
||||||
{
|
{
|
||||||
if ((pos=_z_cs[index])==-1)
|
if ((pos=_z_cs[index])==-1)
|
||||||
{
|
{
|
||||||
_z_cs[index] = (VertexIndex) _mesh->vert.size();
|
_z_cs[index] = (VertexIndex) _mesh->vert.size();
|
||||||
pos = _z_cs[index];
|
pos = _z_cs[index];
|
||||||
Allocator<MeshType>::AddVertices( *_mesh, 1 );
|
Allocator<MeshType>::AddVertices( *_mesh, 1 );
|
||||||
v = &_mesh->vert[pos];
|
v = &_mesh->vert[pos];
|
||||||
_volume->GetZIntercept(p1, p2, v,_thr);
|
_volume->GetZIntercept(p1, p2, v,_thr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p1.Y()==_current_slice+1)
|
if (p1.Y()==_current_slice+1)
|
||||||
{
|
{
|
||||||
if ((pos=_z_ns[index])==-1)
|
if ((pos=_z_ns[index])==-1)
|
||||||
{
|
{
|
||||||
_z_ns[index] = (VertexIndex) _mesh->vert.size();
|
_z_ns[index] = (VertexIndex) _mesh->vert.size();
|
||||||
pos = _z_ns[index];
|
pos = _z_ns[index];
|
||||||
Allocator<MeshType>::AddVertices( *_mesh, 1 );
|
Allocator<MeshType>::AddVertices( *_mesh, 1 );
|
||||||
v = &_mesh->vert[pos];
|
v = &_mesh->vert[pos];
|
||||||
_volume->GetZIntercept(p1, p2, v,_thr);
|
_volume->GetZIntercept(p1, p2, v,_thr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v = &_mesh->vert[pos];
|
v = &_mesh->vert[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Box3i _bbox;
|
Box3i _bbox;
|
||||||
|
|
||||||
int _slice_dimension;
|
int _slice_dimension;
|
||||||
int _current_slice;
|
int _current_slice;
|
||||||
|
|
||||||
VertexIndex *_x_cs; // indici dell'intersezioni della superficie lungo gli Xedge della fetta corrente
|
VertexIndex *_x_cs; // indici dell'intersezioni della superficie lungo gli Xedge della fetta corrente
|
||||||
VertexIndex *_y_cs; // indici dell'intersezioni della superficie lungo gli Yedge della fetta corrente
|
VertexIndex *_y_cs; // indici dell'intersezioni della superficie lungo gli Yedge della fetta corrente
|
||||||
VertexIndex *_z_cs; // indici dell'intersezioni della superficie lungo gli Zedge della fetta corrente
|
VertexIndex *_z_cs; // indici dell'intersezioni della superficie lungo gli Zedge della fetta corrente
|
||||||
VertexIndex *_x_ns; // indici dell'intersezioni della superficie lungo gli Xedge della prossima fetta
|
VertexIndex *_x_ns; // indici dell'intersezioni della superficie lungo gli Xedge della prossima fetta
|
||||||
VertexIndex *_z_ns; // indici dell'intersezioni della superficie lungo gli Zedge della prossima fetta
|
VertexIndex *_z_ns; // indici dell'intersezioni della superficie lungo gli Zedge della prossima fetta
|
||||||
|
|
||||||
MeshType *_mesh;
|
MeshType *_mesh;
|
||||||
VolumeType *_volume;
|
VolumeType *_volume;
|
||||||
|
|
||||||
float _thr;
|
float _thr;
|
||||||
void NextSlice()
|
void NextSlice()
|
||||||
|
@ -328,23 +327,23 @@ protected:
|
||||||
memset(_y_cs, -1, _slice_dimension*sizeof(VertexIndex));
|
memset(_y_cs, -1, _slice_dimension*sizeof(VertexIndex));
|
||||||
memset(_z_cs, -1, _slice_dimension*sizeof(VertexIndex));
|
memset(_z_cs, -1, _slice_dimension*sizeof(VertexIndex));
|
||||||
|
|
||||||
std::swap(_x_cs, _x_ns);
|
std::swap(_x_cs, _x_ns);
|
||||||
std::swap(_z_cs, _z_ns);
|
std::swap(_z_cs, _z_ns);
|
||||||
|
|
||||||
_current_slice += 1;
|
_current_slice += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Begin()
|
void Begin()
|
||||||
{
|
{
|
||||||
_current_slice = _bbox.min.Y();
|
_current_slice = _bbox.min.Y();
|
||||||
|
|
||||||
memset(_x_cs, -1, _slice_dimension*sizeof(VertexIndex));
|
memset(_x_cs, -1, _slice_dimension*sizeof(VertexIndex));
|
||||||
memset(_y_cs, -1, _slice_dimension*sizeof(VertexIndex));
|
memset(_y_cs, -1, _slice_dimension*sizeof(VertexIndex));
|
||||||
memset(_z_cs, -1, _slice_dimension*sizeof(VertexIndex));
|
memset(_z_cs, -1, _slice_dimension*sizeof(VertexIndex));
|
||||||
memset(_x_ns, -1, _slice_dimension*sizeof(VertexIndex));
|
memset(_x_ns, -1, _slice_dimension*sizeof(VertexIndex));
|
||||||
memset(_z_ns, -1, _slice_dimension*sizeof(VertexIndex));
|
memset(_z_ns, -1, _slice_dimension*sizeof(VertexIndex));
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // end namespace
|
} // end namespace
|
||||||
} // end namespace
|
} // end namespace
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -33,7 +33,6 @@
|
||||||
#include <vcg/complex/algorithms/update/topology.h>
|
#include <vcg/complex/algorithms/update/topology.h>
|
||||||
#include <vcg/complex/algorithms/update/flag.h>
|
#include <vcg/complex/algorithms/update/flag.h>
|
||||||
#include <vcg/space/triangle3.h>
|
#include <vcg/space/triangle3.h>
|
||||||
#include <wrap/callback.h>
|
|
||||||
|
|
||||||
namespace vcg{
|
namespace vcg{
|
||||||
namespace tri{
|
namespace tri{
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -33,7 +33,6 @@
|
||||||
#include <vcg/complex/algorithms/intersection.h>
|
#include <vcg/complex/algorithms/intersection.h>
|
||||||
#include <vcg/complex/algorithms/inertia.h>
|
#include <vcg/complex/algorithms/inertia.h>
|
||||||
#include <eigenlib/Eigen/Core>
|
#include <eigenlib/Eigen/Core>
|
||||||
#include <wrap/callback.h>
|
|
||||||
|
|
||||||
namespace vcg {
|
namespace vcg {
|
||||||
namespace tri {
|
namespace tri {
|
||||||
|
@ -52,16 +51,16 @@ class UpdateCurvature
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef typename MeshType::FaceType FaceType;
|
typedef typename MeshType::FaceType FaceType;
|
||||||
typedef typename MeshType::FacePointer FacePointer;
|
typedef typename MeshType::FacePointer FacePointer;
|
||||||
typedef typename MeshType::FaceIterator FaceIterator;
|
typedef typename MeshType::FaceIterator FaceIterator;
|
||||||
typedef typename MeshType::VertexIterator VertexIterator;
|
typedef typename MeshType::VertexIterator VertexIterator;
|
||||||
typedef typename MeshType::VertContainer VertContainer;
|
typedef typename MeshType::VertContainer VertContainer;
|
||||||
typedef typename MeshType::VertexType VertexType;
|
typedef typename MeshType::VertexType VertexType;
|
||||||
typedef typename MeshType::VertexPointer VertexPointer;
|
typedef typename MeshType::VertexPointer VertexPointer;
|
||||||
typedef vcg::face::VFIterator<FaceType> VFIteratorType;
|
typedef vcg::face::VFIterator<FaceType> VFIteratorType;
|
||||||
typedef typename MeshType::CoordType CoordType;
|
typedef typename MeshType::CoordType CoordType;
|
||||||
typedef typename CoordType::ScalarType ScalarType;
|
typedef typename CoordType::ScalarType ScalarType;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -74,11 +73,11 @@ private:
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// \brief Compute principal direction and magnitudo of curvature.
|
/// \brief Compute principal direction and magnitudo of curvature.
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Compute principal direction and magniuto of curvature as describe in the paper:
|
Compute principal direction and magniuto of curvature as describe in the paper:
|
||||||
@InProceedings{bb33922,
|
@InProceedings{bb33922,
|
||||||
author = "G. Taubin",
|
author = "G. Taubin",
|
||||||
title = "Estimating the Tensor of Curvature of a Surface from a
|
title = "Estimating the Tensor of Curvature of a Surface from a
|
||||||
Polyhedral Approximation",
|
Polyhedral Approximation",
|
||||||
|
@ -336,13 +335,13 @@ If pointVSfaceInt==false the covariance is computed by (analytic)integration ove
|
||||||
|
|
||||||
// Jacobi(A, eigenvalues , eigenvectors, nrot);
|
// Jacobi(A, eigenvalues , eigenvectors, nrot);
|
||||||
|
|
||||||
Eigen::Matrix3d AA;
|
Eigen::Matrix3d AA;
|
||||||
A.ToEigenMatrix(AA);
|
A.ToEigenMatrix(AA);
|
||||||
Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eig(AA);
|
Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eig(AA);
|
||||||
Eigen::Vector3d c_val = eig.eigenvalues();
|
Eigen::Vector3d c_val = eig.eigenvalues();
|
||||||
Eigen::Matrix3d c_vec = eig.eigenvectors(); // eigenvector are stored as columns.
|
Eigen::Matrix3d c_vec = eig.eigenvectors(); // eigenvector are stored as columns.
|
||||||
eigenvectors.FromEigenMatrix(c_vec);
|
eigenvectors.FromEigenMatrix(c_vec);
|
||||||
eigenvalues.FromEigenVector(c_val);
|
eigenvalues.FromEigenVector(c_val);
|
||||||
// EV.transposeInPlace();
|
// EV.transposeInPlace();
|
||||||
// ev.FromEigenVector(c_val);
|
// ev.FromEigenVector(c_val);
|
||||||
|
|
||||||
|
@ -520,174 +519,174 @@ static void MeanAndGaussian(MeshType & m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Update the mean and the gaussian curvature of a vertex.
|
/// \brief Update the mean and the gaussian curvature of a vertex.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The function uses the VF adiacency to walk around the vertex.
|
The function uses the VF adiacency to walk around the vertex.
|
||||||
\return It will return the voronoi area around the vertex. If (norm == true) the mean and the gaussian curvature are normalized.
|
\return It will return the voronoi area around the vertex. If (norm == true) the mean and the gaussian curvature are normalized.
|
||||||
Based on the paper <a href="http://www2.in.tu-clausthal.de/~hormann/papers/Dyn.2001.OTU.pdf"> <em> "Optimizing 3d triangulations using discrete curvature analysis" </em> </a>
|
Based on the paper <a href="http://www2.in.tu-clausthal.de/~hormann/papers/Dyn.2001.OTU.pdf"> <em> "Optimizing 3d triangulations using discrete curvature analysis" </em> </a>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static float ComputeSingleVertexCurvature(VertexPointer v, bool norm = true)
|
static float ComputeSingleVertexCurvature(VertexPointer v, bool norm = true)
|
||||||
{
|
{
|
||||||
VFIteratorType vfi(v);
|
VFIteratorType vfi(v);
|
||||||
float A = 0;
|
float A = 0;
|
||||||
|
|
||||||
v->Kh() = 0;
|
v->Kh() = 0;
|
||||||
v->Kg() = 2 * M_PI;
|
v->Kg() = 2 * M_PI;
|
||||||
|
|
||||||
while (!vfi.End()) {
|
while (!vfi.End()) {
|
||||||
if (!vfi.F()->IsD()) {
|
if (!vfi.F()->IsD()) {
|
||||||
FacePointer f = vfi.F();
|
FacePointer f = vfi.F();
|
||||||
int i = vfi.I();
|
int i = vfi.I();
|
||||||
VertexPointer v0 = f->V0(i), v1 = f->V1(i), v2 = f->V2(i);
|
VertexPointer v0 = f->V0(i), v1 = f->V1(i), v2 = f->V2(i);
|
||||||
|
|
||||||
float ang0 = math::Abs(Angle(v1->P() - v0->P(), v2->P() - v0->P() ));
|
float ang0 = math::Abs(Angle(v1->P() - v0->P(), v2->P() - v0->P() ));
|
||||||
float ang1 = math::Abs(Angle(v0->P() - v1->P(), v2->P() - v1->P() ));
|
float ang1 = math::Abs(Angle(v0->P() - v1->P(), v2->P() - v1->P() ));
|
||||||
float ang2 = M_PI - ang0 - ang1;
|
float ang2 = M_PI - ang0 - ang1;
|
||||||
|
|
||||||
float s01 = SquaredDistance(v1->P(), v0->P());
|
float s01 = SquaredDistance(v1->P(), v0->P());
|
||||||
float s02 = SquaredDistance(v2->P(), v0->P());
|
float s02 = SquaredDistance(v2->P(), v0->P());
|
||||||
|
|
||||||
// voronoi cell of current vertex
|
// voronoi cell of current vertex
|
||||||
if (ang0 >= M_PI/2)
|
if (ang0 >= M_PI/2)
|
||||||
A += (0.5f * DoubleArea(*f) - (s01 * tan(ang1) + s02 * tan(ang2)) / 8.0 );
|
A += (0.5f * DoubleArea(*f) - (s01 * tan(ang1) + s02 * tan(ang2)) / 8.0 );
|
||||||
else if (ang1 >= M_PI/2)
|
else if (ang1 >= M_PI/2)
|
||||||
A += (s01 * tan(ang0)) / 8.0;
|
A += (s01 * tan(ang0)) / 8.0;
|
||||||
else if (ang2 >= M_PI/2)
|
else if (ang2 >= M_PI/2)
|
||||||
A += (s02 * tan(ang0)) / 8.0;
|
A += (s02 * tan(ang0)) / 8.0;
|
||||||
else // non obctuse triangle
|
else // non obctuse triangle
|
||||||
A += ((s02 / tan(ang1)) + (s01 / tan(ang2))) / 8.0;
|
A += ((s02 / tan(ang1)) + (s01 / tan(ang2))) / 8.0;
|
||||||
|
|
||||||
// gaussian curvature update
|
// gaussian curvature update
|
||||||
v->Kg() -= ang0;
|
v->Kg() -= ang0;
|
||||||
|
|
||||||
// mean curvature update
|
// mean curvature update
|
||||||
ang1 = math::Abs(Angle(f->N(), v1->N()));
|
ang1 = math::Abs(Angle(f->N(), v1->N()));
|
||||||
ang2 = math::Abs(Angle(f->N(), v2->N()));
|
ang2 = math::Abs(Angle(f->N(), v2->N()));
|
||||||
v->Kh() += ( (math::Sqrt(s01) / 2.0) * ang1 +
|
v->Kh() += ( (math::Sqrt(s01) / 2.0) * ang1 +
|
||||||
(math::Sqrt(s02) / 2.0) * ang2 );
|
(math::Sqrt(s02) / 2.0) * ang2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
++vfi;
|
++vfi;
|
||||||
}
|
}
|
||||||
|
|
||||||
v->Kh() /= 4.0f;
|
v->Kh() /= 4.0f;
|
||||||
|
|
||||||
if(norm) {
|
if(norm) {
|
||||||
if(A <= std::numeric_limits<float>::epsilon()) {
|
if(A <= std::numeric_limits<float>::epsilon()) {
|
||||||
v->Kh() = 0;
|
v->Kh() = 0;
|
||||||
v->Kg() = 0;
|
v->Kg() = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v->Kh() /= A;
|
v->Kh() /= A;
|
||||||
v->Kg() /= A;
|
v->Kg() /= A;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return A;
|
return A;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PerVertex(MeshType & m)
|
static void PerVertex(MeshType & m)
|
||||||
{
|
{
|
||||||
tri::RequireVFAdjacency(m);
|
tri::RequireVFAdjacency(m);
|
||||||
|
|
||||||
for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
||||||
ComputeSingleVertexCurvature(&*vi,false);
|
ComputeSingleVertexCurvature(&*vi,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Compute principal curvature directions and value with normal cycle:
|
Compute principal curvature directions and value with normal cycle:
|
||||||
@inproceedings{CohMor03,
|
@inproceedings{CohMor03,
|
||||||
author = {Cohen-Steiner, David and Morvan, Jean-Marie },
|
author = {Cohen-Steiner, David and Morvan, Jean-Marie },
|
||||||
booktitle = {SCG '03: Proceedings of the nineteenth annual symposium on Computational geometry},
|
booktitle = {SCG '03: Proceedings of the nineteenth annual symposium on Computational geometry},
|
||||||
title - {Restricted delaunay triangulations and normal cycle}
|
title - {Restricted delaunay triangulations and normal cycle}
|
||||||
year = {2003}
|
year = {2003}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void PrincipalDirectionsNormalCycle(MeshType & m){
|
static void PrincipalDirectionsNormalCycle(MeshType & m){
|
||||||
tri::RequireVFAdjacency(m);
|
tri::RequireVFAdjacency(m);
|
||||||
tri::RequireFFAdjacency(m);
|
tri::RequireFFAdjacency(m);
|
||||||
tri::RequirePerFaceNormal(m);
|
tri::RequirePerFaceNormal(m);
|
||||||
|
|
||||||
typename MeshType::VertexIterator vi;
|
typename MeshType::VertexIterator vi;
|
||||||
|
|
||||||
for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
||||||
if(!((*vi).IsD())){
|
if(!((*vi).IsD())){
|
||||||
vcg::Matrix33<ScalarType> m33;m33.SetZero();
|
vcg::Matrix33<ScalarType> m33;m33.SetZero();
|
||||||
face::JumpingPos<typename MeshType::FaceType> p((*vi).VFp(),&(*vi));
|
face::JumpingPos<typename MeshType::FaceType> p((*vi).VFp(),&(*vi));
|
||||||
p.FlipE();
|
p.FlipE();
|
||||||
typename MeshType::VertexType * firstv = p.VFlip();
|
typename MeshType::VertexType * firstv = p.VFlip();
|
||||||
assert(p.F()->V(p.VInd())==&(*vi));
|
assert(p.F()->V(p.VInd())==&(*vi));
|
||||||
|
|
||||||
do{
|
do{
|
||||||
if( p.F() != p.FFlip()){
|
if( p.F() != p.FFlip()){
|
||||||
Point3<ScalarType> normalized_edge = p.F()->V(p.F()->Next(p.VInd()))->cP() - (*vi).P();
|
Point3<ScalarType> normalized_edge = p.F()->V(p.F()->Next(p.VInd()))->cP() - (*vi).P();
|
||||||
ScalarType edge_length = normalized_edge.Norm();
|
ScalarType edge_length = normalized_edge.Norm();
|
||||||
normalized_edge/=edge_length;
|
normalized_edge/=edge_length;
|
||||||
Point3<ScalarType> n1 = p.F()->cN();n1.Normalize();
|
Point3<ScalarType> n1 = p.F()->cN();n1.Normalize();
|
||||||
Point3<ScalarType> n2 = p.FFlip()->cN();n2.Normalize();
|
Point3<ScalarType> n2 = p.FFlip()->cN();n2.Normalize();
|
||||||
ScalarType n1n2 = (n1 ^ n2).dot(normalized_edge);
|
ScalarType n1n2 = (n1 ^ n2).dot(normalized_edge);
|
||||||
n1n2 = std::max(std::min( ScalarType(1.0),n1n2),ScalarType(-1.0));
|
n1n2 = std::max(std::min( ScalarType(1.0),n1n2),ScalarType(-1.0));
|
||||||
ScalarType beta = math::Asin(n1n2);
|
ScalarType beta = math::Asin(n1n2);
|
||||||
m33[0][0] += beta*edge_length*normalized_edge[0]*normalized_edge[0];
|
m33[0][0] += beta*edge_length*normalized_edge[0]*normalized_edge[0];
|
||||||
m33[0][1] += beta*edge_length*normalized_edge[1]*normalized_edge[0];
|
m33[0][1] += beta*edge_length*normalized_edge[1]*normalized_edge[0];
|
||||||
m33[1][1] += beta*edge_length*normalized_edge[1]*normalized_edge[1];
|
m33[1][1] += beta*edge_length*normalized_edge[1]*normalized_edge[1];
|
||||||
m33[0][2] += beta*edge_length*normalized_edge[2]*normalized_edge[0];
|
m33[0][2] += beta*edge_length*normalized_edge[2]*normalized_edge[0];
|
||||||
m33[1][2] += beta*edge_length*normalized_edge[2]*normalized_edge[1];
|
m33[1][2] += beta*edge_length*normalized_edge[2]*normalized_edge[1];
|
||||||
m33[2][2] += beta*edge_length*normalized_edge[2]*normalized_edge[2];
|
m33[2][2] += beta*edge_length*normalized_edge[2]*normalized_edge[2];
|
||||||
}
|
}
|
||||||
p.NextFE();
|
p.NextFE();
|
||||||
}while(firstv != p.VFlip());
|
}while(firstv != p.VFlip());
|
||||||
|
|
||||||
if(m33.Determinant()==0.0){ // degenerate case
|
if(m33.Determinant()==0.0){ // degenerate case
|
||||||
(*vi).K1() = (*vi).K2() = 0.0; continue;}
|
(*vi).K1() = (*vi).K2() = 0.0; continue;}
|
||||||
|
|
||||||
m33[1][0] = m33[0][1];
|
m33[1][0] = m33[0][1];
|
||||||
m33[2][0] = m33[0][2];
|
m33[2][0] = m33[0][2];
|
||||||
m33[2][1] = m33[1][2];
|
m33[2][1] = m33[1][2];
|
||||||
|
|
||||||
Eigen::Matrix3d it;
|
Eigen::Matrix3d it;
|
||||||
m33.ToEigenMatrix(it);
|
m33.ToEigenMatrix(it);
|
||||||
Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eig(it);
|
Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eig(it);
|
||||||
Eigen::Vector3d c_val = eig.eigenvalues();
|
Eigen::Vector3d c_val = eig.eigenvalues();
|
||||||
Eigen::Matrix3d c_vec = eig.eigenvectors();
|
Eigen::Matrix3d c_vec = eig.eigenvectors();
|
||||||
|
|
||||||
Point3<ScalarType> lambda;
|
Point3<ScalarType> lambda;
|
||||||
Matrix33<ScalarType> vect;
|
Matrix33<ScalarType> vect;
|
||||||
vect.FromEigenMatrix(c_vec);
|
vect.FromEigenMatrix(c_vec);
|
||||||
lambda.FromEigenVector(c_val);
|
lambda.FromEigenVector(c_val);
|
||||||
|
|
||||||
ScalarType bestNormal = 0;
|
ScalarType bestNormal = 0;
|
||||||
int bestNormalIndex = -1;
|
int bestNormalIndex = -1;
|
||||||
for(int i = 0; i < 3; ++i)
|
for(int i = 0; i < 3; ++i)
|
||||||
{
|
{
|
||||||
float agreeWithNormal = fabs((*vi).N().Normalize().dot(vect.GetColumn(i)));
|
float agreeWithNormal = fabs((*vi).N().Normalize().dot(vect.GetColumn(i)));
|
||||||
if( agreeWithNormal > bestNormal )
|
if( agreeWithNormal > bestNormal )
|
||||||
{
|
{
|
||||||
bestNormal= agreeWithNormal;
|
bestNormal= agreeWithNormal;
|
||||||
bestNormalIndex = i;
|
bestNormalIndex = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int maxI = (bestNormalIndex+2)%3;
|
int maxI = (bestNormalIndex+2)%3;
|
||||||
int minI = (bestNormalIndex+1)%3;
|
int minI = (bestNormalIndex+1)%3;
|
||||||
if(fabs(lambda[maxI]) < fabs(lambda[minI])) std::swap(maxI,minI);
|
if(fabs(lambda[maxI]) < fabs(lambda[minI])) std::swap(maxI,minI);
|
||||||
|
|
||||||
(*vi).PD1() = *(Point3<ScalarType>*)(& vect[maxI][0]);
|
(*vi).PD1() = *(Point3<ScalarType>*)(& vect[maxI][0]);
|
||||||
(*vi).PD2() = *(Point3<ScalarType>*)(& vect[minI][0]);
|
(*vi).PD2() = *(Point3<ScalarType>*)(& vect[minI][0]);
|
||||||
(*vi).K1() = lambda[2];
|
(*vi).K1() = lambda[2];
|
||||||
(*vi).K2() = lambda[1];
|
(*vi).K2() = lambda[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PerVertexBasicRadialCrossField(MeshType &m, float anisotropyRatio = 1.0 )
|
static void PerVertexBasicRadialCrossField(MeshType &m, float anisotropyRatio = 1.0 )
|
||||||
{
|
{
|
||||||
tri::RequirePerVertexCurvatureDir(m);
|
tri::RequirePerVertexCurvatureDir(m);
|
||||||
CoordType c=m.bbox.Center();
|
CoordType c=m.bbox.Center();
|
||||||
float maxRad = m.bbox.Diag()/2.0f;
|
float maxRad = m.bbox.Diag()/2.0f;
|
||||||
|
|
||||||
for(int i=0;i<m.vert.size();++i) {
|
for(int i=0;i<m.vert.size();++i) {
|
||||||
CoordType dd = m.vert[i].P()-c;
|
CoordType dd = m.vert[i].P()-c;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue