Commit 386e8a9b authored by Dirk Wilden's avatar Dirk Wilden

added smoother doku

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@5073 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 8778fbba
......@@ -12,7 +12,7 @@
*
* \section plugin_prog_sec Plugin programming
* The interface between the core and the plugins is managed via simple interfaces based on the signal/slot
* metaphor of qt. Your plugins have to be derived from these interfaces. You dont have to implementation
* metaphor of qt. Your plugins have to be derived from these interfaces. You dont have to implement
* all functions or signals of the interfaces you include. This has only to be done for the BaseInterface
* which must be implemented by every plugin. See the BaseInterface Documentation for details.
*
......@@ -110,7 +110,129 @@
*
* To test if our plugin has been successfully loaded, we launch OpenFlipper and select \c Plugins->Unload \c Plugin.
* If our plugin \c SimplePlugin is listed, everything is fine. If it's not listed, read OpenFlippers
* log to see what happened wrong.
* log to see what went wrong.
*
* See \ref dataFlow for further information on interface function calls.
*
*
* \section ex2 Implementing a mesh smoother Plugin
*
* The last section dealt with the implementation of a first plugin without any functionality at all. This section
* will show you how to progam a simple mesh smoother. We are assuming that you have read \ref ex1 and will only
* explain parts that have to be added in order to include new functionality.
*
*
* \subsection ex2Header Definition of the header
*
* To start of we first have to add two additional header files. The first one is the \c ToolboxInterface.
* We need this interface because we want to add a Toolbox to our plugin in order to be able to set parameters.
* Additionally, we want to use the \c LoggingInterface so that we can inform the user of our plugin when something
* went wrong.
*
* \dontinclude example/SmootherPlugin.hh
* \skipline #include <OpenFlipper/BasePlugin/ToolboxInterface.hh>
* \skipline #include <OpenFlipper/BasePlugin/LoggingInterface.hh>
*
* In order to work with the Interfaces we have to define that the plugin will implement the additional interfaces.
* The class definition then looks as follows:
*
* \dontinclude example/SmootherPlugin.hh
* \skipline class SmootherPlugin
*
* Furthermore we have to insert the \c Q_INTERFACES macro. This makes the signals and slots from both interfaces available.
*
* \dontinclude example/SmootherPlugin.hh
* \skipline Q_INTERFACES(ToolboxInterface)
* \skipline Q_INTERFACES(LoggingInterface)
*
* Now that we have defined which Interfaces to implement, we can look at which signals and slots we want to implement.
* Firstly, we need two additional signals from the \c BaseInterface :
*
* \dontinclude example/SmootherPlugin.hh
* \skipline void updateView()
* \skipline void updatedObject(
*
* The first signal updateView() is emitted when we have finished computing the smoothed mesh. The signal tells OpenFlipper
* to redraw its viewer(s). The second signal updatedObjects() is emitted to inform all other plugins that an object
* has changed and therfore allows each plugin to react on this change.
*
* Since we also want to use the \c LoggingInterface we have to define the following signals which allow us to send
* log messages to the OpenFlipper Loggers.
*
* \dontinclude example/SmootherPlugin.hh
* \skipline void log(
* \skipline void log(
*
*
* The last Interface that's left over is the \c ToolboxInterface from which we are only implenting one function:
*
* \dontinclude example/SmootherPlugin.hh
* \skipline bool initializeToolbox
*
* As we will see later, this function is used to setup a ToolBox (i.e. a \c QWidget ) and return a reference of this
* ToolBox to OpenFlipper so that it can be intergrated into the GUI.
*
* As a last step we have to add to include additional class members to control the parameter for the smoothing and
* to actually compute the smoothed mesh.
*
* \dontinclude example/SmootherPlugin.hh
* \skipline private:
* \until Laplace();
*
* That's it for the header of the plugin. The complete header looks like this:
*
* \include example/SmootherPlugin.hh
*
*
* \subsection ex2Implemenation1 Implemention of the GUI
*
* As we have already mentioned in \ref ex2Header, the ToolBox is generated inside the initializeToolbox() function.
* So inside this function we begin with creating the elements of the ToolBox:
*
* \dontinclude example/SmootherPlugin.cc
* \skipline QWidget
* \until Iterations:");
*
* Later, the smoothButton is used to start the mesh smoothing and the iterationsSpinbox_ allows the user to control
* the number of smoothing iterations that should be performed.
*
* The created Toolbox elements are then combined into a Layout
*
* \dontinclude example/SmootherPlugin.cc
* \skipline QGridLayout
* \until 2,0,1,2);
*
* Here, the SpacerItem, which is added last, only helps aligning the elements at the top of the toolbox.
*
* We have to connect the smoothButton to the simpleLaplace() slot of our class, so that after clicking
* the button the slot is called. Finally, we return a reference to the new Toolbox by assigning it to _widget and
* return true because we succesfully created the Toolbox.
*
* \dontinclude example/SmootherPlugin.cc
* \skipline connect
* \until true;
*
*
* \subsection ex2Implemenation2 Implemention of the Smoother
*
* Now that the Toolbox is completely setup, we can start implementing the smoother. We begin with searching objects
* on which we have to compute the smoothing. The algorithm takes all objects marked as target and tries to apply the
* smoothing.
*
* To find all these Objects we use an ObjectIterator. This iterator can be found in the PluginFunctions. Every
* communication between OpenFlipper and its Plugins is accomplished through either an interface or the PluginFunctions.
* So these are the places to look for if you want to add additional functionality and therefore need to communicate
* with OpenFlipper.
*
* We initialize the PluginFunctions::ObjectIterator with PluginFunctions::TARGET_OBJECTS and thereby make sure that the
* the iteration is restricted to target objects only.
*
* \dontinclude example/SmootherPlugin.cc
* \skipline void SmootherPlugin::simpleLaplace() {
* \until ++o_it) {
*
*
*
*
*
*/
//=============================================================================
//
// OpenFlipper
// Copyright (C) 2008 by Computer Graphics Group, RWTH Aachen
// www.openflipper.org
//
//-----------------------------------------------------------------------------
//
// License
//
// 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.
//
// 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 Lesser General Public License
// along with OpenFlipper. If not, see <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
//
// $Revision: 4796 $
// $Author: moebius $
// $Date: 2009-02-12 10:09:43 +0100 (Thu, 12 Feb 2009) $
//
//=============================================================================
#include "SmootherPlugin.hh"
#include <ObjectTypes/PolyMesh/PolyMesh.hh>
#include <ObjectTypes/TriangleMesh/TriangleMesh.hh>
#include "OpenFlipper/BasePlugin/PluginFunctions.hh"
bool SmootherPlugin::initializeToolbox(QWidget*& _widget)
{
// Create the Toolbox Widget
QWidget* toolBox = new QWidget();
QPushButton* smoothButton = new QPushButton("&Smooth",toolBox);
iterationsSpinbox_ = new QSpinBox(toolBox) ;
iterationsSpinbox_->setMinimum(1);
iterationsSpinbox_->setMaximum(1000);
iterationsSpinbox_->setSingleStep(1);
QLabel* label = new QLabel("Iterations:");
QGridLayout* layout = new QGridLayout(toolBox);
layout->addWidget( label , 0, 0);
layout->addWidget( smoothButton , 1, 1);
layout->addWidget( iterationsSpinbox_, 0, 1);
layout->addItem(new QSpacerItem(10,10,QSizePolicy::Expanding,QSizePolicy::Expanding),2,0,1,2);
connect( smoothButton, SIGNAL(clicked()), this, SLOT(simpleLaplace()) );
_widget = toolBox;
return true;
}
/** \brief
*
*/
void SmootherPlugin::simpleLaplace() {
for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS) ; o_it != PluginFunctions::objectsEnd(); ++o_it) {
if ( o_it->dataType( DATA_TRIANGLE_MESH ) ) {
// Get the mesh to work on
TriMesh* mesh = PluginFunctions::triMesh(*o_it);
// Property for the active mesh to store original point positions
OpenMesh::VPropHandleT< TriMesh::Point > origPositions;
// Add a property to the mesh to store original vertex positions
mesh->add_property( origPositions, "SmootherPlugin_Original_Positions" );
for ( int i = 0 ; i < iterationsSpinbox_->value() ; ++i ) {
// Copy original positions to backup ( in Vertex property )
TriMesh::VertexIter v_it, v_end=mesh->vertices_end();
for (v_it=mesh->vertices_begin(); v_it!=v_end; ++v_it) {
mesh->property( origPositions, v_it ) = mesh->point(v_it);
}
// Do one smoothing step (For each point of the mesh ... )
for (v_it=mesh->vertices_begin(); v_it!=v_end; ++v_it) {
TriMesh::Point point = TriMesh::Point(0.0,0.0,0.0);
// Flag, to skip boundary vertices
bool skip = false;
// ( .. for each Outoing halfedge .. )
TriMesh::VertexOHalfedgeIter voh_it(*mesh,v_it);
for ( ; voh_it; ++voh_it ) {
// .. add the (original) position of the Neighbour ( end of the outgoing halfedge )
point += mesh->property( origPositions, mesh->to_vertex_handle(voh_it) );
// Check if the current Halfedge is a boundary halfedge
// If it is, abort and keep the current vertex position
if ( mesh->is_boundary( voh_it.handle() ) ) {
skip = true;
break;
}
}
// Devide by the valence of the current vertex
point /= mesh->valence( v_it );
if ( ! skip ) {
// Set new position for the mesh if its not on the boundary
mesh->point(v_it) = point;
}
}
}// Iterations end
// Remove the property
mesh->remove_property( origPositions );
mesh->update_normals();
emit updatedObject( o_it->id() );
} else if ( o_it->dataType( DATA_POLY_MESH ) ) {
// Get the mesh to work on
PolyMesh* mesh = dynamic_cast< MeshObject< PolyMesh,DATA_POLY_MESH >* > (*o_it)->mesh();
// Property for the active mesh to store original point positions
OpenMesh::VPropHandleT< TriMesh::Point > origPositions;
// Add a property to the mesh to store original vertex positions
mesh->add_property( origPositions, "SmootherPlugin_Original_Positions" );
for ( int i = 0 ; i < iterationsSpinbox_->value() ; ++i ) {
// Copy original positions to backup ( in Vertex property )
PolyMesh::VertexIter v_it, v_end=mesh->vertices_end();
for (v_it=mesh->vertices_begin(); v_it!=v_end; ++v_it) {
mesh->property( origPositions, v_it ) = mesh->point(v_it);
}
// Do one smoothing step (For each point of the mesh ... )
for (v_it=mesh->vertices_begin(); v_it!=v_end; ++v_it) {
PolyMesh::Point point = PolyMesh::Point(0.0,0.0,0.0);
// Flag, to skip boundary vertices
bool skip = false;
// ( .. for each Outoing halfedge .. )
PolyMesh::VertexOHalfedgeIter voh_it(*mesh,v_it);
for ( ; voh_it; ++voh_it ) {
// .. add the (original) position of the Neighbour ( end of the outgoing halfedge )
point += mesh->property( origPositions, mesh->to_vertex_handle(voh_it) );
// Check if the current Halfedge is a boundary halfedge
// If it is, abort and keep the current vertex position
if ( mesh->is_boundary( voh_it.handle() ) ) {
skip = true;
break;
}
}
// Devide by the valence of the current vertex
point /= mesh->valence( v_it );
if ( ! skip ) {
// Set new position for the mesh if its not on the boundary
mesh->point(v_it) = point;
}
}
}// Iterations end
// Remove the property
mesh->remove_property( origPositions );
mesh->update_normals();
emit updatedObject( o_it->id() );
} else {
emit log(LOGERR, "DataType not supported.");
}
}
}
Q_EXPORT_PLUGIN2( smootherplugin , SmootherPlugin );
#ifndef SMOOTHERPLUGIN_HH
#define SMOOTHERPLUGIN_HH
#include <OpenFlipper/BasePlugin/BaseInterface.hh>
#include <OpenFlipper/BasePlugin/ToolboxInterface.hh>
#include <OpenFlipper/BasePlugin/LoggingInterface.hh>
#include <OpenFlipper/common/Types.hh>
class SmootherPlugin : public QObject, BaseInterface, ToolboxInterface, LoggingInterface
{
Q_OBJECT
Q_INTERFACES(BaseInterface)
Q_INTERFACES(ToolboxInterface)
Q_INTERFACES(LoggingInterface)
signals:
//BaseInterface
void updateView();
void updatedObject(int _id);
//LoggingInterface
void log(Logtype _type, QString _message);
void log(QString _message);
public:
// ToolboxInterface
bool initializeToolbox(QWidget*& _widget);
// BaseInterface
QString name() { return (QString("Simple Smoother")); };
QString description( ) { return (QString("Smooths the active Mesh")); };
private:
/// SpinBox for Number of iterations
QSpinBox* iterationsSpinbox_;
private slots:
void simpleLaplace();
public slots:
QString version() { return QString("1.0"); };
};
#endif //SMOOTHERPLUGIN_HH
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