Developer Documentation

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 //=============================================================================
45 //
46 // CLASS SmootherPlugin - IMPLEMENTATION
47 //
48 //=============================================================================
49
50
51 //== INCLUDES =================================================================
52
53
54 #include "SmootherPlugin.hh"
55
56 #include "SmootherObject.hh"
57
58
59 #define SMOOTHER "SmootherData"
60
61 //== IMPLEMENTATION ==========================================================
62
63 SmootherPlugin::SmootherPlugin() :
64 tool_(0),
65 toolIcon_(0)
66 {
67 }
68
69 //-----------------------------------------------------------------------------
70
71 void
72 SmootherPlugin::
73 initializePlugin()
74 {
75 if ( OpenFlipper::Options::gui() ) {
76 tool_ = new SmootherToolbarWidget();
77 QSize size(100, 100);
78 tool_->resize(size);
79
80 // connect signals->slots
81 connect(tool_->pB_smooth,SIGNAL(clicked() ),this,SLOT(slot_smooth()));
82
83 toolIcon_ = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"smoother2.png");
84 emit addToolbox( tr("Smoother") , tool_, toolIcon_ );
85 }
86 }
87
88 //-----------------------------------------------------------------------------
89
93 void
94 SmootherPlugin::pluginsInitialized(){
95
96 emit setSlotDescription("smooth(int,int,QString,QString,double,bool)", "Smooth an object",
97 QString("object_id,iterations,direction,continuity,maxDistance,respectFeatures").split(","),
98 QString("id of an object, number of smoothing iterations, Smoothing direction. (tangential;normal;tangential+normal), Continuity. (C1 or C2), max distance the smoothed mesh is allowed to differ from the original,Keep features intact").split(","));
99
100 emit setSlotDescription("smooth(int,int,QString,QString,double)", "Smooth an object",
101 QString("object_id,iterations,direction,continuity,maxDistance").split(","),
102 QString("id of an object, number of smoothing iterations, Smoothing direction. (tangential;normal;tangential+normal), Continuity. (C1 or C2), max distance the smoothed mesh is allowed to differ from the original").split(","));
103
104 emit setSlotDescription("smooth(int,int,QString,QString)", "Smooth an object",
105 QString("object_id,iterations,direction,continuity").split(","),
106 QString("id of an object, number of smoothing iterations, Smoothing direction. (tangential;normal;tangential+normal), Continuity. (C1 or C2)").split(","));
107
108 }
109
110
111 //-----------------------------------------------------------------------------
112
118 void
119 SmootherPlugin::
120 slot_smooth()
121 {
122 bool found = false;
123
124 for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DATA_TRIANGLE_MESH) ;
125 o_it != PluginFunctions::objectsEnd(); ++o_it) {
126
127 QString jobDescription = "Smoothed (";
128
129 TriMeshObject* object = PluginFunctions::triMeshObject(*o_it);
130
131 if ( object == 0 ) {
132 emit log(LOGWARN , "Unable to get object ( Only Triangle Meshes supported)");
133 continue;
134 }
135
136 found = true;
137
138 SmootherObject* data = dynamic_cast< SmootherObject* > ( o_it->objectData(SMOOTHER) );
139
140 // Get triangle mesh
141 TriMesh* mesh = PluginFunctions::triMesh(*o_it);
142
143 if ( mesh == NULL ) {
144 emit log(LOGERR, "Unable to get mesh from object( Only Triangle Meshes supported)");
145 return;
146 }
147
148 if (data == 0){
149 data = new SmootherObject();
150 o_it->setObjectData(SMOOTHER, data);
151 }
152
153 // Create smoother
154 SmootherType smoother(*mesh);
155
156 OpenMesh::Smoother::SmootherT< TriMesh >::Component component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential_and_Normal;
157 if( tool_->rbTangential_and_Normal->isChecked() ) {
158 component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential_and_Normal;
159 jobDescription += "tangential and normal,";
160 } else if( tool_->rbNormal->isChecked() ) {
161 component = OpenMesh::Smoother::SmootherT< TriMesh >::Normal;
162 jobDescription += "normal,";
163 } else if( tool_->rbTangential->isChecked() ) {
164 component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential;
165 jobDescription += "tangential,";
166 }
167
168 // Set perObjectData
169 data->component(component);
170
171 OpenMesh::Smoother::SmootherT< TriMesh >::Continuity continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C0;
172 if( tool_->rB_c0->isChecked() ) {
173 continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C0;
174 jobDescription += "C0";
175 } else if( tool_->rB_c1->isChecked() ) {
176 continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C1;
177 jobDescription += "C1";
178 }
179
180 // Set perObjectData
181 data->continuity(continuity);
182
183 // Read maximum distance Error from lineEdit
184 if ( tool_->cbDistance->isChecked() ) {
185 QString value;
186 value = tool_->distance->text();
187 bool ok = false;
188
189 double absoluteError = value.toDouble(&ok);
190
191 if ( ok ) {
192 data->distance(absoluteError);
193 smoother.set_absolute_local_error( absoluteError );
194 } else {
195 emit log(LOGWARN , "Unable to read distance error from LineEdit");
196 }
197
198 jobDescription += ",max_error: " + QString::number(absoluteError);
199 }
200
201 // Set perObjectData
202 data->features(tool_->respectFeatures->isChecked());
203 data->iterations(tool_->sB_iter->value());
204
205 // Initialize smoother
206
207 if(tool_->cbReinitialize->isChecked() || !data->initialized())
208 {
209 smoother.initialize(component,continuity );
210 data->initialized(true);
211 }
212
213 smoother.skip_features(data->features());
214
215 smoother.smooth( data->iterations() );
216
217 jobDescription += ") " + QString::number(tool_->sB_iter->value()) + " iterations";
218
219 mesh->update_normals();
220
221 emit updatedObject( o_it->id(), UPDATE_GEOMETRY );
222 emit createBackup(o_it->id(), "Smoothing", UPDATE_GEOMETRY );
223 }
224
225 if ( !found )
226 emit log(LOGERR , tr("Unable to smooth. No triangle mesh selected as target!") );
227
228 }
229
230
231 //-----------------------------------------------------------------------------
232
233 void SmootherPlugin::smooth(int _objectId , int _iterations , QString _direction , QString _continuity, double _maxDistance, bool _respectFeatures ) {
234
235 BaseObjectData* baseObjectData;
236 if ( ! PluginFunctions::getObject(_objectId,baseObjectData) ) {
237 emit log(LOGERR,"Unable to get Object");
238 return;
239 }
240
241 if ( baseObjectData->dataType() == DATA_TRIANGLE_MESH ) {
242 TriMeshObject* object = PluginFunctions::triMeshObject(baseObjectData);
243
244 QString jobDescription = "Smoothed (";
245
246 if ( object == 0 ) {
247 emit log(LOGWARN , "Unable to get object ( Only Triangle Meshes supported)");
248 return;
249 }
250
251 SmootherObject* data = dynamic_cast< SmootherObject* > ( object->objectData(SMOOTHER) );
252
253 // Get triangle mesh
254 TriMesh* mesh = PluginFunctions::triMesh(object);
255
256 if ( mesh == NULL ) {
257 emit log(LOGERR, "Unable to get mesh from object( Only Triangle Meshes supported)");
258 return;
259 }
260
261 if (data == 0){
262 data = new SmootherObject();
263 object->setObjectData(SMOOTHER, data);
264 }
265
266 SmootherType smoother(*mesh);
267
268 OpenMesh::Smoother::SmootherT< TriMesh >::Component component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential_and_Normal;
269 bool tangential = _direction.contains("tangential");
270 bool normal = _direction.contains("normal");
271
272 if ( tangential && normal ) {
273 component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential_and_Normal;
274 jobDescription += "tangential and normal,";
275 } else if ( tangential ) {
276 component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential;
277 jobDescription += "normal,";
278 } else {
279 component = OpenMesh::Smoother::SmootherT< TriMesh >::Normal;
280 jobDescription += "tangential,";
281 }
282
283 // Set perObjectData
284 data->component(component);
285
286 OpenMesh::Smoother::SmootherT< TriMesh >::Continuity continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C0;
287 bool c0 = _continuity.contains("C0");
288 bool c1 = _continuity.contains("C1");
289
290 if ( c0 && c1 )
291 std::cerr << "Continuity C0 + C1 ? Using C1" << std::endl;
292 if( c1 ) {
293 continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C1;
294 jobDescription += "C1";
295 } else if( c0 ) {
296 continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C0;
297 jobDescription += "C0";
298 }
299
300 // Set perObjectData
301 data->continuity(continuity);
302
303 if ( _maxDistance > 0.0) {
304 // Set perObjectData
305 data->distance(_maxDistance);
306 smoother.set_absolute_local_error( _maxDistance );
307 jobDescription += ",max_error: " + QString::number(_maxDistance);
308 } else {
309 // Set perObjectData
310 data->distance( FLT_MAX );
311 smoother.set_absolute_local_error( FLT_MAX );
312 }
313
314 // Keep features?
315 data->features(_respectFeatures);
316 smoother.skip_features(_respectFeatures);
317
318 smoother.initialize(component,continuity);
319
320 smoother.smooth( _iterations );
321
322 jobDescription += ") " + QString::number(_iterations) + " iterations";
323
324 mesh->update_normals();
325
326 emit updatedObject( object->id(), UPDATE_GEOMETRY );
327
328 // Create backup
329 emit createBackup(object->id(),"Smoothing", UPDATE_GEOMETRY );
330
331 emit scriptInfo(tr("smooth(%1, %2, %3, %4, %5)").arg(QString::number(_objectId), QString::number(_iterations),
332 _direction, _continuity, QString::number(_maxDistance)));
333
334 } else {
335 emit log(LOGERR,"Unsupported object type for smoother");
336 return;
337 }
338
339 }
340
341 //-----------------------------------------------------------------------------
342
343
LOGERR
Definition: LoggingInterface.hh:96
UPDATE_GEOMETRY
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
DATA_TRIANGLE_MESH
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:60
OpenMesh::Smoother::SmootherT
Definition: SmootherT.hh:76
OpenMesh::Smoother::JacobiLaplaceSmootherT::smooth
void smooth(unsigned int _n)
Do _n smoothing iterations.
Definition: JacobiLaplaceSmootherT_impl.hh:74
SmootherObject
Definition: SmootherObject.hh:51
PluginFunctions::getObject
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
Definition: PluginFunctions.cc:296
SmootherPlugin::tool_
SmootherToolbarWidget * tool_
Widget for Toolbox.
Definition: SmootherPlugin.hh:137
PluginFunctions::triMesh
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
Definition: PluginFunctionsTriangleMesh.cc:134
OpenMesh::Smoother::SmootherT::set_absolute_local_error
void set_absolute_local_error(Scalar _err)
Set local error as an absolute value.
Definition: SmootherT_impl.hh:278
LOGWARN
Definition: LoggingInterface.hh:95
SmootherPlugin::pluginsInitialized
void pluginsInitialized()
Set the scripting slot descriptions.
Definition: SmootherPlugin.cc:97
BaseObject::id
int id() const
Definition: BaseObject.cc:190
BaseObject::dataType
bool dataType(DataType _type) const
Definition: BaseObject.cc:221
PluginFunctions::objectsEnd
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
Definition: PluginFunctionsIterator.cc:177
OpenMesh::Smoother::JacobiLaplaceSmootherT
Definition: JacobiLaplaceSmootherT.hh:75
PluginFunctions::ObjectIterator
Core Data Iterator.
Definition: PluginFunctions.hh:441
PluginFunctions::triMeshObject
TriMeshObject * triMeshObject(BaseObjectData *_object)
Cast an BaseObject to a TriMeshObject if possible.
Definition: PluginFunctionsTriangleMesh.cc:156
TriMeshObject
Type for a MeshObject containing a triangle mesh.
Definition: TriangleMesh.hh:67
BaseObjectData
Definition: BaseObjectData.hh:102
SmootherPlugin::slot_smooth
void slot_smooth()
Slot connected to the smooth button in the toolbox.
Definition: SmootherPlugin.cc:120
PluginFunctions::TARGET_OBJECTS
const QStringList TARGET_OBJECTS("target")
Iterable object range.
SmootherToolbarWidget
Definition: SmootherToolbarWidget.hh:46
SmootherPlugin::smooth
void smooth(int _objectId, int _iterations, QString _direction, QString _continuity, double _maxDistance=-1.0, bool _respectFeatures=true)
smooth an object
Definition: SmootherPlugin.cc:233
OpenMesh::Smoother::SmootherT::Component
Component
Definition: SmootherT.hh:87
OpenMesh::Smoother::SmootherT::skip_features
void skip_features(bool _state)
enable or disable feature handling
Definition: SmootherT.hh:167