Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
SmootherPlugin.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49
50
51
52 #include "SmootherPlugin.hh"
53
54
55 #include <ObjectTypes/PolyMesh/PolyMesh.hh>
56 #include <ObjectTypes/TriangleMesh/TriangleMesh.hh>
57
58 SmootherPlugin::SmootherPlugin() :
59 iterationsSpinbox_(0)
60 {
61
62 }
63
64 SmootherPlugin::~SmootherPlugin()
65 {
66
67 }
68
69 void SmootherPlugin::initializePlugin()
70 {
71 // Create the Toolbox Widget
72 QWidget* toolBox = new QWidget();
73 QGridLayout* layout = new QGridLayout(toolBox);
74
75 QPushButton* smoothButton = new QPushButton("&Smooth",toolBox);
76 smoothButton->setToolTip(tr("Smooths an Object using Laplacian Smoothing."));
77 smoothButton->setWhatsThis(tr("Smooths an Object using Laplacian Smoothing. Use the Smooth Plugin for more options."));
78
79
80
81 iterationsSpinbox_ = new QSpinBox(toolBox) ;
82 iterationsSpinbox_->setMinimum(1);
83 iterationsSpinbox_->setMaximum(1000);
84 iterationsSpinbox_->setSingleStep(1);
85 iterationsSpinbox_->setToolTip(tr("The number of the smooting operations."));
86 iterationsSpinbox_->setWhatsThis(tr("Give the number, how often the Laplacian Smoothing should modify the object."));
87
88 QLabel* label = new QLabel("Iterations:");
89
90 layout->addWidget( label , 0, 0);
91 layout->addWidget( smoothButton , 1, 1);
92 layout->addWidget( iterationsSpinbox_, 0, 1);
93
94 layout->addItem(new QSpacerItem(10,10,QSizePolicy::Expanding,QSizePolicy::Expanding),2,0,1,2);
95
96 connect( smoothButton, SIGNAL(clicked()), this, SLOT(simpleLaplace()) );
97
98 QIcon* toolIcon = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"smoother1.png");
99 emit addToolbox( tr("Simple Smoother") , toolBox, toolIcon );
100 }
101
102 void SmootherPlugin::pluginsInitialized() {
103
104 // Emit slot description
105 emit setSlotDescription(tr("simpleLaplace(int)"), tr("Smooth mesh using the Laplace operator with uniform weights."),
106 QStringList(tr("iterations")), QStringList(tr("Number of iterations")));
107 }
108
114 void SmootherPlugin::simpleLaplace() {
115
116 int iterations = 1;
117
118 if(!OpenFlipper::Options::nogui()) {
119 iterations = iterationsSpinbox_->value();
120 }
121
122 simpleLaplace(iterations);
123 }
124
132 void SmootherPlugin::simpleLaplace(int _iterations) {
133
134 for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS) ; o_it != PluginFunctions::objectsEnd(); ++o_it) {
135
136 bool selectionExists = false;
137
138 if ( o_it->dataType( DATA_TRIANGLE_MESH ) ) {
139
140 // Get the mesh to work on
141 TriMesh* mesh = PluginFunctions::triMesh(*o_it);
142
143 // Property for the active mesh to store original point positions
144 OpenMesh::VPropHandleT< TriMesh::Point > origPositions;
145
146 // Add a property to the mesh to store original vertex positions
147 mesh->add_property( origPositions, "SmootherPlugin_Original_Positions" );
148
149 for ( int i = 0 ; i < _iterations ; ++i ) {
150
151 // Copy original positions to backup ( in Vertex property )
152 TriMesh::VertexIter v_it, v_end=mesh->vertices_end();
153 for (v_it=mesh->vertices_begin(); v_it!=v_end; ++v_it) {
154 mesh->property( origPositions, *v_it ) = mesh->point(*v_it);
155 // See if at least one vertex has been selected
156 selectionExists |= mesh->status(*v_it).selected();
157 }
158
159 // Do one smoothing step (For each point of the mesh ... )
160 for (v_it=mesh->vertices_begin(); v_it!=v_end; ++v_it) {
161
162 if(selectionExists && mesh->status(*v_it).selected() == false) {
163 continue;
164 }
165
166 TriMesh::Point point = TriMesh::Point(0.0,0.0,0.0);
167
168 // Flag, to skip boundary vertices
169 bool skip = false;
170
171 // ( .. for each Outoing halfedge .. )
172 TriMesh::VertexOHalfedgeIter voh_it(*mesh,*v_it);
173 for ( ; voh_it.is_valid(); ++voh_it ) {
174 // .. add the (original) position of the Neighbour ( end of the outgoing halfedge )
175 point += mesh->property( origPositions, mesh->to_vertex_handle(*voh_it) );
176
177 // Check if the current Halfedge is a boundary halfedge
178 // If it is, abort and keep the current vertex position
179 if ( mesh->is_boundary( *voh_it ) ) {
180 skip = true;
181 break;
182 }
183
184 }
185
186 // Devide by the valence of the current vertex
187 point /= mesh->valence( *v_it );
188
189 if ( ! skip ) {
190 // Set new position for the mesh if its not on the boundary
191 mesh->point(*v_it) = point;
192 }
193 }
194
195 }// Iterations end
196
197 // Remove the property
198 mesh->remove_property( origPositions );
199
200 mesh->update_normals();
201
202 emit updatedObject( o_it->id(), UPDATE_GEOMETRY );
203
204 // Create backup
205 emit createBackup(o_it->id(), "Simple Smoothing", UPDATE_GEOMETRY );
206
207 } else if ( o_it->dataType( DATA_POLY_MESH ) ) {
208
209 // Get the mesh to work on
210 PolyMesh* mesh = PluginFunctions::polyMesh(*o_it);
211
212 // Property for the active mesh to store original point positions
213 OpenMesh::VPropHandleT< TriMesh::Point > origPositions;
214
215 // Add a property to the mesh to store original vertex positions
216 mesh->add_property( origPositions, "SmootherPlugin_Original_Positions" );
217
218 for ( int i = 0 ; i < _iterations ; ++i ) {
219
220 // Copy original positions to backup ( in Vertex property )
221 PolyMesh::VertexIter v_it, v_end=mesh->vertices_end();
222 for (v_it=mesh->vertices_begin(); v_it!=v_end; ++v_it) {
223 mesh->property( origPositions, *v_it ) = mesh->point(*v_it);
224 // See if at least one vertex has been selected
225 selectionExists |= mesh->status(*v_it).selected();
226 }
227
228 // Do one smoothing step (For each point of the mesh ... )
229 for (v_it=mesh->vertices_begin(); v_it!=v_end; ++v_it) {
230
231 if(selectionExists && mesh->status(*v_it).selected() == false) {
232 continue;
233 }
234
235 PolyMesh::Point point = PolyMesh::Point(0.0,0.0,0.0);
236
237 // Flag, to skip boundary vertices
238 bool skip = false;
239
240 // ( .. for each Outoing halfedge .. )
241 PolyMesh::VertexOHalfedgeIter voh_it(*mesh,*v_it);
242 for ( ; voh_it.is_valid(); ++voh_it ) {
243 // .. add the (original) position of the Neighbour ( end of the outgoing halfedge )
244 point += mesh->property( origPositions, mesh->to_vertex_handle(*voh_it) );
245
246 // Check if the current Halfedge is a boundary halfedge
247 // If it is, abort and keep the current vertex position
248 if ( mesh->is_boundary( *voh_it ) ) {
249 skip = true;
250 break;
251 }
252
253 }
254
255 // Devide by the valence of the current vertex
256 point /= mesh->valence( *v_it );
257
258 if ( ! skip ) {
259 // Set new position for the mesh if its not on the boundary
260 mesh->point(*v_it) = point;
261 }
262 }
263
264 }// Iterations end
265
266 // Remove the property
267 mesh->remove_property( origPositions );
268
269 mesh->update_normals();
270
271 emit updatedObject( o_it->id() , UPDATE_GEOMETRY);
272
273 // Create backup
274 emit createBackup(o_it->id(), "Simple Smoothing", UPDATE_GEOMETRY);
275
276 } else {
277
278 emit log(LOGERR, "DataType not supported.");
279 }
280 }
281
282 // Show script logging
283 emit scriptInfo("simpleLaplace(" + QString::number(_iterations) + ")");
284
285 emit updateView();
286 }
287
288
289 #if QT_VERSION < 0x050000
290 Q_EXPORT_PLUGIN2( smootherplugin , SmootherPlugin );
291 #endif
292
293
294
SmootherPlugin
Definition: SmootherPlugin.hh:9
UPDATE_GEOMETRY
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
OpenMesh::PolyMesh_ArrayKernelT
Definition: PolyMesh_ArrayKernelT.hh:98
LOGERR
Definition: LoggingInterface.hh:107
TriangleMesh.hh
PluginFunctions::polyMesh
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
Definition: PluginFunctionsPolyMesh.cc:134
OpenMesh::PolyMeshT::Point
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:115
PluginFunctions::TARGET_OBJECTS
const QStringList TARGET_OBJECTS("target")
Iterable object range.
PluginFunctions::triMesh
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
Definition: PluginFunctionsTriangleMesh.cc:140
SmootherPlugin::simpleLaplace
void simpleLaplace()
simpleLaplace
Definition: SmootherPlugin.cc:78
OpenMesh::VPropHandleT
Definition: Property.hh:487
PluginFunctions::ObjectIterator
Core Data Iterator.
Definition: PluginFunctions.hh:452
PluginFunctions::objectsEnd
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
Definition: PluginFunctionsIterator.cc:187
DATA_POLY_MESH
#define DATA_POLY_MESH
Definition: PolyMesh.hh:65
OpenMesh::PolyMeshT::VertexOHalfedgeIter
Kernel::VertexOHalfedgeIter VertexOHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:166
PolyMesh.hh
OpenMesh::PolyMeshT::update_normals
void update_normals()
Compute normals for all primitives.
Definition: PolyMeshT.cc:241
SmootherPlugin::iterationsSpinbox_
QSpinBox * iterationsSpinbox_
SpinBox for Number of iterations.
Definition: SmootherPlugin.hh:34
SmootherPlugin::pluginsInitialized
void pluginsInitialized()
Set the scripting slot descriptions.
Definition: SmootherPlugin.cc:102
DATA_TRIANGLE_MESH
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:66