Commit e96349d3 authored by Jan Möbius's avatar Jan Möbius

Updated flip function to work in all selection cases. refs #1002

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@15734 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 0328a683
......@@ -106,9 +106,9 @@ MeshRepairPlugin::flipOrientation(int _objectId) {
PluginFunctions::getMesh(_objectId,polyMesh);
if (triMesh)
flipOrientationSelected(triMesh);
flipOrientation(*triMesh);
else if (polyMesh)
flipOrientationSelected(polyMesh);
flipOrientation(*polyMesh);
else
emit log( LOGERR,tr("Unsupported Object Type for normal flipping!") );
......
......@@ -322,13 +322,14 @@ private:
/** \brief flip orientation of selected faces.
*
* flips the orientation of selected faces.
* for correct topology, some vertices are added
* flips the orientation of selected faces or if nothing is selected, the whole mesh is flipped
* for correct topology, some vertices may be duplicated
*
* @param _mesh target mesh
*
*/
template<typename MeshT>
void flipOrientationSelected(MeshT *_mesh);
void flipOrientation(MeshT& _mesh);
public slots:
......
......@@ -5,76 +5,158 @@
//-----------------------------------------------------------------------------
template<typename MeshT>
void MeshRepairPlugin::flipOrientationSelected(MeshT *_mesh)
void MeshRepairPlugin::flipOrientation(MeshT& _mesh)
{
typename MeshT::FaceIter f_it, f_end = _mesh->faces_end();
std::vector< typename MeshT::VertexHandle > handles;
std::vector< uint > valence;
const unsigned int n_VerticesPerFace = _mesh->is_trimesh() ? 3 : 4;
std::vector< unsigned int > valence;
std::vector< typename MeshT::VertexHandle > vhandles;
handles.reserve( _mesh->n_faces() * n_VerticesPerFace );
valence.reserve( _mesh->n_faces() );
OpenMesh::FPropHandleT< bool > orientation; //inidcates the orientation. true = new orientation. false = old orientation
if ( !_mesh->get_property_handle(orientation,"orientation") )
_mesh->add_property(orientation, "orientation");
for (f_it = _mesh->faces_begin(); f_it != f_end ; ++f_it) {
bool selected = false;
if (_mesh->status(f_it).selected())
{
// Collect vertex handles
typename MeshT::FaceVertexIter fv_it = _mesh->fv_iter(f_it);
// Check if a face is selected
for (typename MeshT::FaceIter f_it = _mesh.faces_begin(); f_it != _mesh.faces_end() ; ++f_it)
if ( _mesh.status(f_it).selected() ) {
selected = true;
break;
}
// Two ways to go
// if something is selected, we have to duplicate some vertices in order to get a manifold mesh
if ( selected ) {
// Tag all vertices adjacent to selected faces
for (typename MeshT::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end(); ++v_it) {
bool tagged = false;
for (typename MeshT::VertexFaceIter vf_it = _mesh.vf_iter(v_it); !tagged && vf_it; ++vf_it)
if (_mesh.status(vf_it).selected())
tagged = true;
_mesh.status(v_it).set_tagged(tagged);
}
// Remember the vertex mapping for the duplication
OpenMesh::VPropHandleT< typename MeshT::VHandle> vmap;
_mesh.add_property(vmap);
// duplicate vertices that are incident to tagged and un-tagged faces
for (typename MeshT::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end(); ++v_it) {
typename MeshT::VertexHandle vh = v_it.handle();
if (_mesh.status(v_it).tagged() )
for (typename MeshT::VertexFaceIter vf_it = _mesh.vf_iter(v_it); vf_it; ++vf_it)
if (!_mesh.status(vf_it).tagged()) {
typename MeshT::Point tmpPoint = _mesh.point(v_it);
// Duplicate the vertex
vh = _mesh.add_vertex( tmpPoint );
// The next vertex should be tagged
_mesh.status(vh).set_tagged(true);
// The original vertex is already duplicated, so we don't need to do it again!
_mesh.status(v_it).set_tagged(false);
break;
}
_mesh.property(vmap, v_it) = vh;
}
// Delete the old faces and collect their information
for (typename MeshT::FaceIter f_it = _mesh.faces_begin(); f_it != _mesh.faces_end(); ++f_it) {
valence.push_back( _mesh->valence(f_it) );
while( fv_it) {
handles.push_back( fv_it.handle() );
++fv_it;
if (_mesh.status(f_it).selected()) {
// Collect vertex handles
typename MeshT::FaceVertexIter fv_it = _mesh.fv_iter(f_it);
valence.push_back(_mesh.valence(f_it));
while (fv_it) {
vhandles.push_back(fv_it.handle());
++fv_it;
}
// delete the corresponding face
_mesh.delete_face(f_it, false);
}
// delete the corresponding face
_mesh->delete_face(f_it, false);
}
else
{
_mesh->property(orientation,f_it) = false;
// Rebuild the faces in the opposite order
std::size_t pos = 0;
for (std::size_t i = 0; i < valence.size(); i++) {
std::vector<typename MeshT::VertexHandle> faceVertices;
pos += valence[i];
// add valence vertices in the inverse order
for (unsigned int j = 1; j <= valence[i]; ++j)
faceVertices.push_back(_mesh.property(vmap,vhandles[pos - j]) );
typename MeshT::FaceHandle fh = _mesh.add_face(faceVertices);
}
}
// clean the mesh
_mesh->garbage_collection();
_mesh.remove_property(vmap);
// read the faces
std::size_t pos = 0;
} else {
for (std::size_t i=0; i < valence.size(); i++) {
std::vector < typename MeshT::Point > points;
std::vector< typename MeshT::VertexHandle > faceVertices;
// store vertices
points.reserve(_mesh.n_vertices() );
for (typename MeshT::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end(); ++v_it)
points.push_back(_mesh.point(v_it));
pos += valence[i];
// Better approximation of vector size for storing the handles
const unsigned int n_VerticesPerFace = _mesh.is_trimesh() ? 3 : 4;
// add valence vertices in the inverse order
for (unsigned int j = 1 ; j <= valence[i] ; ++j )
{
typename MeshT::VertexHandle handle = handles[pos - j];
// Remember vertex handles for each face and its valence
std::vector< typename MeshT::VertexHandle > vhandles;
vhandles.reserve( _mesh.n_faces() * n_VerticesPerFace);
for (typename MeshT::FaceIter f_it = _mesh.faces_begin(); f_it != _mesh.faces_end(); ++f_it) {
//check, if orientation problems exists. If so, add a new vertex avoiding them
if(_mesh->vf_begin(handle) && !_mesh->property(orientation,_mesh->vf_begin(handle)))
handle = _mesh->add_vertex(_mesh->point(handle));
valence.push_back( _mesh.valence(f_it) );
faceVertices.push_back(handle);
for (typename MeshT::FaceVertexIter fv_it = _mesh.fv_iter(f_it); fv_it; ++fv_it)
vhandles.push_back(fv_it.handle());
}
typename MeshT::FaceHandle fh = _mesh->add_face(faceVertices);
_mesh->property(orientation,fh) = true;
// Remove all entities from the mesh
_mesh.clean();
// Restore vertices
for (unsigned int i = 0; i < points.size(); ++i)
_mesh.add_vertex(points[i]);
// Add back the faces
std::size_t pos = 0;
for (std::size_t i = 0; i < valence.size(); i++) {
std::vector<typename MeshT::VertexHandle> faceVertices;
pos += valence[i];
// add valence vertices in the inverse order
for (unsigned int j = 1; j <= valence[i]; ++j)
faceVertices.push_back(vhandles[pos - j]);
typename MeshT::FaceHandle fh = _mesh.add_face(faceVertices);
}
}
_mesh->remove_property(orientation);
_mesh->update_normals();
_mesh.garbage_collection();
_mesh.update_normals();
}
//-----------------------------------------------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment