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