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 
36 
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 
76 {
77 
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
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.is_valid(); ++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
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.is_valid(); ++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 
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:60
#define DATA_POLY_MESH
Definition: PolyMesh.hh:59
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
void simpleLaplace()
simpleLaplace
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(4))
Geometry updated.
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
const QStringList TARGET_OBJECTS("target")
Iterable object range.
virtual void updatedObject(int _objectId)
An object has been changed or added by this plugin.