From 44725a52f4c74da9888570cfafeb6d48d04a205e Mon Sep 17 00:00:00 2001 From: Paolo Cignoni cignoni Date: Tue, 9 Dec 2008 14:31:01 +0000 Subject: [PATCH] renamed cleanfilter to the standard naming scheme filter_clean --- .../filter_clean/align_tools.cpp | 325 ++++++++++++++++++ src/meshlabplugins/filter_clean/align_tools.h | 61 ++++ .../filter_clean/cleanfilter.cpp | 298 ++++++++++++++++ src/meshlabplugins/filter_clean/cleanfilter.h | 117 +++++++ .../filter_clean/cleanfilter.pro | 33 ++ src/meshlabplugins/filter_clean/parameter.cpp | 0 src/meshlabplugins/filter_clean/parameter.h | 12 + .../filter_clean/remove_small_cc.h | 104 ++++++ 8 files changed, 950 insertions(+) create mode 100644 src/meshlabplugins/filter_clean/align_tools.cpp create mode 100644 src/meshlabplugins/filter_clean/align_tools.h create mode 100644 src/meshlabplugins/filter_clean/cleanfilter.cpp create mode 100644 src/meshlabplugins/filter_clean/cleanfilter.h create mode 100644 src/meshlabplugins/filter_clean/cleanfilter.pro create mode 100644 src/meshlabplugins/filter_clean/parameter.cpp create mode 100644 src/meshlabplugins/filter_clean/parameter.h create mode 100644 src/meshlabplugins/filter_clean/remove_small_cc.h diff --git a/src/meshlabplugins/filter_clean/align_tools.cpp b/src/meshlabplugins/filter_clean/align_tools.cpp new file mode 100644 index 000000000..f44f6bdef --- /dev/null +++ b/src/meshlabplugins/filter_clean/align_tools.cpp @@ -0,0 +1,325 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include + +#include "align_tools.h" + +#include + +#include + +#include +#include +#include + +#include + +#include +#include +#include + +using namespace vcg; + +const QString AlignTools::FilterName = "Align Mesh using Picked Points"; +const QString AlignTools::UseMarkers = "UseM"; +const QString AlignTools::AllowScaling = "AllowScaling"; +const QString AlignTools::UseICP = "UseICP"; +const QString AlignTools::StuckMesh = "StuckMesh"; +const QString AlignTools::MeshToMove = "MeshToMove"; + +AlignTools::AlignTools(){} + +void AlignTools::buildParameterSet(FilterParameterSet & parlst) +{ + vcg::AlignPair::Param ICPParameters; + AlignParameter::buildFilterParameterSet(ICPParameters, parlst); + + parlst.addBool(UseMarkers, true, "Use Markers for Alignment","if true (default), then use the user picked markers to do an alignment (or pre alignment if you also use ICP)."); + parlst.addBool(AllowScaling, false, "Scale the mesh","if true (false by default), in addition to the alignment, scale the mesh based on the points picked"); + + parlst.addBool(UseICP, true, "Use ICP for Alignment","if true (default), then use the ICP to align the two meshes."); + + parlst.addMesh (StuckMesh, 0, "Stuck Mesh", + "The mesh that will not move."); + parlst.addMesh (MeshToMove, 1, "Mesh to Move", + "The mesh that will move to fit close to the Stuck Mesh."); +} + +bool AlignTools::setupThenAlign(MeshModel &/*mm*/, FilterParameterSet & par) +{ + //mesh that wont move + MeshModel *stuckModel = par.getMesh(StuckMesh); + PickedPoints *stuckPickedPoints = 0; + + //mesh that will move + MeshModel *modelToMove = par.getMesh(MeshToMove); + PickedPoints *modelToMovePickedPoints = 0; + + bool useMarkers = par.getBool(UseMarkers); + + if(NULL == stuckModel || NULL == modelToMove) + { + qDebug() << "one of the input meshes to filter align was null"; + return false; + } + + //if we are going to use the markers try to load them + if(useMarkers){ + //first try to get points from memory + if(vcg::tri::HasPerMeshAttribute(stuckModel->cm, PickedPoints::Key) ) + { + CMeshO::PerMeshAttributeHandle ppHandle = + vcg::tri::Allocator::GetPerMeshAttribute(stuckModel->cm, PickedPoints::Key); + + stuckPickedPoints = ppHandle(); + + if(NULL == stuckPickedPoints){ + qDebug() << "problem casting to picked points"; + return false; + } + } else + { + //now try to load them from a file + QString ppFileName = PickedPoints::getSuggestedPickedPointsFileName(*stuckModel); + QFileInfo file(ppFileName); + if(file.exists()) + { + stuckPickedPoints = new PickedPoints(); + bool success = stuckPickedPoints->open(ppFileName); + + if(!success){ + qDebug() << "problem loading stuck picked points from a file"; + return false; + } + } else + { + qDebug() << "stuck points file didnt exist: " << ppFileName; + //Log(GLLogStream::Info, "No points were found for the Stuck mesh."); + return false; + } + } + + if(vcg::tri::HasPerMeshAttribute(modelToMove->cm, PickedPoints::Key) ) + { + CMeshO::PerMeshAttributeHandle ppHandle = + vcg::tri::Allocator::GetPerMeshAttribute(modelToMove->cm, PickedPoints::Key); + + modelToMovePickedPoints = ppHandle(); + + if(NULL == modelToMovePickedPoints){ + qDebug() << "problem casting to picked poitns"; + return false; + } + } else + { + QString ppFileName = PickedPoints::getSuggestedPickedPointsFileName(*modelToMove); + QFileInfo file(ppFileName); + if(file.exists()) + { + modelToMovePickedPoints = new PickedPoints(); + bool success = modelToMovePickedPoints->open(ppFileName); + if(!success){ + qDebug() << "failed to load modelToMove pick points"; + return false; + } + } else + { + qDebug() << "model to move points file didnt exist: " << ppFileName; + //Log(GLLogStream::Info, "No points were found for the mesh to move."); + return false; + } + } + } + + bool result = AlignTools::align(stuckModel, stuckPickedPoints, + modelToMove, modelToMovePickedPoints, + 0, par); + + return result; +} + + +bool AlignTools::align(MeshModel *stuckModel, PickedPoints *stuckPickedPoints, + MeshModel *modelToMove, PickedPoints *modelToMovePickedPoints, + GLArea *modelToMoveGLArea, + FilterParameterSet &filterParameters, + QWidget *parentWidget, bool confirm) +{ + vcg::Matrix44f result; + + bool useMarkers = filterParameters.getBool(UseMarkers); + bool allowScaling = filterParameters.getBool(AllowScaling); + bool useICP = filterParameters.getBool(UseICP); + + if(useMarkers){ + //get the picked points + std::vector *stuckPoints = stuckPickedPoints->getPoint3fVector(); + std::vector *meshToMovePoints = modelToMovePickedPoints->getPoint3fVector(); + + //number of points are not the same so return false + if(stuckPoints->size() != meshToMovePoints->size()) return false; + + //this will calculate the transform for the destination mesh model which we will be moving + //into alignment with the source + if(allowScaling) + { + qDebug() << "Scaling allowed"; + vcg::PointMatching::ComputeSimilarityMatchMatrix(result, *stuckPoints, *meshToMovePoints); + } else + vcg::PointMatching::ComputeRigidMatchMatrix(result, *stuckPoints, *meshToMovePoints); + + //set the transform + modelToMove->cm.Tr = result; + + if(NULL != modelToMoveGLArea) + modelToMoveGLArea->update(); + } + + if(useICP) + { + qDebug("Now on to ICP"); + + //create a meshtree + MeshTree meshTree; + //put both meshes in it + meshTree.nodeList.push_back(new MeshNode(stuckModel, 0)); + meshTree.nodeList.push_back(new MeshNode(modelToMove, 1)); + + //set both to glued + foreach(MeshNode *mn, meshTree.nodeList) + mn->glued=true; + + vcg::AlignPair::Param ICPParameters; + + //get the parameter values + AlignParameter::buildAlignParameters(filterParameters, ICPParameters); + + meshTree.Process(ICPParameters); + + qDebug() << "done with process for ICP"; + + if(NULL != modelToMoveGLArea) + modelToMoveGLArea->update(); + + } + + if(useMarkers || useICP) + { + + if(confirm && NULL != modelToMoveGLArea) + { + bool removeMeshAddedForQuestion = false; + + vcg::Color4b oldStuckColor; + vcg::Color4b oldToMoveColor; + vcg::GLW::ColorMode oldColorMode; + //if the stuck model is not displayed next to the model to move, + //then temporarily display it + if(!modelToMoveGLArea->meshDoc.meshList.contains(stuckModel)) + { + removeMeshAddedForQuestion = true; + modelToMoveGLArea->meshDoc.meshList.push_back(stuckModel); + + //save the old colors + oldStuckColor = stuckModel->cm.C(); + oldToMoveColor = modelToMove->cm.C(); + //set the color of the objects + stuckModel->cm.C() = vcg::Color4b::LightBlue; + modelToMove->cm.C() = vcg::Color4b::LightGray; + + //save the old colorMode + oldColorMode = modelToMoveGLArea->rm.colorMode; + //set the new colorMode + modelToMoveGLArea->rm.colorMode = GLW::CMPerMesh; + + modelToMoveGLArea->update(); + } + + int returnValue = QMessageBox::question(parentWidget, + "MeshLab", "Do you want accept this alignment?", + QMessageBox::Yes|QMessageBox::No, QMessageBox::No); + + //if we added the other model in for comparing + if(removeMeshAddedForQuestion) + { + //remove the mesh that was added + modelToMoveGLArea->meshDoc.meshList.pop_back(); + + //set back to how things were before + stuckModel->cm.C() = oldStuckColor; + modelToMove->cm.C() = oldToMoveColor; + modelToMoveGLArea->rm.colorMode = oldColorMode; + + modelToMoveGLArea->update(); + } + + if(returnValue == QMessageBox::No) + { + modelToMove->cm.Tr.SetIdentity(); + + modelToMoveGLArea->update(); + + return false; + } + } + + //if there are points (may not be if you just used ICP + if(NULL != modelToMovePickedPoints) + { + //now translate the picked points points + modelToMovePickedPoints->translatePoints(modelToMove->cm.Tr); + + //update the metadata + CMeshO::PerMeshAttributeHandle ppHandle = + (vcg::tri::HasPerMeshAttribute(modelToMove->cm, PickedPoints::Key) ? + vcg::tri::Allocator::GetPerMeshAttribute (modelToMove->cm, PickedPoints::Key) : + vcg::tri::Allocator::AddPerMeshAttribute (modelToMove->cm, PickedPoints::Key) ); + + ppHandle() = modelToMovePickedPoints; + } + + //now save the transform as perMeshData so that we can undo it in the future + CMeshO::PerMeshAttributeHandle transformHandle = + (vcg::tri::HasPerMeshAttribute(modelToMove->cm, getKey()) ? + vcg::tri::Allocator::GetPerMeshAttribute (modelToMove->cm, getKey()) : + vcg::tri::Allocator::AddPerMeshAttribute (modelToMove->cm, getKey()) ); + transformHandle() = modelToMove->cm.Tr; + + //now translate all the points in the mesh + //TODO probably should call a function to do this so if meshlab changes we dont have to + //taken from meshlab/src/meshlabplugins/meshfilter/meshfilter.cpp + //if (ID(filter) == (FP_FREEZE_TRANSFORM) ) { + vcg::tri::UpdatePosition::Matrix(modelToMove->cm, modelToMove->cm.Tr); + vcg::tri::UpdateNormals::PerVertexNormalizedPerFace(modelToMove->cm); + vcg::tri::UpdateBounding::Box(modelToMove->cm); + modelToMove->cm.Tr.SetIdentity(); + + return true; + } else + { + qDebug() << "you ran align without choosing a method"; + } + + return false; +} diff --git a/src/meshlabplugins/filter_clean/align_tools.h b/src/meshlabplugins/filter_clean/align_tools.h new file mode 100644 index 000000000..5f2b3995f --- /dev/null +++ b/src/meshlabplugins/filter_clean/align_tools.h @@ -0,0 +1,61 @@ +/* + * This class will will hold useful things for doing alignment of meshes + * + * @author Oscar Barney + * + */ + +#ifndef ALIGN_TOOLS_H +#define ALIGN_TOOLS_H + +#include + +#include +#include +#include + +#include +#include + +class AlignTools : public QObject +{ + Q_OBJECT + +public: + static const QString FilterName; + static const QString UseMarkers; + static const QString AllowScaling; + static const QString UseICP; + static const QString StuckMesh; + static const QString MeshToMove; + + //make the default parameter set for this filter + static void buildParameterSet(FilterParameterSet & parlst); + + //setup all the parameters and then call align + static bool setupThenAlign(MeshModel &mm, FilterParameterSet & par); + + /* + * stuckModel - the mesh one that stays put + * modelToMove - the mesh to be moved into place + * modelToMoveGLArea - so we can update the position of the model + * parentWidget - the widget that should be the parent of the confirm dialog window + * confirm - whether to ask the user if they want the alignment to stay put + * + * return value - true if align was accepted or successful + */ + static bool align(MeshModel *stuckModel, PickedPoints *stuckPickedPoints, + MeshModel *modelToMove, PickedPoints *modelToMovePickedPoints, + GLArea *modelToMoveGLArea, + FilterParameterSet ¶meters, + QWidget *parentWidget = 0, bool confirm = false); + + //returns the key applied if this transform is stored to perMeshAttribute + static const std::string getKey() { return "TransformAppliedKey"; } + +protected: + AlignTools(); + +}; + +#endif diff --git a/src/meshlabplugins/filter_clean/cleanfilter.cpp b/src/meshlabplugins/filter_clean/cleanfilter.cpp new file mode 100644 index 000000000..c296f4a2f --- /dev/null +++ b/src/meshlabplugins/filter_clean/cleanfilter.cpp @@ -0,0 +1,298 @@ +/**************************************************************************** +* MeshLab o o * +* An extendible mesh processor o o * +* _ O _ * +* Copyright(C) 2005, 2006 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +/**************************************************************************** + History + + $Log$ + Revision 1.19 2008/04/08 10:16:04 cignoni + added missing std:: and vcg:: + + Revision 1.18 2007/12/14 14:57:20 cignoni + Improved ball pivoting params and descriptions + + Revision 1.17 2007/12/13 00:19:35 cignoni + removed deprecated setD + + Revision 1.16 2007/10/02 08:13:38 cignoni + New filter interface. Hopefully more clean and easy to use. + + Revision 1.15 2007/06/11 15:26:43 ponchio + *** empty log message *** + + Revision 1.14 2007/05/30 15:10:54 ponchio + *** empty log message *** + + Revision 1.13 2007/05/22 15:26:02 cignoni + Improved params of ball pivoting (again) + + Revision 1.12 2007/05/22 15:16:43 cignoni + Improved params of ball pivoting + + Revision 1.11 2007/04/16 09:25:28 cignoni + ** big change ** + Added Layers managemnt. + Interfaces are changing again... + + Revision 1.10 2007/03/20 16:23:07 cignoni + Big small change in accessing mesh interface. First step toward layers + + Revision 1.9 2007/02/08 23:46:15 pirosu + merged srcpar and par in the GetStdParameters() function + + Revision 1.8 2007/01/11 19:52:25 pirosu + fixed bug for QT 4.1.0/dotnet2003 + removed the request of the window title to the plugin. The action description is used instead. + + Revision 1.7 2006/12/27 21:41:58 pirosu + Added improvements for the standard plugin window: + split of the apply button in two buttons:ok and apply + added support for parameters with absolute and percentage values + + Revision 1.6 2006/12/13 17:37:27 pirosu + Added standard plugin window support + + + Revision 1.5 2006/11/29 00:59:15 cignoni + Cleaned plugins interface; changed useless help class into a plain string + + Revision 1.4 2006/11/27 06:57:19 cignoni + Wrong way of using the __DATE__ preprocessor symbol + + Revision 1.3 2006/11/07 17:26:01 cignoni + small gcc compiling issues + + Revision 1.2 2006/11/07 14:56:23 zifnab1974 + Changes for compilation with gcc 3.4.6 on linux AMD64 + + Revision 1.1 2006/11/07 09:09:27 cignoni + First Working release, moved in from epoch svn + + Revision 1.1 2006/01/20 13:03:27 cignoni + *** empty log message *** + +*****************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include "cleanfilter.h" +#include "remove_small_cc.h" +#include "align_tools.h" + +//#include +#include +#include +#include +#include +#include +#include +#include + +#include +using namespace std; +using namespace vcg; + +CleanFilter::CleanFilter() +{ + typeList << FP_REBUILD_SURFACE << FP_REMOVE_WRT_Q << FP_REMOVE_ISOLATED_COMPLEXITY << FP_REMOVE_ISOLATED_DIAMETER << FP_ALIGN_WITH_PICKED_POINTS; + + FilterIDType tt; + foreach(tt , types()) + actionList << new QAction(filterName(tt), this); + + maxDiag1=0; + maxDiag2=-1; + minCC=25; + val1=1.0; + +} + +CleanFilter::~CleanFilter() { + for (int i = 0; i < actionList.count() ; i++ ) + delete actionList.at(i); +} + +const QString CleanFilter::filterName(FilterIDType filter) +{ + switch(filter) + { + case FP_REBUILD_SURFACE : return QString("Ball Pivoting Surface Reconstruction"); + case FP_REMOVE_WRT_Q : return QString("Remove vertices wrt quality"); + case FP_REMOVE_ISOLATED_DIAMETER : return QString("Remove isolated pieces (wrt diameter)"); + case FP_REMOVE_ISOLATED_COMPLEXITY : return QString("Remove isolated pieces (wrt face num)"); + case FP_ALIGN_WITH_PICKED_POINTS : return AlignTools::FilterName; + default: assert(0); + } + return QString("error!"); +} + +const QString CleanFilter::filterInfo(FilterIDType filterId) +{ + switch(filterId) + { + case FP_REBUILD_SURFACE : return QString("Reconstruct a surface using the Ball Pivoting Algorithm (Bernardini et al. 1999).
" + "Starting with a seed triangle, the BPA algorithm pivots a ball around an edge " + "(i.e. it revolves around the edge while keeping in contact with the edge endpoints) " + "until it touches another point, forming another triangle. The process continues until all reachable edges have been tried."); + case FP_REMOVE_ISOLATED_COMPLEXITY: return tr("Remove isolated connected components composed by a limited number of triangles"); + case FP_REMOVE_ISOLATED_DIAMETER: return tr("Remove isolated connected components whose diameter is smaller than the specified constant"); + case FP_REMOVE_WRT_Q: return tr("Remove all the vertices with a quality lower smaller than the specified constant"); + case FP_ALIGN_WITH_PICKED_POINTS: return tr("Align this mesh with another that has corresponding picked points."); + default: assert(0); + } + return QString("error!"); +} + +const CleanFilter::FilterClass CleanFilter::getClass(QAction *a) +{ + switch(ID(a)) + { + case FP_REMOVE_WRT_Q : + case FP_REMOVE_ISOLATED_DIAMETER : + case FP_REMOVE_ISOLATED_COMPLEXITY : + return MeshFilterInterface::Cleaning; + default : return MeshFilterInterface::Generic; + } +} + +const int CleanFilter::getRequirements(QAction *action) +{ + switch(ID(action)) + { + case FP_REMOVE_WRT_Q: + case FP_REBUILD_SURFACE : return MeshModel::MM_FACEFLAGBORDER | MeshModel::MM_VERTMARK; + case FP_REMOVE_ISOLATED_COMPLEXITY: + case FP_REMOVE_ISOLATED_DIAMETER: + return MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER | MeshModel::MM_FACEMARK; + case FP_ALIGN_WITH_PICKED_POINTS: + return MeshModel::MM_NONE; + default: assert(0); + } + return 0; +} + +void CleanFilter::initParameterSet(QAction *action,MeshModel &m, FilterParameterSet & parlst) +{ + pair qualityRange; + switch(ID(action)) + { + case FP_REBUILD_SURFACE : + parlst.addAbsPerc("BallRadius",(float)maxDiag1,0,m.cm.bbox.Diag(),"Pivoting Ball radius (0 autoguess)","The radius of the ball pivoting (rolling) over the set of points. Gaps that are larger than the ball radius will not be filled; similarly the small pits that are smaller than the ball radius will be filled."); + parlst.addFloat("Clustering",20.0f,"Clustering radius (% of ball radius)","To avoid the creation of too small triangles, if a vertex is found too close to a previous one, it is clustered/merged with it."); parlst.addFloat("CreaseThr", 90.0f,"Angle Threshold (degrees)","If we encounter a crease angle that is too large we should stop the ball rolling"); + parlst.addBool("DeleteFaces",false,"Delete intial set of faces","if true all the initial faces of the mesh are deleted and the whole surface is rebuilt from scratch, other wise the current faces are used as a starting point. Useful if you run multiple times the algorithm with an incrasing ball radius."); + break; + case FP_REMOVE_ISOLATED_DIAMETER: + parlst.addAbsPerc("MinComponentDiag",m.cm.bbox.Diag()/10.0,0,m.cm.bbox.Diag(),"Enter max diameter of isolated pieces","Delete all the connected components (floating pieces) with a diameter smaller than the specified one"); + break; + case FP_REMOVE_ISOLATED_COMPLEXITY: + parlst.addInt("MinComponentSize",(int)minCC,"Enter minimum conn. comp size:","Delete all the connected components (floating pieces) composed by a number of triangles smaller than the specified one"); + break; + case FP_REMOVE_WRT_Q: + qualityRange=tri::Stat::ComputePerVertexQualityMinMax(m.cm); + parlst.addAbsPerc("MaxQualityThr",(float)val1, qualityRange.first, qualityRange.second,"Delete all vertices with quality under:"); + break; + case FP_ALIGN_WITH_PICKED_POINTS : + AlignTools::buildParameterSet(parlst); + break; + default: assert(0); + } +} + +bool CleanFilter::applyFilter(QAction *filter, MeshModel &m, FilterParameterSet & par, vcg::CallBackPos * cb) +{ + if(filter->text() == filterName(FP_REBUILD_SURFACE) ) + { + float Radius = par.getAbsPerc("BallRadius"); + float Clustering = par.getFloat("Clustering"); + float CreaseThr = math::ToRad(par.getFloat("CreaseThr")); + bool DeleteFaces = par.getBool("DeleteFaces"); + if(DeleteFaces) { + m.cm.fn=0; + m.cm.face.resize(0); + } + + int startingFn=m.cm.fn; + Clustering /= 100.0; + tri::BallPivoting pivot(m.cm, Radius, Clustering, CreaseThr); + // the main processing + pivot.BuildMesh(cb); + m.clearDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER); + Log(GLLogStream::Info,"Reconstructed surface. Added %i faces",m.cm.fn-startingFn); + } + if(filter->text() == filterName(FP_REMOVE_ISOLATED_DIAMETER) ) + { + float minCC= par.getAbsPerc("MinComponentDiag"); + std::pair delInfo= RemoveSmallConnectedComponentsDiameter(m.cm,minCC); + Log(GLLogStream::Info,"Removed %2 connected components out of %1", delInfo.second, delInfo.first); + } + + if(filter->text() == filterName(FP_REMOVE_ISOLATED_COMPLEXITY) ) + { + float minCC= par.getInt("MinComponentSize"); + std::pair delInfo=RemoveSmallConnectedComponentsSize(m.cm,minCC); + Log(GLLogStream::Info,"Removed %i connected components out of %i", delInfo.second, delInfo.first); + } + if(filter->text() == filterName(FP_REMOVE_WRT_Q) ) + { + int deletedFN=0; + int deletedVN=0; + float val=par.getAbsPerc("MaxQualityThr"); + CMeshO::VertexIterator vi; + for(vi=m.cm.vert.begin();vi!=m.cm.vert.end();++vi) + if(!(*vi).IsD() && (*vi).Q()::DeleteVertex(m.cm, *vi); + deletedVN++; + } + + CMeshO::FaceIterator fi; + for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) + if((*fi).V(0)->IsD() ||(*fi).V(1)->IsD() ||(*fi).V(2)->IsD() ) + { + tri::Allocator::DeleteFace(m.cm, *fi); + deletedFN++; + } + + m.clearDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER); + Log(GLLogStream::Info,"Deleted %i vertices and %i faces with a quality lower than %f", deletedVN,deletedFN,val); + + } + + if(filter->text() == filterName(FP_ALIGN_WITH_PICKED_POINTS) ) + { + bool result = AlignTools::setupThenAlign(m, par); + if(!result) + { + Log(GLLogStream::Info,"Align failed, make sure you have equal numbers of points."); + return false; + } + } + + return true; +} + + +Q_EXPORT_PLUGIN(CleanFilter) diff --git a/src/meshlabplugins/filter_clean/cleanfilter.h b/src/meshlabplugins/filter_clean/cleanfilter.h new file mode 100644 index 000000000..34c30ec6d --- /dev/null +++ b/src/meshlabplugins/filter_clean/cleanfilter.h @@ -0,0 +1,117 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +/**************************************************************************** + History + + $Log$ + Revision 1.8 2007/10/02 08:13:39 cignoni + New filter interface. Hopefully more clean and easy to use. + + Revision 1.7 2007/04/16 09:25:28 cignoni + ** big change ** + Added Layers managemnt. + Interfaces are changing again... + + Revision 1.6 2007/02/08 23:46:16 pirosu + merged srcpar and par in the GetStdParameters() function + + Revision 1.5 2007/01/11 19:52:25 pirosu + fixed bug for QT 4.1.0/dotnet2003 + removed the request of the window title to the plugin. The action description is used instead. + + Revision 1.4 2006/12/27 21:41:58 pirosu + Added improvements for the standard plugin window: + split of the apply button in two buttons:ok and apply + added support for parameters with absolute and percentage values + + Revision 1.3 2006/12/13 17:37:27 pirosu + Added standard plugin window support + + + Revision 1.2 2006/11/29 00:59:15 cignoni + Cleaned plugins interface; changed useless help class into a plain string + + Revision 1.1 2006/11/07 09:09:27 cignoni + First Working release, moved in from epoch svn + + Revision 1.1 2006/01/20 13:03:27 cignoni + *** empty log message *** + + *****************************************************************************/ +#ifndef EXTRAIOPLUGINV3D_H +#define EXTRAIOPLUGINV3D_H + +#include +#include +#include + +#include +#include + + +class CleanFilter : public QObject, public MeshFilterInterface +{ + Q_OBJECT + Q_INTERFACES(MeshFilterInterface) + + public: + /* naming convention : + - FP -> Filter Plugin + - name of the plugin separated by _ + */ + enum { + FP_REBUILD_SURFACE, + FP_REMOVE_ISOLATED_COMPLEXITY, + FP_REMOVE_ISOLATED_DIAMETER, + FP_REMOVE_WRT_Q, + FP_ALIGN_WITH_PICKED_POINTS + } ; + + /* default values for standard parameters' values of the plugin actions */ + float maxDiag1; + float maxDiag2; + int minCC; + float val1; + + + CleanFilter(); + ~CleanFilter(); + + virtual const QString filterName(FilterIDType filter); + virtual const QString filterInfo(FilterIDType filter); + + virtual const FilterClass getClass(QAction *); + virtual const int getRequirements(QAction *); + + virtual bool autoDialog(QAction *) {return true;} + virtual void initParameterSet(QAction *,MeshModel &/*m*/, FilterParameterSet & /*parent*/); + virtual bool applyFilter(QAction *filter, MeshModel &m, FilterParameterSet & /*parent*/, vcg::CallBackPos * cb) ; + +}; + + + + + + +#endif diff --git a/src/meshlabplugins/filter_clean/cleanfilter.pro b/src/meshlabplugins/filter_clean/cleanfilter.pro new file mode 100644 index 000000000..1551b8067 --- /dev/null +++ b/src/meshlabplugins/filter_clean/cleanfilter.pro @@ -0,0 +1,33 @@ +include (../../shared.pri) + +HEADERS = cleanfilter.h \ + ../../meshlab/filterparameter.h + +SOURCES = cleanfilter.cpp\ + ../../meshlab/filterparameter.cpp + +#align stuff + +HEADERS += align_tools.h \ + ../../meshlabplugins/edit_pickpoints/pickedPoints.h \ + ../../meshlabplugins/editalign/align/align_parameter.h \ + ../../meshlabplugins/editalign/meshtree.h \ + ../../meshlabplugins/editalign/align/AlignPair.h \ + ../../meshlabplugins/editalign/align/AlignGlobal.h \ + ../../meshlabplugins/editalign/align/OccupancyGrid.h \ + $$VCGDIR/wrap/gl/trimesh.h + +SOURCES += align_tools.cpp \ + ../../meshlabplugins/edit_pickpoints/pickedPoints.cpp \ + ../../meshlabplugins/editalign/align/align_parameter.cpp \ + ../../meshlabplugins/editalign/meshtree.cpp \ + ../../meshlabplugins/editalign/align/AlignPair.cpp \ + ../../meshlabplugins/editalign/align/AlignGlobal.cpp \ + ../../meshlabplugins/editalign/align/OccupancyGrid.cpp \ + $$VCGDIR/wrap/ply/plylib.cpp + + +TARGET = filter_clean + +QT += opengl +QT += xml \ No newline at end of file diff --git a/src/meshlabplugins/filter_clean/parameter.cpp b/src/meshlabplugins/filter_clean/parameter.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/meshlabplugins/filter_clean/parameter.h b/src/meshlabplugins/filter_clean/parameter.h new file mode 100644 index 000000000..ed457b806 --- /dev/null +++ b/src/meshlabplugins/filter_clean/parameter.h @@ -0,0 +1,12 @@ +class Parameter : QWidget +{ + public: + + void addBool(); + void addOption() + void addFloat(); + void addRangedFloat(); + + exec +}; + diff --git a/src/meshlabplugins/filter_clean/remove_small_cc.h b/src/meshlabplugins/filter_clean/remove_small_cc.h new file mode 100644 index 000000000..85c1253f3 --- /dev/null +++ b/src/meshlabplugins/filter_clean/remove_small_cc.h @@ -0,0 +1,104 @@ +/**************************************************************************** +* MeshLab o o * +* An extendible mesh processor o o * +* _ O _ * +* Copyright(C) 2005, 2006 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +/**************************************************************************** + History + + $Log$ + Revision 1.3 2008/04/04 14:08:17 cignoni + Solved namespace ambiguities caused by the removal of a silly 'using namespace' in meshmodel.h + + Revision 1.2 2007/12/14 11:52:18 cignoni + now use the correct deleteFace/vert and returns info on the number of deleted stuff + + Revision 1.1 2006/11/07 09:09:28 cignoni + First Working release, moved in from epoch svn + + Revision 1.1 2006/01/20 13:03:27 cignoni + *** empty log message *** + +*****************************************************************************/ +#ifndef __VCGLIB__REMOVE_SMALL_CC +#define __VCGLIB__REMOVE_SMALL_CC + +#include +#include + +namespace vcg +{ +template +std::pair RemoveSmallConnectedComponentsSize(MeshType &m, int maxCCSize) +{ + std::vector< std::pair > CCV; + int TotalCC=vcg::tri::Clean::ConnectedComponents(m, CCV); + int DeletedCC=0; + + tri::ConnectedIterator ci; + for(unsigned int i=0;i FPV; + if(CCV[i].first::iterator fpvi; + for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi) + tri::Allocator::DeleteFace(m,(**fpvi)); + } + } + return std::make_pair(TotalCC,DeletedCC); +} + +/// Remove the connected components smaller than a given diameter +// it returns a pair with the number of connected components and the number of deleted ones. +template +std::pair RemoveSmallConnectedComponentsDiameter(MeshType &m, typename MeshType::ScalarType maxDiameter) +{ + std::vector< std::pair > CCV; + int TotalCC=vcg::tri::Clean::ConnectedComponents(m, CCV); + int DeletedCC=0; + tri::ConnectedIterator ci; + for(unsigned int i=0;i FPV; + for(ci.start(m,CCV[i].second);!ci.completed();++ci) + { + FPV.push_back(*ci); + bb.Add((*ci)->P(0)); + bb.Add((*ci)->P(1)); + bb.Add((*ci)->P(2)); + } + if(bb.Diag()::iterator fpvi; + for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi) + tri::Allocator::DeleteFace(m,(**fpvi)); + } + } + return std::make_pair(TotalCC,DeletedCC); +} +} //end namespace +#endif