vcglib/wrap/miq/core/vertex_indexing.h

444 lines
14 KiB
C++

#ifndef MIQ_VERTEX_INDEXING
#define MIQ_VERTEX_INDEXING
#include <vcg/complex/complex.h>
#include <vcg/simplex/face/pos.h>
#include <vcg/simplex/face/jumping_pos.h>
#include <vcg/simplex/face/topology.h>
struct SeamInfo
{
int v0,v0p,v1,v1p;
int integerVar;
//unsigned char RotInt;
unsigned char MMatch;
SeamInfo(int _v0,
int _v1,
int _v0p,
int _v1p,
int _MMatch,
int _integerVar)
{
v0=_v0;
v1=_v1;
v0p=_v0p;
v1p=_v1p;
integerVar=_integerVar;
MMatch=_MMatch;
}
SeamInfo(const SeamInfo &S1)
{
v0=S1.v0;
v1=S1.v1;
v0p=S1.v0p;
v1p=S1.v1p;
integerVar=S1.integerVar;
MMatch=S1.MMatch;
}
};
struct MeshSystemInfo
{
///total number of scalar variables
int num_scalar_variables;
////number of vertices variables
int num_vert_variables;
///num of integer for cuts
int num_integer_cuts;
///this are used for drawing purposes
std::vector<SeamInfo> EdgeSeamInfo;
///this are values of integer variables after optimization
std::vector<int> IntegerValues;
};
template <class MeshType>
class VertexIndexing
{
private:
typedef typename MeshType::ScalarType ScalarType;
typedef typename MeshType::FaceType FaceType;
typedef typename MeshType::VertexType VertexType;
typedef typename MeshType::CoordType CoordType;
typedef typename MeshType::FaceIterator FaceIterator;
MeshType *mesh;
///this maps back index to vertices
std::vector<VertexType*> IndexToVert;
///this maps the integer for edge
typename MeshType::template PerFaceAttributeHandle<vcg::Point3i> Handle_Integer;
///per face indexes of vertex in the solver
typename MeshType::template PerFaceAttributeHandle<vcg::Point3i> HandleS_Index;
///per face per edge of mmatch in the solver
typename MeshType::template PerFaceAttributeHandle<vcg::Point3i> Handle_MMatch;
///per vertex variable indexes
typename MeshType::template PerVertexAttributeHandle<std::vector<int> > HandleV_Integer;
///per vertex singular or not
typename MeshType::template PerVertexAttributeHandle<bool> Handle_Singular;
///per vertex degree of a singularity
typename MeshType::template PerVertexAttributeHandle<int> Handle_SingularDegree;
///seam per face
typename MeshType::template PerFaceAttributeHandle<vcg::Point3<bool> > Handle_Seams;
///this handle for mesh
typename MeshType::template PerMeshAttributeHandle<MeshSystemInfo> Handle_SystemInfo;
///this are used for drawing purposes
std::vector<VertexType*> duplicated;
void FirstPos(const VertexType* v,FaceType *&f,int &edge)
{
f=v->cVFp();
edge=v->cVFi();
}
int AddNewIndex(VertexType* v0)
{
Handle_SystemInfo().num_scalar_variables++;
HandleV_Integer[v0].push_back(Handle_SystemInfo().num_scalar_variables);
IndexToVert.push_back(v0);
return Handle_SystemInfo().num_scalar_variables;
}
bool HasIndex(int indexVert,int indexVar)
{
for (unsigned int i=0;i<HandleV_Integer[indexVert].size();i++)
if (HandleV_Integer[indexVert][i]==indexVar)return true;
return false;
}
bool HasIndex(VertexType* v0,int indexVar)
{
for (unsigned int i=0;i<HandleV_Integer[v0].size();i++)
if (HandleV_Integer[v0][i]==indexVar)return true;
return false;
}
void GetSeamInfo(const FaceType *f0,
const FaceType *f1,
const int indexE,
int &v0,int &v1,
int &v0p,int &v1p,
unsigned char &_MMatch,
int &integerVar)
{
int edgef0=indexE;
v0=HandleS_Index[f0][edgef0];
v1=HandleS_Index[f0][(edgef0+1)%3];
////get the index on opposite side
assert(f0->cFFp(edgef0)==f1);
int edgef1=f0->cFFi(edgef0);
v1p=HandleS_Index[f1][edgef1];
v0p=HandleS_Index[f1][(edgef1+1)%3];
integerVar=Handle_Integer[f0][edgef0];
_MMatch=Handle_MMatch[f0][edgef0];
assert(f0->cV0(edgef0)==f1->cV1(edgef1));
assert(f0->cV1(edgef0)==f1->cV0(edgef1));
}
bool IsSeam(FaceType *f0,FaceType *f1)
{
for (int i=0;i<3;i++)
{
FaceType *f_clos=f0->FFp(i);
assert(!f_clos->IsD()); ///check not deleted
if (f_clos==f0)continue;///border
if(f_clos==f1)
return(Handle_Seams[f0][i]);
}
assert(0);
return false;
}
///find initial position of the pos to
// assing face to vert inxex correctly
void FindInitialPos(const VertexType * vert,
int &edge,
FaceType *&face)
{
FaceType *f_init;
int edge_init;
FirstPos(vert,f_init,edge_init);
vcg::face::JumpingPos<FaceType> VFI(f_init,edge_init);
bool vertexB=vert->IsB();
bool possible_split=false;
bool complete_turn=false;
do
{
FaceType *curr_f=VFI.F();
int curr_edge=VFI.E();
VFI.NextFE();
FaceType *next_f=VFI.F();
///test if I've just crossed a border
bool on_border=(curr_f->FFp(curr_edge)==curr_f);
//bool mismatch=false;
bool seam=false;
///or if I've just crossed a seam
///if I'm on a border I MUST start from the one next t othe border
if (!vertexB)
//seam=curr_f->IsSeam(next_f);
seam=IsSeam(curr_f,next_f);
if (vertexB)
assert(!Handle_Singular[vert]);
;
//assert(!vert->IsSingular());
possible_split=((on_border)||(seam));
complete_turn=(next_f==f_init);
}while ((!possible_split)&&(!complete_turn));
face=VFI.F();
edge=VFI.E();
///test that is not on a border
//assert(face->FFp(edge)!=face);
}
///intialize the mapping given an initial pos
///whih must be initialized with FindInitialPos
void MapIndexes(VertexType * vert,
int &edge_init,
FaceType *&f_init)
{
///check that is not on border..
///in such case maybe it's non manyfold
///insert an initial index
int curr_index=AddNewIndex(vert);
///and initialize the jumping pos
vcg::face::JumpingPos<FaceType> VFI(f_init,edge_init);
bool complete_turn=false;
do
{
FaceType *curr_f=VFI.F();
int curr_edge=VFI.E();
///assing the current index
HandleS_Index[curr_f][curr_edge]=curr_index;
VFI.NextFE();
FaceType *next_f=VFI.F();
///test if I've finiseh with the face exploration
complete_turn=(next_f==f_init);
///or if I've just crossed a mismatch
if (!complete_turn)
{
bool seam=false;
//seam=curr_f->IsSeam(next_f);
seam=IsSeam(curr_f,next_f);
if (seam)
{
///then add a new index
curr_index=AddNewIndex(vert);
}
}
}while (!complete_turn);
}
///intialize the mapping for a given vertex
void InitMappingSeam(VertexType *vert)
{
///first rotate until find the first pos after a mismatch
///or a border or return to the first position...
FaceType *f_init=vert->VFp();
int indexE=vert->VFi();
vcg::face::JumpingPos<FaceType> VFI(f_init,indexE);
int edge_init;
FaceType *face_init;
FindInitialPos(vert,edge_init,face_init);
MapIndexes(vert,edge_init,face_init);
}
///intialize the mapping for a given sampled mesh
void InitMappingSeam()
{
//num_scalar_variables=-1;
Handle_SystemInfo().num_scalar_variables=-1;
for (unsigned int i=0;i<mesh->vert.size();i++)
if (!mesh->vert[i].IsD())
InitMappingSeam(&mesh->vert[i]);
for (unsigned int j=0;j<mesh->vert.size();j++)
{
VertexType *v= &(mesh->vert[j]);
if (!v->IsD()){
assert(HandleV_Integer[j].size()>0);
if (HandleV_Integer[j].size()>1)
duplicated.push_back(v);
}
}
}
///initialized mapping structures if are not already initialized
void AddAttributesIfNeeded()
{
IndexToVert.clear();
///other per mesh attributes
///see if already exists otherwise it creates it
Handle_SystemInfo=vcg::tri::Allocator<MeshType>::template GetPerMeshAttribute<MeshSystemInfo>(*mesh,std::string("SystemInfo"));
Handle_SystemInfo().num_scalar_variables=0;
Handle_SystemInfo().num_vert_variables=0;
Handle_SystemInfo().num_integer_cuts=0;
duplicated.clear();
HandleS_Index = vcg::tri::Allocator<MeshType>::template GetPerFaceAttribute<vcg::Point3i>(*mesh,std::string("SystemIndex"));
Handle_Integer= vcg::tri::Allocator<MeshType>::template GetPerFaceAttribute<vcg::Point3i>(*mesh,std::string("Integer"));
HandleV_Integer=vcg::tri::Allocator<MeshType>::template GetPerVertexAttribute<std::vector<int> >(*mesh,std::string("VertInteger"));
bool HasHandleMMatch=vcg::tri::HasPerFaceAttribute(*mesh,std::string("MissMatch"));
assert(HasHandleMMatch);
Handle_MMatch = vcg::tri::Allocator<MeshType>::template FindPerFaceAttribute<vcg::Point3i>(*mesh,std::string("MissMatch"));
bool HasHandleSingularity=vcg::tri::HasPerVertexAttribute(*mesh,std::string("Singular"));
assert(HasHandleSingularity);
Handle_Singular=vcg::tri::Allocator<MeshType>::template FindPerVertexAttribute<bool>(*mesh,std::string("Singular"));
bool HasHandleSingularityDegree=vcg::tri::HasPerVertexAttribute(*mesh,std::string("SingularityDegree"));
assert(HasHandleSingularityDegree);
Handle_SingularDegree=vcg::tri::Allocator<MeshType>::template FindPerVertexAttribute<int>(*mesh,std::string("SingularityDegree"));
bool HasHandleSeams=vcg::tri::HasPerFaceAttribute(*mesh,std::string("Seams"));
assert(HasHandleSeams);
Handle_Seams=vcg::tri::Allocator<MeshType>::template FindPerFaceAttribute<vcg::Point3<bool> >(*mesh,std::string("Seams"));
}
///test consistency of face variables per vert mapping
void TestSeamMapping(FaceType *f)
{
for (int k=0;k<3;k++)
{
int indexV=HandleS_Index[f][k];
VertexType *v=f->V(k);
bool has_index=HasIndex(v,indexV);
assert(has_index);
}
}
///test consistency of face variables per vert mapping
void TestSeamMapping(int indexVert)
{
VertexType *v=&mesh->vert[indexVert];
for (unsigned int k=0;k<HandleV_Integer[indexVert].size();k++)
{
int indexV=HandleV_Integer[indexVert][k];
///get faces sharing vertex
std::vector<FaceType*> faces;
std::vector<int> indexes;
vcg::face::VFStarVF(v,faces,indexes);
for (unsigned int j=0;j<faces.size();j++)
{
FaceType *f=faces[j];
int index=indexes[j];
assert(!f->IsD());
assert(f->V(index)==v);
assert((index>=0)&&(index<3));
if (HandleS_Index[f][index]==indexV)
return;
}
}
assert(0);
}
///check consistency of variable mapping across seams
void TestSeamMapping()
{
printf("\n TESTING SEAM INDEXES \n");
///test F-V mapping
for (unsigned int j=0;j<mesh->face.size();j++)
{
FaceType *f=&mesh->face[j];
if (f->IsD()) continue;
TestSeamMapping(f);
}
///TEST V-F MAPPING
for (unsigned int j=0;j<mesh->vert.size();j++)
{
VertexType *v=&mesh->vert[j];
if (v->IsD()) continue;
TestSeamMapping(j);
}
}
public:
///vertex to variable mapping
void InitMapping()
{
//use_direction_field=_use_direction_field;
IndexToVert.clear();
duplicated.clear();
InitMappingSeam();
Handle_SystemInfo().num_vert_variables=Handle_SystemInfo().num_scalar_variables+1;
///end testing...
TestSeamMapping();
}
void InitFaceIntegerVal()
{
Handle_SystemInfo().num_integer_cuts=0;
for (unsigned int j=0;j<mesh->face.size();j++)
{
FaceType *f=&mesh->face[j];
if (f->IsD())continue;
for (int k=0;k<3;k++)
{
if (Handle_Seams[f][k])
{
Handle_Integer[j][k]=Handle_SystemInfo().num_integer_cuts;
Handle_SystemInfo().num_integer_cuts++;
}
else
Handle_Integer[j][k]=-1;
}
}
}
void InitSeamInfo()
{
Handle_SystemInfo().EdgeSeamInfo.clear();
for (unsigned int j=0;j<mesh->face.size();j++)
{
FaceType *f0=&mesh->face[j];
if (f0->IsD())continue;
for (int k=0;k<3;k++)
{
FaceType *f1=f0->FFp(k);
if (f1==f0)continue;
bool seam=Handle_Seams[f0][k];//f0->IsSeam(k);
if ((seam) )//&&(f0<f1))
{
int v0,v0p,v1,v1p;
unsigned char MM;
int integerVar;
GetSeamInfo(f0,f1,k,v0,v1,v0p,v1p,MM,integerVar);
Handle_SystemInfo().EdgeSeamInfo.push_back(SeamInfo(v0,v1,v0p,v1p,MM,integerVar));
}
}
}
}
void Init(MeshType *_mesh){mesh=_mesh;AddAttributesIfNeeded();}
VertexIndexing(){mesh=NULL;}
};
#endif