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