Developer Documentation

SmootherPlugin.cc
1 //=============================================================================
2 //
3 // OpenFlipper
4 // Copyright (C) 2008 by Computer Graphics Group, RWTH Aachen
5 // www.openflipper.org
6 //
7 //-----------------------------------------------------------------------------
8 //
9 // License
10 //
11 // OpenFlipper is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU Lesser General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // OpenFlipper is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public License
22 // along with OpenFlipper. If not, see <http://www.gnu.org/licenses/>.
23 //
24 //-----------------------------------------------------------------------------
25
26 //
27 //=============================================================================
28
29
30
31 #include "SmootherPlugin.hh"
32
33
34 #include <ObjectTypes/PolyMesh/PolyMesh.hh>
35 #include <ObjectTypes/TriangleMesh/TriangleMesh.hh>
36
37 #include "OpenFlipper/BasePlugin/PluginFunctions.hh"
38
39 SmootherPlugin::SmootherPlugin() :
40 iterationsSpinbox_(0)
41 {
42
43 }
44
45 void SmootherPlugin::initializePlugin()
46 {
47 // Create the Toolbox Widget
48 QWidget* toolBox = new QWidget();
49
50 QPushButton* smoothButton = new QPushButton("&Smooth", toolBox);
51
52 iterationsSpinbox_ = new QSpinBox(toolBox);
53 iterationsSpinbox_->setMinimum(1);
54 iterationsSpinbox_->setMaximum(1000);
55 iterationsSpinbox_->setSingleStep(1);
56
57 QLabel* label = new QLabel("Iterations:");
58
59 QGridLayout* layout = new QGridLayout(toolBox);
60
61 layout->addWidget(label, 0, 0);
62 layout->addWidget(smoothButton, 1, 1);
63 layout->addWidget(iterationsSpinbox_, 0, 1);
64
65 layout->addItem(new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding), 2, 0, 1, 2);
66
67 connect(smoothButton, SIGNAL(clicked()), this, SLOT(simpleLaplace()));
68
69 emit addToolbox(tr("Smoother"), toolBox);
70 }
71
75 void SmootherPlugin::simpleLaplace()
76 {
77
78 for (PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS); o_it != PluginFunctions::objectsEnd();
79 ++o_it) {
80
81 if (o_it->dataType(DATA_TRIANGLE_MESH)) {
82
83 // Get the mesh to work on
84 TriMesh* mesh = PluginFunctions::triMesh(*o_it);
85
86 // Property for the active mesh to store original point positions
87 OpenMesh::VPropHandleT<TriMesh::Point> origPositions;
88
89 // Add a property to the mesh to store original vertex positions
90 mesh->add_property(origPositions, "SmootherPlugin_Original_Positions");
91
92 for (int i = 0; i < iterationsSpinbox_->value(); ++i) {
93
94 // Copy original positions to backup ( in vertex property )
95 TriMesh::VertexIter v_it, v_end = mesh->vertices_end();
96 for (v_it = mesh->vertices_begin(); v_it != v_end; ++v_it) {
97 mesh->property(origPositions, v_it) = mesh->point(v_it);
98 }
99
100 // Do one smoothing step (For each point of the mesh ... )
101 for (v_it = mesh->vertices_begin(); v_it != v_end; ++v_it) {
102
103 TriMesh::Point point = TriMesh::Point(0.0, 0.0, 0.0);
104
105 // Flag, to skip boundary vertices
106 bool skip = false;
107
108 // ( .. for each outgoing halfedge .. )
109 TriMesh::VertexOHalfedgeIter voh_it(*mesh, v_it);
110
111 for (; voh_it; ++voh_it) {
112
113 // .. add the (original) position of the neighbour ( end of the outgoing halfedge )
114 point += mesh->property(origPositions, mesh->to_vertex_handle(voh_it));
115
116 // Check if the current Halfedge is a boundary halfedge
117 // If it is, abort and keep the current vertex position
118 if (mesh->is_boundary(*voh_it)) {
119 skip = true;
120 break;
121 }
122 }
123
124 // Devide by the valence of the current vertex
125 point /= mesh->valence(v_it);
126
127 if (!skip) {
128 // Set new position for the mesh if its not on the boundary
129 mesh->point(v_it) = point;
130 }
131 }
132
133 } // Iterations end
134
135 // Remove the property
136 mesh->remove_property(origPositions);
137
138 mesh->update_normals();
139
140 emit updatedObject(o_it->id(),UPDATE_GEOMETRY);
141
142 } else if (o_it->dataType(DATA_POLY_MESH)) {
143
144 // Get the mesh to work on
145 PolyMesh* mesh = PluginFunctions::polyMesh(*o_it);
146
147 // Property for the active mesh to store original point positions
148 OpenMesh::VPropHandleT<PolyMesh::Point> origPositions;
149
150 // Add a property to the mesh to store original vertex positions
151 mesh->add_property(origPositions, "SmootherPlugin_Original_Positions");
152
153 for (int i = 0; i < iterationsSpinbox_->value(); ++i) {
154
155 // Copy original positions to backup ( in Vertex property )
156 PolyMesh::VertexIter v_it, v_end = mesh->vertices_end();
157 for (v_it = mesh->vertices_begin(); v_it != v_end; ++v_it) {
158 mesh->property(origPositions, v_it) = mesh->point(v_it);
159 }
160
161 // Do one smoothing step (For each point of the mesh ... )
162 for (v_it = mesh->vertices_begin(); v_it != v_end; ++v_it) {
163
164 PolyMesh::Point point = PolyMesh::Point(0.0, 0.0, 0.0);
165
166 // Flag, to skip boundary vertices
167 bool skip = false;
168
169 // ( .. for each Outoing halfedge .. )
170 PolyMesh::VertexOHalfedgeIter voh_it(*mesh, v_it);
171 for (; voh_it; ++voh_it) {
172 // .. add the (original) position of the Neighbour ( end of the outgoing halfedge )
173 point += mesh->property(origPositions, mesh->to_vertex_handle(voh_it));
174
175 // Check if the current Halfedge is a boundary halfedge
176 // If it is, abort and keep the current vertex position
177 if (mesh->is_boundary(*voh_it)) {
178 skip = true;
179 break;
180 }
181
182 }
183
184 // Devide by the valence of the current vertex
185 point /= mesh->valence(v_it);
186
187 if (!skip) {
188 // Set new position for the mesh if its not on the boundary
189 mesh->point(v_it) = point;
190 }
191 }
192
193 } // Iterations end
194
195 // Remove the property
196 mesh->remove_property(origPositions);
197
198 mesh->update_normals();
199
200 emit updatedObject(o_it->id(),UPDATE_GEOMETRY);
201
202 } else {
203
204 emit log(LOGERR, "Data type not supported.");
205
206 } // Switch data type
207 }
208 }
209
210 Q_EXPORT_PLUGIN2( smootherplugin, SmootherPlugin);
211
TriangleMesh.hh
DATA_POLY_MESH
#define DATA_POLY_MESH
Definition: PolyMesh.hh:59
PluginFunctions.hh
PluginFunctions::TARGET_OBJECTS
const QStringList TARGET_OBJECTS("target")
Iterable object range.
BaseInterface::updatedObject
virtual void updatedObject(int _objectId)
An object has been changed or added by this plugin.
Definition: BaseInterface.hh:146
PluginFunctions::triMesh
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
Definition: PluginFunctionsTriangleMesh.cc:134
LOGERR
Definition: LoggingInterface.hh:96
UPDATE_GEOMETRY
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
SmootherPlugin
Definition: SmootherPlugin.hh:9
PluginFunctions::ObjectIterator
Core Data Iterator.
Definition: PluginFunctions.hh:441
PluginFunctions::objectsEnd
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
Definition: PluginFunctionsIterator.cc:177
PluginFunctions::polyMesh
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
Definition: PluginFunctionsPolyMesh.cc:128
DATA_TRIANGLE_MESH
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:60
PolyMesh.hh
SmootherPlugin::simpleLaplace
void simpleLaplace()
simpleLaplace
Definition: SmootherPlugin.cc:75
OpenMesh::VPropHandleT
Definition: Property.hh:482