Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 // $Revision$
27 // $Author$
28 // $Date$
29 //
30 //=============================================================================
31 
32 
33 
34 #include "SmootherPlugin.hh"
35 
36 
39 
41 
42 SmootherPlugin::SmootherPlugin() :
43  iterationsSpinbox_(0)
44 {
45 
46 }
47 
48 void SmootherPlugin::initializePlugin()
49 {
50  // Create the Toolbox Widget
51  QWidget* toolBox = new QWidget();
52 
53  QPushButton* smoothButton = new QPushButton("&Smooth", toolBox);
54 
55  iterationsSpinbox_ = new QSpinBox(toolBox);
56  iterationsSpinbox_->setMinimum(1);
57  iterationsSpinbox_->setMaximum(1000);
58  iterationsSpinbox_->setSingleStep(1);
59 
60  QLabel* label = new QLabel("Iterations:");
61 
62  QGridLayout* layout = new QGridLayout(toolBox);
63 
64  layout->addWidget(label, 0, 0);
65  layout->addWidget(smoothButton, 1, 1);
66  layout->addWidget(iterationsSpinbox_, 0, 1);
67 
68  layout->addItem(new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding), 2, 0, 1, 2);
69 
70  connect(smoothButton, SIGNAL(clicked()), this, SLOT(simpleLaplace()));
71 
72  emit addToolbox(tr("Smoother"), toolBox);
73 }
74 
79 {
80 
82  ++o_it) {
83 
84  if (o_it->dataType(DATA_TRIANGLE_MESH)) {
85 
86  // Get the mesh to work on
87  TriMesh* mesh = PluginFunctions::triMesh(*o_it);
88 
89  // Property for the active mesh to store original point positions
91 
92  // Add a property to the mesh to store original vertex positions
93  mesh->add_property(origPositions, "SmootherPlugin_Original_Positions");
94 
95  for (int i = 0; i < iterationsSpinbox_->value(); ++i) {
96 
97  // Copy original positions to backup ( in vertex property )
98  TriMesh::VertexIter v_it, v_end = mesh->vertices_end();
99  for (v_it = mesh->vertices_begin(); v_it != v_end; ++v_it) {
100  mesh->property(origPositions, v_it) = mesh->point(v_it);
101  }
102 
103  // Do one smoothing step (For each point of the mesh ... )
104  for (v_it = mesh->vertices_begin(); v_it != v_end; ++v_it) {
105 
106  TriMesh::Point point = TriMesh::Point(0.0, 0.0, 0.0);
107 
108  // Flag, to skip boundary vertices
109  bool skip = false;
110 
111  // ( .. for each outgoing halfedge .. )
112  TriMesh::VertexOHalfedgeIter voh_it(*mesh, v_it);
113 
114  for (; voh_it; ++voh_it) {
115 
116  // .. add the (original) position of the neighbour ( end of the outgoing halfedge )
117  point += mesh->property(origPositions, mesh->to_vertex_handle(voh_it));
118 
119  // Check if the current Halfedge is a boundary halfedge
120  // If it is, abort and keep the current vertex position
121  if (mesh->is_boundary(*voh_it)) {
122  skip = true;
123  break;
124  }
125  }
126 
127  // Devide by the valence of the current vertex
128  point /= mesh->valence(v_it);
129 
130  if (!skip) {
131  // Set new position for the mesh if its not on the boundary
132  mesh->point(v_it) = point;
133  }
134  }
135 
136  } // Iterations end
137 
138  // Remove the property
139  mesh->remove_property(origPositions);
140 
141  mesh->update_normals();
142 
143  emit updatedObject(o_it->id(),UPDATE_GEOMETRY);
144 
145  } else if (o_it->dataType(DATA_POLY_MESH)) {
146 
147  // Get the mesh to work on
148  PolyMesh* mesh = PluginFunctions::polyMesh(*o_it);
149 
150  // Property for the active mesh to store original point positions
152 
153  // Add a property to the mesh to store original vertex positions
154  mesh->add_property(origPositions, "SmootherPlugin_Original_Positions");
155 
156  for (int i = 0; i < iterationsSpinbox_->value(); ++i) {
157 
158  // Copy original positions to backup ( in Vertex property )
159  PolyMesh::VertexIter v_it, v_end = mesh->vertices_end();
160  for (v_it = mesh->vertices_begin(); v_it != v_end; ++v_it) {
161  mesh->property(origPositions, v_it) = mesh->point(v_it);
162  }
163 
164  // Do one smoothing step (For each point of the mesh ... )
165  for (v_it = mesh->vertices_begin(); v_it != v_end; ++v_it) {
166 
167  PolyMesh::Point point = PolyMesh::Point(0.0, 0.0, 0.0);
168 
169  // Flag, to skip boundary vertices
170  bool skip = false;
171 
172  // ( .. for each Outoing halfedge .. )
173  PolyMesh::VertexOHalfedgeIter voh_it(*mesh, v_it);
174  for (; voh_it; ++voh_it) {
175  // .. add the (original) position of the Neighbour ( end of the outgoing halfedge )
176  point += mesh->property(origPositions, mesh->to_vertex_handle(voh_it));
177 
178  // Check if the current Halfedge is a boundary halfedge
179  // If it is, abort and keep the current vertex position
180  if (mesh->is_boundary(*voh_it)) {
181  skip = true;
182  break;
183  }
184 
185  }
186 
187  // Devide by the valence of the current vertex
188  point /= mesh->valence(v_it);
189 
190  if (!skip) {
191  // Set new position for the mesh if its not on the boundary
192  mesh->point(v_it) = point;
193  }
194  }
195 
196  } // Iterations end
197 
198  // Remove the property
199  mesh->remove_property(origPositions);
200 
201  mesh->update_normals();
202 
203  emit updatedObject(o_it->id(),UPDATE_GEOMETRY);
204 
205  } else {
206 
207  emit log(LOGERR, "Data type not supported.");
208 
209  } // Switch data type
210  }
211 }
212 
213 Q_EXPORT_PLUGIN2( smootherplugin, SmootherPlugin);
214 
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:115
const QStringList TARGET_OBJECTS("target")
Iterable object range.
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
void simpleLaplace()
simpleLaplace
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
#define DATA_POLY_MESH
Definition: PolyMesh.hh:65
Kernel::VertexOHalfedgeIter VertexOHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:166
void update_normals()
Compute normals for all primitives.
Definition: PolyMeshT.cc:241
QSpinBox * iterationsSpinbox_
SpinBox for Number of iterations.
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:66