Commit 683299e9 authored by Martin Schultz's avatar Martin Schultz

added merge plugin

parents
include (plugin)
if (WIN32)
openflipper_plugin (DEPS CGAL Boost GMM LAPACK BLAS)
else ()
openflipper_plugin (DEPS GMM LAPACK BLAS)
endif ()
#include <QtGui>
#include "MergePlugin.hh"
#include <iostream>
#include "OpenFlipper/BasePlugin/PluginFunctions.hh"
#include <OpenFlipper/BasePlugin/RPCWrappers.hh>
/**
* Helper functions
*/
namespace
{
template< class MeshT >
void getAllMeshes(std::vector< MeshT* > & meshes, const std::vector< BaseObjectData* > & objects)
{
for (uint i=0; i < objects.size(); i++)
{
MeshT* t;
if(PluginFunctions::getMesh(objects[i]->id(),t))
meshes.push_back( t );
}
}
void getTargets(std::vector< BaseObjectData* > & _objects)
{
_objects.clear();
//read all target objects
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType(DATA_TRIANGLE_MESH | DATA_POLY_MESH)) ;
o_it != PluginFunctions::objectsEnd(); ++o_it)
_objects.push_back( *o_it );
}
template< class MeshT >
void convertMeshes(const DataType & _type, std::vector< int >& convertedIds, std::vector< MeshT* >& _meshes)
{
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,_type) ;
o_it != PluginFunctions::objectsEnd(); ++o_it)
{
//convert polyMesh to triMesh or vice versa
convertedIds.push_back(RPC::callFunctionValue<int>("meshconvert","convert",(*o_it)->id(), _type != DATA_TRIANGLE_MESH));
MeshT* ptr;
PluginFunctions::getMesh(convertedIds.back(),ptr);
_meshes.push_back(ptr);
}
}
}
void MergePlugin::slotCleanup( DataType _type, bool _deleteSeparateObjects )
{
//clean up conversion objects
for(int i : convertedIds)
emit deleteObject( i );
convertedIds.clear();
if(_deleteSeparateObjects)
{
//clean up separated objects
for (size_t i=0; i < objects.size(); i++)
emit deleteObject( (objects[i])->id() );
objects.clear();
}
//clean up unused merge target
if(_type == DATA_TRIANGLE_MESH)
emit deleteObject( polyMergeID );
else
emit deleteObject( triMergeID );
}
DataType MergePlugin::checkType(const std::vector< BaseObjectData* > & objects )
{
DataType type = (objects[0])->dataType();
bool askForType = false;
for (uint i=1; i < objects.size(); i++)
if ( type != (objects[i])->dataType() ){
askForType = true;
break;
}
if(askForType)
{
QStringList types;
types.append(dataTypeName(DATA_TRIANGLE_MESH));
types.append(dataTypeName(DATA_POLY_MESH));
bool ok;
QString result = QInputDialog::getItem(nullptr,
tr("Select Mesh Type"),
tr("Convert meshes to:"),
types,
1,
false,
&ok);
if(ok)
{
if( result == dataTypeName(DATA_POLY_MESH))
{
type = DATA_POLY_MESH;
}
else
{
type = DATA_TRIANGLE_MESH;
}
}
else
return DataType();
}
return type;
}
/// init the Toolbox
void MergePlugin::initializePlugin() {
tool_ = new MergeToolBox();
QSize size(300, 300);
tool_->resize(size);
connect(tool_->mergeButton, SIGNAL( clicked() ), this, SLOT( mergeObjects() ) );
tool_->mergeButton->setStatusTip("Merge all target objects into one without changing geometry");
tool_->mergeButton->setToolTip( tool_->mergeButton->statusTip() );
connect(this,SIGNAL(cleanup(DataType, bool)),this,SLOT(slotCleanup(DataType, bool)),Qt::QueuedConnection);
emit addToolbox( tr("Merge") , tool_ );
polyMergeID = -1;
triMergeID = -1;
}
void MergePlugin::pluginsInitialized()
{
//populate scripting function
emit setSlotDescription("mergeObjects(const std::vector< BaseObjectData* >,QString,bool)", "Merges multiple meshes into one mesh. returns the ID of the new mesh or -1 in case of error.",
QString("objects,mergedName,deleteSeparateObjects").split(","),
QString(" vector of BaseObjectData* containing Poly or TriMeshes to be merged, name for the merged object, flag to remove separated objects default is true").split(","));
}
int MergePlugin::mergeObjects(const std::vector< BaseObjectData* > _objects, QString _name, bool _deleteSeparateObjects)
{
int result = -1;
if (_objects.size() < 2)
return -1; //nothing to do
objects = _objects;
//check dataType
DataType type = checkType(objects);
//user pushed the cancel button
if(type != DATA_TRIANGLE_MESH && type != DATA_POLY_MESH)
return -1;
convertedIds.clear();
std::vector< TriMesh* > triMeshes;
std::vector< PolyMesh* > polyMeshes;
TriMesh* triMergePtr;
PolyMesh* polyMergePtr;
emit addEmptyObject(DATA_POLY_MESH, polyMergeID);
PluginFunctions::getMesh(polyMergeID, polyMergePtr);
polyMeshes.push_back(polyMergePtr);
emit addEmptyObject(DATA_TRIANGLE_MESH, triMergeID);
PluginFunctions::getMesh(triMergeID,triMergePtr);
triMeshes.push_back(triMergePtr);
getAllMeshes(triMeshes,objects);
getAllMeshes(polyMeshes,objects);
if ( type == DATA_TRIANGLE_MESH ) {
// Convert PolyMeshes to TriMeshes
convertMeshes(DATA_POLY_MESH,convertedIds,triMeshes);
*triMergePtr = *triMeshes[1];
mergeMeshes(triMeshes);
(triMeshes[0])->update_normals();
BaseObject* bo;
PluginFunctions::getObject(triMergeID,bo);
bo->setName(_name);
result = bo->id();
} else {
// Convert TriMeshes to PolyMeshes
convertMeshes(DATA_TRIANGLE_MESH,convertedIds,polyMeshes);
*polyMergePtr = *polyMeshes[1];
mergeMeshes(polyMeshes);
(polyMeshes[0])->update_normals();
BaseObject* bo;
PluginFunctions::getObject(polyMergeID,bo);
bo->setName(_name);
result = bo->id();
}
emit updatedObject(triMergeID,UPDATE_ALL);
emit updatedObject(polyMergeID,UPDATE_ALL);
//clean up after merging (removes OF objects)
emit cleanup( type, _deleteSeparateObjects );
return result;
}
/// merge two objects with target flag
void MergePlugin::mergeObjects()
{
getTargets(objects);
mergeObjects(objects,tool_->mergedName->text(),tool_->deleteObjects->isChecked());
}
#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2( mergePlugin , MergePlugin );
#endif
#ifndef MERGEPLUGIN_HH
#define MERGEPLUGIN_HH
#include <QObject>
#include <QtGui>
#include <QCheckBox>
#include <QMenuBar>
#ifdef CGAL_AUTOLINK
#include <CGAL/auto_link/LAPACK.h>
#endif
#include <OpenFlipper/BasePlugin/BaseInterface.hh>
#include <OpenFlipper/BasePlugin/ToolboxInterface.hh>
#include <OpenFlipper/BasePlugin/LoadSaveInterface.hh>
#include <OpenFlipper/BasePlugin/LoggingInterface.hh>
#include <OpenFlipper/BasePlugin/ScriptInterface.hh>
#include <OpenFlipper/common/Types.hh>
#include <Math_Tools/PCA/PCA.hh>
#include <ObjectTypes/PolyMesh/PolyMesh.hh>
#include <ObjectTypes/TriangleMesh/TriangleMesh.hh>
#include "MergeToolbox.hh"
class MergePlugin : public QObject, BaseInterface, ToolboxInterface, LoggingInterface, LoadSaveInterface, ScriptInterface
{
Q_OBJECT
Q_INTERFACES(BaseInterface)
Q_INTERFACES(ToolboxInterface)
Q_INTERFACES(LoggingInterface)
Q_INTERFACES(LoadSaveInterface)
Q_INTERFACES(ScriptInterface)
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA(IID "org.OpenFlipper.Plugins.Plugin-Merge")
#endif
signals:
//BaseInterface
void updateView();
void updatedObject(int _identifier, const UpdateType _type);
//LoggingInterface:
void log( Logtype _type, QString _message );
void log( QString _message );
// LoadSaveInterface
void addEmptyObject( DataType _type, int &_objectId );
void deleteObject( int _id );
// ToolboxInterface
void addToolbox( QString _name , QWidget* _widget );
// ScriptInterface
void setSlotDescription(QString _slotName, QString _slotDescription,
QStringList _parameters, QStringList _descriptions);
void cleanup( DataType _type, bool _deleteSeparateObjects);
public :
~MergePlugin() {};
QString name() { return (QString("Merge")); };
QString description( ) { return (QString("Merge target objects")); };
private :
MergeToolBox* tool_;
std::vector<int> convertedIds;
std::vector< BaseObjectData* > objects;
int polyMergeID, triMergeID;
DataType checkType(const std::vector< BaseObjectData* > &);
public slots:
// BaseInterface
void initializePlugin();
void pluginsInitialized();
void mergeObjects();
int mergeObjects(const std::vector< BaseObjectData* > _objects, QString _name = "merged object", bool _deleteSeparateObjects = true);
void slotCleanup(DataType _type, bool _deleteSeparateObjects);
//template functions
private:
template< class MeshT >
void mergeMeshes( const std::vector< MeshT* >& _meshes );
template< class MeshT >
void mergeMeshes( const std::vector< MeshT* >& _meshes, typename MeshT::VertexHandle& _vhB);
public slots:
QString version() { return QString("1.1"); };
};
#if defined(INCLUDE_TEMPLATES) && !defined(MERGEPLUGIN_C)
#define MERGEPLUGIN_TEMPLATES
#include "MergePluginT.cc"
#endif
#endif //MERGEPLUGIN_HH
#define MERGEPLUGIN_C
#include "MergePlugin.hh"
#include <ACG/Math/GLMatrixT.hh>
#include <Math_Tools/Math_Tools.hh>
#include <OpenMesh/Core/Geometry/MathDefs.hh>
#include <MeshTools/MeshSelectionT.hh>
#include <MeshTools/MeshFunctions.hh>
#include <Plugin-HoleFilling/HoleFillerT.hh>
#include <OpenFlipper/BasePlugin/RPCWrappers.hh>
///merges Meshes into the first mesh
template< class MeshT >
void MergePlugin::mergeMeshes(const std::vector< MeshT* >& _meshes)
{
typename MeshT::VertexHandle vhB;
mergeMeshes(_meshes, vhB);
}
///merges meshes together and maps the VertexHandle _vhB from _meshes[max] to its new handle in _meshes[0]
template< class MeshT >
void MergePlugin::mergeMeshes(const std::vector< MeshT* >& _meshes, typename MeshT::VertexHandle& _vhB)
{
for (uint i=0; i < _meshes.size(); i++)
if ( _meshes[i] == 0) {
emit log(LOGERR,"Unable to get Meshes.");
return;
}
typename MeshT::VertexHandle tmp;
for (uint i=1; i < _meshes.size(); i++){
// COPY VERTICES into the first mesh
//
OpenMesh::VPropHandleT< typename MeshT::VertexHandle > vertexID;
_meshes[i]->add_property(vertexID, "Vertex ID Property" );
typename MeshT::VertexIter v_it;
typename MeshT::VertexIter v_end = _meshes[i]->vertices_end();
//iterate over all vertices of the current mesh
for (v_it = _meshes[i]->vertices_begin(); v_it != v_end; ++v_it){
//add vertex to _meshes[0] and set vertexID property
typename MeshT::VertexHandle vh = _meshes[0]->add_vertex( _meshes[i]->point(*v_it) );
_meshes[i]->property(vertexID, *v_it) = vh;
//map vertexHandle _vhB
if (*v_it == _vhB)
tmp = vh;
}
// COPY FACES into the first mesh
//
typename MeshT::FaceIter f_it;
typename MeshT::FaceIter f_end = _meshes[i]->faces_end();
//itertate over all faces of meshes[i]
for (f_it = _meshes[i]->faces_begin(); f_it != f_end; ++f_it){
//get corresponding VertexHandles
typename MeshT::FaceVertexIter fv_it;
std::vector< typename MeshT::VertexHandle > vHandles;
for (fv_it=_meshes[i]->fv_iter(*f_it); fv_it.is_valid(); ++fv_it)
vHandles.push_back( _meshes[i]->property(vertexID, *fv_it) );
//add faces to meshA
_meshes[0]->add_face(vHandles);
}
_meshes[i]->remove_property( vertexID );
}
_vhB = tmp;
}
#include "MergeToolbox.hh"
#include <QtGui>
MergeToolBox::MergeToolBox(QWidget *parent)
: QWidget(parent)
{
setupUi(this);
}
#include "ui_toolbox.hh"
#include <QtGui>
class MergeToolBox : public QWidget, public Ui::MergeTool
{
Q_OBJECT
public:
MergeToolBox(QWidget *parent = 0);
};
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MergeTool</class>
<widget class="QWidget" name="MergeTool">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>442</width>
<height>465</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Merging</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QPushButton" name="mergeButton">
<property name="text">
<string>merge multiple objects</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="mergedName">
<property name="text">
<string>Name for merged object</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="deleteObjects">
<property name="text">
<string>delete separate objects after merge</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>98</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
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