added method MergeFlatFaces (does what it says). Plus clean-ups.

This commit is contained in:
mtarini 2012-07-18 21:46:12 +00:00
parent 45b0deb7eb
commit 240b88a582
1 changed files with 108 additions and 88 deletions

View File

@ -29,69 +29,89 @@
#include <vcg/simplex/face/jumping_pos.h> #include <vcg/simplex/face/jumping_pos.h>
#include <vcg/space/planar_polygon_tessellation.h> #include <vcg/space/planar_polygon_tessellation.h>
namespace vcg namespace vcg {
{ namespace tri {
namespace tri{ /// \ingroup trimesh
/// \ingroup trimesh
/// \headerfile polygon_support.h vcg/complex/algorithms/polygon_support.h /// \headerfile polygon_support.h vcg/complex/algorithms/polygon_support.h
/// \brief This class is used convert between polygonal meshes and triangular meshes /// \brief This class is used convert between polygonal meshes and triangular meshes
/** /**
This class contains two members that allow to build a triangular mesh from a polygonal mesh This class contains two members that allow to build a triangular mesh from a polygonal mesh
and viceversa. In a trimesh, the generic polygons with n sides are codified represented by tagging the internal edge of the face and viceversa. In a trimesh, the generic polygons with n sides are codified represented by tagging the internal edge of the face
with the SetF. with the SetF.
*/ */
template <class TriMeshType,class PolyMeshType > template <class TriMeshType,class PolyMeshType >
struct PolygonSupport{ struct PolygonSupport{
/**
Import a trianglemesh from a polygon mesh
**/
static void ImportFromPolyMesh(TriMeshType & tm, PolyMeshType & pm){
std::vector<typename PolyMeshType::CoordType> points;
std::vector<int> faces;
// the vertices are the same, simply import them /**
typename PolyMeshType::VertexIterator vi; Given a tri mesh (with per-face normals and FF connectivity),
typename TriMeshType::FaceIterator tfi,tfib ; merges flat faces into larger polygons.
typename TriMeshType ::VertexIterator tvi = Allocator<TriMeshType>::AddVertices(tm,pm.vert.size()); **/
int cnt = 0; static void MergeFlatFaces(TriMeshType & tm, double tolerance = 0.1E-4){
for(tvi = tm.vert.begin(),vi = pm.vert.begin(); tvi != tm.vert.end(); ++tvi,++vi,++cnt) typedef typename TriMeshType::CoordType::ScalarType Scalar;
if(!(*vi).IsD()) (*tvi).ImportData(*vi); else vcg::tri::Allocator<TriMeshType>::DeleteVertex(tm,(*tvi)); typedef typename TriMeshType::FaceIterator FaceIterator;
typedef typename TriMeshType::FaceType FaceType;
typename PolyMeshType::FaceIterator fi; Scalar minDist = 1 - Scalar(tolerance);
for(fi = pm.face.begin(); fi != pm.face.end(); ++fi) for (FaceIterator fi=tm.face.begin(); fi!=tm.face.end(); fi++) {
if(!((*fi).IsD())){ FaceType *fa = &*fi;
points.clear(); for (int w=0; w<3; w++) {
for(int i = 0; i < (*fi).VN(); ++i) { FaceType *fb = fa->FFp(w);
typename PolyMeshType::VertexType * v = (*fi).V(i); if ( (fb>fa) && (fa->N()*fb->N() > minDist) ) {
points.push_back(v->P()); fa->SetF( w );
fb->SetF( fa->FFi(w) ); // reciprocate
} }
faces.clear();
TessellatePlanarPolygon3(points,faces);
tfib = tfi = Allocator<TriMeshType>::AddFaces(tm,faces.size()/3);
for(int i = 0; tfi != tm.face.end();++tfi){
(*tfi).V(0) = &tm.vert[ (*fi).V( faces[i] ) - &(*pm.vert.begin())];
(*tfi).V(1) = &tm.vert[ (*fi).V( faces[i+1]) - &(*pm.vert.begin())];
(*tfi).V(2) = &tm.vert[ (*fi).V( faces[i+2]) - &(*pm.vert.begin())];
// set the F flags
if( (faces[i]+1)%points.size() != faces[i+1]) (*tfi).SetF(0);
if( (faces[i+1]+1)%points.size() != faces[i+2]) (*tfi).SetF(1);
if( (faces[i+2]+1)%points.size() != faces[i]) (*tfi).SetF(2);
i+=3;
}
} }
} }
}
/** /**
Import a polygon mesh from a triangle mesh Import a trianglemesh from a polygon mesh
**/ **/
static void ImportFromTriMesh( PolyMeshType & pm, TriMeshType & tm){ static void ImportFromPolyMesh(TriMeshType & tm, PolyMeshType & pm){
std::vector<typename PolyMeshType::CoordType> points;
std::vector<int> faces;
// the vertices are the same, simply import them
typename PolyMeshType::VertexIterator vi;
typename TriMeshType::FaceIterator tfi,tfib ;
typename TriMeshType ::VertexIterator tvi = Allocator<TriMeshType>::AddVertices(tm,pm.vert.size());
int cnt = 0;
for(tvi = tm.vert.begin(),vi = pm.vert.begin(); tvi != tm.vert.end(); ++tvi,++vi,++cnt)
if(!(*vi).IsD()) (*tvi).ImportData(*vi); else vcg::tri::Allocator<TriMeshType>::DeleteVertex(tm,(*tvi));
typename PolyMeshType::FaceIterator fi;
for(fi = pm.face.begin(); fi != pm.face.end(); ++fi)
if(!((*fi).IsD())){
points.clear();
for(int i = 0; i < (*fi).VN(); ++i) {
typename PolyMeshType::VertexType * v = (*fi).V(i);
points.push_back(v->P());
}
faces.clear();
TessellatePlanarPolygon3(points,faces);
tfib = tfi = Allocator<TriMeshType>::AddFaces(tm,faces.size()/3);
for(int i = 0; tfi != tm.face.end();++tfi){
(*tfi).V(0) = &tm.vert[ (*fi).V( faces[i] ) - &(*pm.vert.begin())];
(*tfi).V(1) = &tm.vert[ (*fi).V( faces[i+1]) - &(*pm.vert.begin())];
(*tfi).V(2) = &tm.vert[ (*fi).V( faces[i+2]) - &(*pm.vert.begin())];
// set the F flags
if( (faces[i]+1)%points.size() != faces[i+1]) (*tfi).SetF(0);
if( (faces[i+1]+1)%points.size() != faces[i+2]) (*tfi).SetF(1);
if( (faces[i+2]+1)%points.size() != faces[i]) (*tfi).SetF(2);
i+=3;
}
}
}
/**
Import a polygon mesh from a triangle mesh
**/
static void ImportFromTriMesh( PolyMeshType & pm, TriMeshType & tm){
// the vertices are the same, simply import them // the vertices are the same, simply import them
int cnt = 0; int cnt = 0;
@ -140,43 +160,43 @@ namespace vcg
// TODO // TODO
} }
} }
// Given a facepointer, it build a vector with all the vertex pointer // Given a facepointer, it build a vector with all the vertex pointer
// around the polygonal face determined by the current FAUX-EDGE markings // around the polygonal face determined by the current FAUX-EDGE markings
// It assumes that the mesh is 2Manifold and has FF adjacency already computed // It assumes that the mesh is 2Manifold and has FF adjacency already computed
// NOTE: All the faces touched are marked as visited. (so for example you can avoid to get twice the same polygon) // NOTE: All the faces touched are marked as visited. (so for example you can avoid to get twice the same polygon)
static void ExtractPolygon(typename TriMeshType::FacePointer tfp, std::vector<typename TriMeshType::VertexPointer> &vs) static void ExtractPolygon(typename TriMeshType::FacePointer tfp, std::vector<typename TriMeshType::VertexPointer> &vs)
{
vs.clear();
// find a non tagged edge
int se = -1;
for(int i=0; i<3; i++) if (!( tfp->IsF(i))) { se = i; break;}
// all faux edges return an empty vertex vector!
if(se==-1) return;
// initialize a pos on the first non faux edge
typename TriMeshType::VertexPointer v0 = tfp->V(se);
vcg::face::Pos<typename TriMeshType::FaceType> p(tfp,se,v0);
vcg::face::Pos<typename TriMeshType::FaceType> start(p);
do
{ {
vs.clear(); assert(!p.F()->IsF(p.E()));
// find a non tagged edge vs.push_back(p.F()->V(p.E()));
int se = -1; p.FlipE();
for(int i=0; i<3; i++) if (!( tfp->IsF(i))) { se = i; break;}
// all faux edges return an empty vertex vector! while( p.F()->IsF(p.E()) )
if(se==-1) return; {
p.F()->SetV();
// initialize a pos on the first non faux edge p.FlipF();
typename TriMeshType::VertexPointer v0 = tfp->V(se); p.FlipE();
}
vcg::face::Pos<typename TriMeshType::FaceType> p(tfp,se,v0); p.FlipV();
vcg::face::Pos<typename TriMeshType::FaceType> start(p); } while(p!=start);
}
do
{
assert(!p.F()->IsF(p.E()));
vs.push_back(p.F()->V(p.E()));
p.FlipE();
while( p.F()->IsF(p.E()) )
{
p.F()->SetV();
p.FlipF();
p.FlipE();
}
p.FlipV();
} while(p!=start);
}
}; // end of struct }; // end of struct
}} // end namespace vcg::tri }} // end namespace vcg::tri