Commit 7247415b authored by Sylvain Thery's avatar Sylvain Thery

Add algo to restore orientation of meshes imported from broken files

parent 0345ab1b
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your *
* option) any later version. *
* *
* This library 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 Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this library; if not, write to the Free Software Foundation, *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
* Web site: http://cgogn.unistra.fr/ *
* Contact information: cgogn@unistra.fr *
* *
*******************************************************************************/
#ifndef __UNIFORM_ORIENTATION__
#define __UNIFORM_ORIENTATION__
namespace CGoGN
{
namespace Algo
{
namespace Topo
{
/**
* @brief Restore an uniform orientation on a mesh that has been imported from set of triangle with non uniform orientation
* @param map a Map2 or inherited
* @param faceSeed a dart of a face of the CC to process.
*/
template <typename MAP>
void uniformOrientationCC(MAP& map, Dart faceSeed);
} // namespace Topo
} // namespace Algo
} // namespace CGoGN
#include "uniformOrientation.hpp"
#endif
namespace CGoGN
{
namespace Algo
{
namespace Topo
{
// private function
template <typename MAP>
void reverse2MapFaceKeepPhi2(MAP& map, Dart d)
{
unsigned int first = map.template getEmbedding<VERTEX>(d);
Dart e=d;
do
{
Dart f=map.phi1(e);
unsigned int emb = map.template getEmbedding<VERTEX>(f);
map.template setDartEmbedding<VERTEX>(e,emb);
e =f;
}while (e!=d);
map.template setDartEmbedding<VERTEX>(map.phi_1(d),first);
map.reverseCycle(d);
}
// private function
inline Dart findOtherInCouplesOfDarts(const std::vector<Dart>& couples, Dart d)
{
unsigned int nb = couples.size();
for (unsigned int i=0; i<nb; ++i)
{
if (couples[i] == d)
{
if (i%2 == 0)
return couples[i+1];
//else
return couples[i-1];
}
}
return NIL;
}
template <typename MAP>
void uniformOrientationCC(MAP& map, Dart faceSeed)
{
// first bufferize boundary edges
std::vector<Dart> boundEdges;
TraversorE<MAP> travEdge(map);
for (Dart d=travEdge.begin(); d!= travEdge.end(); d = travEdge.next())
{
if (map.isBoundaryEdge(d))
boundEdges.push_back(d);
}
// store couple of boundary edges the have same embedding
std::vector<Dart> couples;
int nb = boundEdges.size();
int nbm = nb-1;
for (int i=0; i< nbm; ++i)
{
if (boundEdges[i] != NIL)
{
for (int j=i+1; j< nb; ++j)
{
if (boundEdges[j] != NIL)
{
Dart d = boundEdges[i];
Dart d1 = map.phi1(d);
Dart e = boundEdges[j];
Dart e1 = map.phi1(e);
if ((map.template getEmbedding<VERTEX>(d) == map.template getEmbedding<VERTEX>(e)) && (map.template getEmbedding<VERTEX>(d1) == map.template getEmbedding<VERTEX>(e1)))
{
couples.push_back(d);
couples.push_back(e);
boundEdges[j] = NIL; // not using the dart again
j=nb; // out of the loop
}
}
}
}
}
// vector of front propagation for good orientation
std::vector<Dart> propag;
boundEdges.clear();
propag.swap(boundEdges);// reused memory of boundEdges
// vector of front propagation for wrong orientation
std::vector<Dart> propag_inv;
//vector of faces to invert
std::vector<Dart> face2invert;
// optimize memory reserve
propag_inv.reserve(1024);
face2invert.reserve(1024);
DartMarker cmf(map);
cmf.markOrbit<FACE>(faceSeed);
propag.push_back(faceSeed);
while (!propag.empty() || !propag_inv.empty())
{
if (!propag.empty())
{
Dart f = propag.back();
propag.pop_back();
Dart d = f;
do
{
Dart e = map.phi2(d);
if (map.isBoundaryMarked2(e))
{
e = findOtherInCouplesOfDarts(couples,d);
if (e!=NIL)
{
if (!cmf.isMarked(e))
{
propag_inv.push_back(e);
face2invert.push_back(e);
cmf.markOrbit<FACE>(e);
}
cmf.mark(map.phi2(e));// use cmf also to mark boudary cycle to invert
}
}
else
{
if (!cmf.isMarked(e))
{
propag.push_back(e);
cmf.markOrbit<FACE>(e);
}
}
d= map.phi1(d);
} while (d!=f);
}
if (!propag_inv.empty())
{
Dart f = propag_inv.back();
propag_inv.pop_back();
Dart d = f;
do
{
Dart e = map.phi2(d);
if (map.isBoundaryMarked2(e))
{
e = findOtherInCouplesOfDarts(couples,d);
if (e!=NIL)
{
if (!cmf.isMarked(e))
{
propag.push_back(e);
cmf.markOrbit<FACE>(e);
}
cmf.mark(map.phi2(d));// use cmf also to mark boudary cycle to invert
}
}
else
{
if (!cmf.isMarked(e))
{
propag_inv.push_back(e);
face2invert.push_back(e);
cmf.markOrbit<FACE>(e);
}
}
d= map.phi1(d); // traverse all edges of face
} while (d!=f);
}
}
// reverse all faces of the wrong orientation
for (std::vector<Dart>::iterator id=face2invert.begin(); id!=face2invert.end(); ++id)
reverse2MapFaceKeepPhi2<MAP>(map,*id);
// reverse the boundary cycles that bound reverse faces
for (std::vector<Dart>::iterator id=couples.begin(); id!=couples.end(); ++id)
{
Dart e = map.phi2(*id);
if (cmf.isMarked(e)) // check cmf for wrong orientation
{
reverse2MapFaceKeepPhi2<MAP>(map,e);
cmf.unmarkOrbit<FACE>(e);
}
}
// sew the faces that correspond to couples of boundary edges
for (std::vector<Dart>::iterator id=couples.begin(); id!=couples.end(); ++id)// second ++ inside !
{
Dart d = *id++;
Dart e = *id;
map.sewFaces(d,e);
}
}
} // namespace Topo
} // namespace Algo
} // namespace CGoGN
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