/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (C) 2001-2014 by Computer Graphics Group, RWTH Aachen *
* www.openflipper.org *
* *
*--------------------------------------------------------------------------- *
* This file is part of OpenFlipper. *
* *
* OpenFlipper 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 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenFlipper 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 LesserGeneral Public *
* License along with OpenFlipper. If not, *
* see . *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision$ *
* $LastChangedBy$ *
* $Date$ *
* *
\*===========================================================================*/
#if QT_VERSION >= 0x050000
#include
#else
#include
#endif
#include "MeshRepairPlugin.hh"
#include
#include "OpenFlipper/INIFile/INIFile.hh"
#include
#include
//-----------------------------------------------------------------------------
MeshRepairPlugin::MeshRepairPlugin() :
tool_(0),
toolIcon_(0)
{
}
//-----------------------------------------------------------------------------
void
MeshRepairPlugin::
initializePlugin()
{
tool_ = new MeshRepairToolbarWidget();
QSize size(300, 300);
tool_->resize(size);
//==================
// Vertex operations
//==================
connect(tool_->valenceThreeButton, SIGNAL(clicked()), this, SLOT(slotDetectFlatValence3Vertices()) );
connect(tool_->repairRemoveVButton, SIGNAL(clicked()), this, SLOT(slotRemoveSelectedVal3Vertices()) );
//==================
// Edge operations
//==================
connect(tool_->detectEShorterButton, SIGNAL(clicked()), this, SLOT(slotDetectEdgesShorter()) );
connect(tool_->detectELargerButton, SIGNAL(clicked()), this, SLOT(slotDetectEdgesLonger()) );
connect(tool_->repairCollapseEButton, SIGNAL(clicked()), this, SLOT(slotRemoveSelectedEdges()) );
connect(tool_->detectCapAngle, SIGNAL(clicked()), this, SLOT(slotDetectSkinnyTriangleByAngle()) );
connect(tool_->repairFlipEButton, SIGNAL(clicked()), this, SLOT(slotRemoveSkinnyTriangleByAngle()) );
connect(tool_->detectFoldoverButton, SIGNAL(clicked()), this, SLOT(slotDetectFoldover()) );
//==================
// Face operations
//==================
connect(tool_->triangleAspectButton,SIGNAL(clicked()),this,SLOT(slotDetectTriangleAspect()));
connect(tool_->flipOrientation,SIGNAL(clicked()),this,SLOT(slotFlipOrientation()));
//==================
// Normal operations
//==================
connect(tool_->computeNormals,SIGNAL(clicked()),this,SLOT(slotUpdateNormals()));
connect(tool_->computeVertexNormals,SIGNAL(clicked()),this,SLOT(slotUpdateVertexNormals()));
connect(tool_->computeFaceNormals,SIGNAL(clicked()),this,SLOT(slotUpdateFaceNormals()));
connect(tool_->computeHalfedgeNormals,SIGNAL(clicked()),this,SLOT(slotUpdateHalfedgeNormals()));
//==================
// General
//==================
connect(tool_->snapBoundaryButton, SIGNAL(clicked()), this, SLOT(slotSnapBoundary()) );
connect(tool_->fixNonManifoldVerticesButton,SIGNAL(clicked()),this,SLOT(slotFixNonManifoldVertices()));
connect(tool_->fixMeshButton,SIGNAL(clicked()),this,SLOT(slotFixMesh()));
toolIcon_ = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"meshrepair-toolbox.png");
tool_->repairCollapseEButton->setIcon(*toolIcon_);
tool_->repairFlipEButton->setIcon(*toolIcon_);
tool_->repairRemoveVButton->setIcon(*toolIcon_);
emit addToolbox( tr("Mesh Repair") , tool_, toolIcon_);
}
//===========================================================================
// Button Slots
//===========================================================================
void MeshRepairPlugin::slotRemoveSelectedVal3Vertices() {
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
removeSelectedVal3Vertices(o_it->id());
emit updateView();
}
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotRemoveSelectedEdges(){
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
removeSelectedEdges(o_it->id());
emit updateView();
}
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotDetectSkinnyTriangleByAngle()
{
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH | DATA_POLY_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
detectSkinnyTriangleByAngle( o_it->id(), tool_->capAngleSpinbox->value(), false );
emit updateView();
}
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotRemoveSkinnyTriangleByAngle()
{
//rewrite!!!
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH | DATA_POLY_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
detectSkinnyTriangleByAngle( o_it->id(), tool_->capAngleSpinbox->value(), true );
emit updateView();
}
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotDetectFoldover() {
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH | DATA_POLY_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
detectFoldover(o_it->id(), tool_->detectFoldoverSpinbox->value());
emit updateView();
}
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotDetectTriangleAspect() {
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH | DATA_POLY_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
detectTriangleAspect(o_it->id(), tool_->triangleAspectSpinbox->value());
emit updateView();
}
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotFlipOrientation(){
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH | DATA_POLY_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
flipOrientation(o_it->id());
emit updateView();
}
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotFixMesh() {
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
fixMesh(o_it->id() , tool_->fixMeshBox->value() );
emit updateView();
}
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotUpdateVertexNormals() {
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH | DATA_POLY_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
updateVertexNormals(o_it->id());
emit updateView();
}
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotUpdateFaceNormals() {
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH | DATA_POLY_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
updateFaceNormals(o_it->id());
emit updateView();
}
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotUpdateHalfedgeNormals() {
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH | DATA_POLY_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
updateHalfedgeNormals(o_it->id());
emit updateView();
}
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotUpdateNormals(){
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH | DATA_POLY_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
updateNormals(o_it->id());
emit updateView();
}
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotDetectEdgesShorter(){
double length = tool_->edgeSpin->value();
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH | DATA_POLY_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
selectEdgesShorterThan(o_it->id(),length);
emit updateView();
}
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotDetectEdgesLonger(){
double length = tool_->edgeSpin->value();
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH | DATA_POLY_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
selectEdgesLongerThan(o_it->id(),length);
emit updateView();
}
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotDetectFlatValence3Vertices() {
double angle = tool_->valenceThreeSpinbox->value();
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH | DATA_POLY_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
detectFlatValence3Vertices(o_it->id(), angle);
emit updateView();
}
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotSnapBoundary()
{
double eps = tool_->snapBoundarySpinBox->value();
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH | DATA_POLY_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
snapBoundary(o_it->id(), eps);
emit updateView();
}
//-----------------------------------------------------------------------------
void MeshRepairPlugin::slotFixNonManifoldVertices()
{
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType( DATA_TRIANGLE_MESH | DATA_POLY_MESH ) ); o_it != PluginFunctions::objectsEnd(); ++o_it)
fixNonManifoldVertices(o_it->id());
emit updateView();
}
//-----------------------------------------------------------------------------
/** \brief Initialization of the plugin when it is loaded by the core
*
*/
void MeshRepairPlugin::pluginsInitialized() {
// ===============================
// Vertex Operations
// ===============================
emit setSlotDescription("removeSelectedVal3Vertices(int)",tr("Remove all selected valence 3 vertices"),
QStringList(tr("objectId")),
QStringList(tr("ID of an object")));
emit setSlotDescription("detectFlatValence3Vertices(int,double)",tr("Selects all vertices that have valence 3 and the normals of their neighboring faces have an angle less then the given angle"),
QString(tr("objectId,angle")).split(","),
QString(tr("ID of an object;the maximal angle between the adjacent faces")).split(";"));
// ===============================
// Edge Operations
// ===============================
emit setSlotDescription("selectEdgesShorterThan(int,double)",tr("Selects all edges of an object which are shorter than the given length"),
QString(tr("objectId,length")).split(","),
QString(tr("ID of an object;All edges shorter than this length will be selected")).split(";"));
emit setSlotDescription("selectEdgesLongerThan(int,double)",tr("Selects all edges of an object which are longer than the given length"),
QString(tr("objectId,length")).split(","),
QString(tr("ID of an object;All edges longer than this length will be selected")).split(";"));
emit setSlotDescription("removeSelectedEdges(int)",tr("Remove the selected edges"),
QStringList(tr("objectId")),
QStringList(tr("ID of an object")));
emit setSlotDescription("detectSkinnyTriangleByAngle(int,double,bool)",tr("Select or remove skinny triangles (determined by a minimum angle threshold)."),
QString(tr("objectId,angle,remove")).split(","),
QString(tr("ID of an object;Minimum angle threshold;Remove")).split(";"));
emit setSlotDescription("detectFoldover(int,float)",tr("Selects edges that are incident to folded over faces."),
QString(tr("objectId,angle")).split(","),
QString(tr("ID of an object;Minimum threshold angle for fold-overs")).split(";"));
// ===============================
// Face Operations
// ===============================
emit setSlotDescription("detectTriangleAspect(int,float)",tr("Selects all faces that have a larger aspect ratio than the given one."),
QString(tr("objectId,aspect")).split(","),
QString(tr("ID of an object;The minimal aspect ratio to select")).split(";"));
emit setSlotDescription("flipOrientation(int)",tr("Flips the normals of all faces by changing the vertex order in each face"),
QStringList(tr("objectId")),
QStringList(tr("ID of an object")));
// ===============================
// Normal Fixing
// ===============================
emit setSlotDescription("updateFaceNormals(int)",tr("Recompute Face normals"),
QStringList(tr("objectId")),
QStringList(tr("ID of an object")));
emit setSlotDescription("updateHalfedgeNormals(int)",tr("Recompute Halfedge normals"),
QStringList(tr("objectId")),
QStringList(tr("ID of an object")));
emit setSlotDescription("updateVertexNormals(int)",tr("Recompute Vertex normals"),
QStringList(tr("objectId")),
QStringList(tr("ID of an object")));
emit setSlotDescription("updateNormals(int)",tr("Recompute Face and Vertex normals"),
QStringList(tr("objectId")),
QStringList(tr("ID of an object")));
// ===============================
// General Mesh fixing
// ===============================
emit setSlotDescription("snapBoundary(int,double)",tr("Snaps selected boundary vertices if the distance is less than the given maximal distance."),
QString(tr("objectId,epsilon")).split(","),
QString(tr("ID of an object;Max Distance")).split(";"));
emit setSlotDescription("(int)",tr("Fixes non manifold vertices."),
QString(tr("objectId")).split(","),
QString(tr("ID of an object;Non manifold vertices are splitted.")).split(";"));
emit setSlotDescription("fixMesh(int,double)",tr("Fixes a mesh."),
QString(tr("objectId,distance")).split(","),
QString(tr("ID of an object;Vertices with distance lower than epsilon will be treated as one.")).split(";"));
}
#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2( meshrepairplugin , MeshRepairPlugin );
#endif