Commit 68391422 authored by Matthias Möller's avatar Matthias Möller
Browse files

add fix-topology function

move some gui elements

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@15427 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 44bed7b2
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>456</width> <width>456</width>
<height>795</height> <height>803</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
...@@ -103,6 +103,53 @@ These vertices can usually be removed without destroying the features of the mes ...@@ -103,6 +103,53 @@ These vertices can usually be removed without destroying the features of the mes
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QLabel" name="label_11">
<property name="text">
<string>Snap Boundary:</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item>
<widget class="QPushButton" name="snapBoundaryButton">
<property name="toolTip">
<string>Snaps selected boundary vertices together.</string>
</property>
<property name="text">
<string>Snap</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>max. Distance</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="snapBoundarySpinBox">
<property name="decimals">
<number>6</number>
</property>
<property name="minimum">
<double>0.500000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.500000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</item> </item>
<item> <item>
...@@ -575,6 +622,20 @@ There is no automatic algorithm to fix these foldovers here. So you will have to ...@@ -575,6 +622,20 @@ There is no automatic algorithm to fix these foldovers here. So you will have to
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="label_13">
<property name="text">
<string>Fix Mesh:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="fixMeshButton">
<property name="text">
<string>Fix Topology</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
...@@ -592,55 +653,6 @@ There is no automatic algorithm to fix these foldovers here. So you will have to ...@@ -592,55 +653,6 @@ There is no automatic algorithm to fix these foldovers here. So you will have to
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
<string>Snap Boundary</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item>
<widget class="QPushButton" name="snapBoundaryButton">
<property name="toolTip">
<string>Snaps selected boundary vertices together.</string>
</property>
<property name="text">
<string>Snap</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>max. Distance</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="snapBoundarySpinBox">
<property name="decimals">
<number>6</number>
</property>
<property name="minimum">
<double>0.500000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.500000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
......
...@@ -88,6 +88,7 @@ initializePlugin() ...@@ -88,6 +88,7 @@ initializePlugin()
//Face operations //Face operations
connect(tool_->triangleAspectButton,SIGNAL(clicked()),this,SLOT(slotDetectTriangleAspect())); connect(tool_->triangleAspectButton,SIGNAL(clicked()),this,SLOT(slotDetectTriangleAspect()));
connect(tool_->flipOrientation,SIGNAL(clicked()),this,SLOT(slotFlipOrientation())); connect(tool_->flipOrientation,SIGNAL(clicked()),this,SLOT(slotFlipOrientation()));
connect(tool_->fixMeshButton,SIGNAL(clicked()),this,SLOT(slotFixMesh()));
//Normal operations //Normal operations
connect(tool_->computeNormals,SIGNAL(clicked()),this,SLOT(slotUpdateNormals())); connect(tool_->computeNormals,SIGNAL(clicked()),this,SLOT(slotUpdateNormals()));
...@@ -255,6 +256,15 @@ void MeshRepairPlugin::slotSnapBoundary() ...@@ -255,6 +256,15 @@ void MeshRepairPlugin::slotSnapBoundary()
emit updateView(); emit updateView();
} }
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotFixMesh()
{
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH | DATA_POLY_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
fixTopology(o_it->id());
emit updateView();
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
...@@ -348,6 +358,29 @@ void MeshRepairPlugin::snapBoundary(int _objectId, double _eps) ...@@ -348,6 +358,29 @@ void MeshRepairPlugin::snapBoundary(int _objectId, double _eps)
emit scriptInfo("snapBoundary(" + QString::number(_objectId) + ", " + QString::number(_eps) +")"); emit scriptInfo("snapBoundary(" + QString::number(_objectId) + ", " + QString::number(_eps) +")");
} }
void MeshRepairPlugin::fixTopology(int _objectId)
{
TriMesh* triMesh = 0;
PolyMesh* polyMesh = 0;
PluginFunctions::getMesh(_objectId, triMesh);
PluginFunctions::getMesh(_objectId, polyMesh);
if (triMesh)
fixTopology(triMesh);
else if (polyMesh)
fixTopology(polyMesh);
else
{
emit log(LOGERR, tr("Unsupported Object Type."));
return;
}
emit updatedObject(_objectId, UPDATE_ALL);
emit createBackup(_objectId, "fixTopology", UPDATE_ALL);
emit scriptInfo("fixTopology(" + QString::number(_objectId) + ")");
}
void MeshRepairPlugin::removeSelectedVal3Vertices(int _objectId) { void MeshRepairPlugin::removeSelectedVal3Vertices(int _objectId) {
unsigned int count = 0; unsigned int count = 0;
......
...@@ -165,6 +165,9 @@ private slots: ...@@ -165,6 +165,9 @@ private slots:
/// Button slot /// Button slot
void slotSnapBoundary(); void slotSnapBoundary();
/// Button slot
void slotFixMesh();
//Scripting functions: //Scripting functions:
public slots: public slots:
...@@ -209,6 +212,8 @@ public slots: ...@@ -209,6 +212,8 @@ public slots:
void snapBoundary(int _objectId, double _eps); void snapBoundary(int _objectId, double _eps);
void fixTopology(int _objectId);
private: private:
/** \brief select edges based on length /** \brief select edges based on length
* *
...@@ -247,6 +252,12 @@ private: ...@@ -247,6 +252,12 @@ private:
template<typename MeshT> template<typename MeshT>
static bool sort_less_pair_second(const std::pair<typename MeshT::VertexHandle,double> &lhs,const std::pair<typename MeshT::VertexHandle,double> &rhs); static bool sort_less_pair_second(const std::pair<typename MeshT::VertexHandle,double> &lhs,const std::pair<typename MeshT::VertexHandle,double> &rhs);
/** \brief fixes the orientation and non-manifold problems in a mesh.
* @param _mesh target mesh
*
*/
template<typename MeshT>
void fixTopology(MeshT *_mesh);
public slots: public slots:
QString version() { QString version() {
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
#include "MeshRepairPlugin.hh" #include "MeshRepairPlugin.hh"
//-----------------------------------------------------------------------------
template<typename MeshT> template<typename MeshT>
inline unsigned MeshRepairPlugin::n_verticesPerFace() inline unsigned MeshRepairPlugin::n_verticesPerFace()
{ {
...@@ -10,12 +12,15 @@ inline unsigned MeshRepairPlugin::n_verticesPerFace() ...@@ -10,12 +12,15 @@ inline unsigned MeshRepairPlugin::n_verticesPerFace()
return 4; return 4;
} }
//-----------------------------------------------------------------------------
template<> template<>
inline unsigned MeshRepairPlugin::n_verticesPerFace<TriMesh>() inline unsigned MeshRepairPlugin::n_verticesPerFace<TriMesh>()
{ {
return 3; return 3;
} }
//-----------------------------------------------------------------------------
template<typename MeshT> template<typename MeshT>
void MeshRepairPlugin::flipOrientationSelected(MeshT *_mesh) void MeshRepairPlugin::flipOrientationSelected(MeshT *_mesh)
...@@ -78,12 +83,16 @@ void MeshRepairPlugin::flipOrientationSelected(MeshT *_mesh) ...@@ -78,12 +83,16 @@ void MeshRepairPlugin::flipOrientationSelected(MeshT *_mesh)
_mesh->update_normals(); _mesh->update_normals();
} }
//-----------------------------------------------------------------------------
template<typename MeshT> template<typename MeshT>
bool MeshRepairPlugin::sort_less_pair_second(const std::pair<typename MeshT::VertexHandle,double> &lhs,const std::pair<typename MeshT::VertexHandle,double> &rhs) bool MeshRepairPlugin::sort_less_pair_second(const std::pair<typename MeshT::VertexHandle,double> &lhs,const std::pair<typename MeshT::VertexHandle,double> &rhs)
{ {
return lhs.second < rhs.second; return lhs.second < rhs.second;
} }
//-----------------------------------------------------------------------------
template<typename MeshT> template<typename MeshT>
void MeshRepairPlugin::snapBoundary(MeshT *_mesh, double _eps) void MeshRepairPlugin::snapBoundary(MeshT *_mesh, double _eps)
{ {
...@@ -217,7 +226,6 @@ void MeshRepairPlugin::snapBoundary(MeshT *_mesh, double _eps) ...@@ -217,7 +226,6 @@ void MeshRepairPlugin::snapBoundary(MeshT *_mesh, double _eps)
//try to add new face //try to add new face
std::vector<typename MeshT::VertexHandle> newFace_vertices(f_vertices); std::vector<typename MeshT::VertexHandle> newFace_vertices(f_vertices);
std::replace(newFace_vertices.begin(),newFace_vertices.end(),v_old,v_new); std::replace(newFace_vertices.begin(),newFace_vertices.end(),v_old,v_new);
typename MeshT::FaceHandle faceH = _mesh->add_face(newFace_vertices); typename MeshT::FaceHandle faceH = _mesh->add_face(newFace_vertices);
if (!faceH.is_valid()) if (!faceH.is_valid())
...@@ -239,3 +247,96 @@ void MeshRepairPlugin::snapBoundary(MeshT *_mesh, double _eps) ...@@ -239,3 +247,96 @@ void MeshRepairPlugin::snapBoundary(MeshT *_mesh, double _eps)
_mesh->garbage_collection(); _mesh->garbage_collection();
} }
//-----------------------------------------------------------------------------
template<typename MeshT>
void MeshRepairPlugin::fixTopology(MeshT *_mesh)
{
OpenMesh::FPropHandleT< size_t > component;
if ( !_mesh->get_property_handle(component,"component") )
_mesh->add_property(component, "component");
for (typename MeshT::VertexIter v_iter = _mesh->vertices_begin(); v_iter != _mesh->vertices_end(); ++v_iter)
{
//unmark all faces
for (typename MeshT::VertexFaceIter vf_iter = _mesh->vf_begin(v_iter); vf_iter; ++vf_iter)
_mesh->property(component,vf_iter.handle()) = 0;
size_t componentCount = 1;
//search and isolate new components
//shared vertices will be doublicated
for (typename MeshT::VertexFaceIter vf_iter = _mesh->vf_begin(v_iter); vf_iter; ++vf_iter)
{
//get the first face in the component
std::vector<typename MeshT::FaceHandle> checkNeighbour;
if(_mesh->property(component,vf_iter.handle()) == 0)
{
_mesh->property(component,vf_iter.handle()) = componentCount;
checkNeighbour.push_back(vf_iter.handle());
}
//if a reference face was found, it exists a new component
//and a new vertex is required (except for the first component)
typename MeshT::VertexHandle v_new;
if (componentCount > 1 && !checkNeighbour.empty())
{
typename MeshT::Point p = _mesh->point(v_iter.handle());
v_new = _mesh->add_vertex(p);
}
//check all adjacent faces of our reference
while(!checkNeighbour.empty())
{
typename MeshT::FaceHandle face = checkNeighbour.back();
checkNeighbour.pop_back();
std::vector<typename MeshT::VertexHandle> f_vertices;
//get all neighbour faces of face
for (typename MeshT::FaceVertexIter fv_iter = _mesh->fv_begin(face); fv_iter; ++fv_iter)
{
f_vertices.push_back(fv_iter.handle());
if (fv_iter.handle() != v_iter)
{
//find the next neighbour face over edge v_iter and fv_iter
typename MeshT::FaceHandle nf;
for (typename MeshT::VertexFaceIter nf_iter = _mesh->vf_begin(v_iter); nf_iter && !nf.is_valid(); ++nf_iter)
{
if (nf_iter.handle() != face)
for (typename MeshT::FaceVertexIter nfv_iter = _mesh->fv_begin(nf_iter); nfv_iter && !nf.is_valid(); ++nfv_iter)
if (nfv_iter.handle() == fv_iter.handle())
nf = nf_iter.handle();
}
//if such a face was found, it is in the same component as the reference face
if (nf.is_valid() && !_mesh->property(component,nf))
{
_mesh->property(component,nf) = componentCount;
checkNeighbour.push_back(nf);
}
}
}
//if one face wasn't found in the component = 1 run, then it is a new component, due split it
if (componentCount > 1 && v_new.is_valid())
{
std::replace(f_vertices.begin(),f_vertices.end(),v_iter.handle(),v_new);
_mesh->delete_face(face,false);
_mesh->add_face(f_vertices);
}
}
//all faces which belongs to v_iter and inside same component found
//the next face will be in a new component
++componentCount;
}
}
_mesh->remove_property(component);
_mesh->garbage_collection();
}
//-----------------------------------------------------------------------------
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