SmootherPlugin.cc 12.7 KB
Newer Older
1
/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
2 3
*                                                                            *
*                              OpenFlipper                                   *
Jan Möbius's avatar
Jan Möbius committed
4
*      Copyright (C) 2001-2014 by Computer Graphics Group, RWTH Aachen       *
Jan Möbius's avatar
Jan Möbius committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
*                           www.openflipper.org                              *
*                                                                            *
*--------------------------------------------------------------------------- *
*  This file is part of OpenFlipper.                                         *
*                                                                            *
*  OpenFlipper is free software: you can redistribute it and/or modify       *
*  it under the terms of the GNU Lesser General Public License as            *
*  published by the Free Software Foundation, either version 3 of            *
*  the License, or (at your option) any later version with the               *
*  following exceptions:                                                     *
*                                                                            *
*  If other files instantiate templates or use macros                        *
*  or inline functions from this file, or you compile this file and          *
*  link it with other files to produce an executable, this file does         *
*  not by itself cause the resulting executable to be covered by the         *
*  GNU Lesser General Public License. This exception does not however        *
*  invalidate any other reasons why the executable file might be             *
*  covered by the GNU Lesser General Public License.                         *
*                                                                            *
*  OpenFlipper is distributed in the hope that it will be useful,            *
*  but WITHOUT ANY WARRANTY; without even the implied warranty of            *
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
*  GNU Lesser General Public License for more details.                       *
*                                                                            *
*  You should have received a copy of the GNU LesserGeneral Public           *
*  License along with OpenFlipper. If not,                                   *
*  see <http://www.gnu.org/licenses/>.                                       *
*                                                                            *
33 34 35
\*===========================================================================*/

/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
36 37 38 39 40
*                                                                            *
*   $Revision$                                                       *
*   $LastChangedBy$                                                *
*   $Date$                     *
*                                                                            *
41
\*===========================================================================*/
Jan Möbius's avatar
Jan Möbius committed
42

43 44 45 46 47 48 49 50 51
//=============================================================================
//
//  CLASS SmootherPlugin - IMPLEMENTATION
//
//=============================================================================


//== INCLUDES =================================================================

52 53 54 55 56 57 58

#if QT_VERSION >= 0x050000 
  #include <QtWidgets>
#else
  #include <QtGui>
#endif

59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74

#include "SmootherPlugin.hh"

#include <iostream>
#include <ACG/GL/GLState.hh>
#include <QStringList>
#include <ACG/Scenegraph/ManipulatorNode.hh>

#include <OpenFlipper/BasePlugin/PluginFunctions.hh>

#include "SmootherObject.hh"

#define SMOOTHER "SmootherData"

//== IMPLEMENTATION ==========================================================

Jan Möbius's avatar
Jan Möbius committed
75 76 77 78 79 80 81
SmootherPlugin::SmootherPlugin() :
        tool_(0),
        toolIcon_(0)
{
}

//-----------------------------------------------------------------------------
82

Jan Möbius's avatar
Jan Möbius committed
83
void
84
SmootherPlugin::
Jan Möbius's avatar
Jan Möbius committed
85
initializePlugin()
86
{
87 88 89 90
  if ( OpenFlipper::Options::gui() ) {
    tool_ = new SmootherToolbarWidget();
    QSize size(100, 100);
    tool_->resize(size);
91

92 93
    // connect signals->slots
    connect(tool_->pB_smooth,SIGNAL(clicked() ),this,SLOT(slot_smooth()));
94

95 96 97
    toolIcon_ = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"smoother2.png");
    emit addToolbox( tr("Smoother") , tool_, toolIcon_ );
  }
98 99 100 101
}

//-----------------------------------------------------------------------------

Dirk Wilden's avatar
Dirk Wilden committed
102
/** \brief Set the scripting slot descriptions
103
 *
Dirk Wilden's avatar
Dirk Wilden committed
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
 */
void
SmootherPlugin::pluginsInitialized(){

  emit setSlotDescription("smooth(int,int,QString,QString,double)", "Smooth an object",
                          QString("object_id,iterations,direction,continuity,maxDistance").split(","),
                          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(","));

  emit setSlotDescription("smooth(int,int,QString,QString)", "Smooth an object",
                          QString("object_id,iterations,direction,continuity").split(","),
                          QString("id of an object, number of smoothing iterations, Smoothing direction. (tangential;normal;tangential+normal), Continuity. (C1 or C2)").split(","));

}


//-----------------------------------------------------------------------------

121 122
/** \brief Smooth all target objects
 *
Dirk Wilden's avatar
Dirk Wilden committed
123 124 125
 * Parameters for the smoothing are retrieved from the toolbox
 *
 */
126 127 128 129
void
SmootherPlugin::
slot_smooth()
{
Dirk Wilden's avatar
Dirk Wilden committed
130 131
  bool found = false;
  
132 133 134
  for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DATA_TRIANGLE_MESH) ;
        o_it != PluginFunctions::objectsEnd(); ++o_it)  {

135 136
    QString jobDescription = "Smoothed (";
  
137 138 139 140 141 142 143
    TriMeshObject* object = PluginFunctions::triMeshObject(*o_it);

    if ( object == 0 ) {
      emit log(LOGWARN , "Unable to get object ( Only Triangle Meshes supported)");
      continue;
    }

Dirk Wilden's avatar
Dirk Wilden committed
144 145
    found = true;

146 147
    SmootherObject* data = dynamic_cast< SmootherObject* > ( o_it->objectData(SMOOTHER) );

148 149 150
    // Get triangle mesh
    TriMesh* mesh = PluginFunctions::triMesh(*o_it);
    
151 152 153 154 155
    if ( mesh == NULL ) {
      emit log(LOGERR, "Unable to get mesh from object( Only Triangle Meshes supported)");
      return;
    }

156
    if (data == 0){
157
      data = new SmootherObject();
158 159
      o_it->setObjectData(SMOOTHER, data);
    }
160 161 162
    
    // Create smoother
    SmootherType smoother(*mesh);
163 164

    OpenMesh::Smoother::SmootherT< TriMesh >::Component component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential_and_Normal;
165
    if( tool_->rbTangential_and_Normal->isChecked() ) {
166
      component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential_and_Normal;
167 168
      jobDescription += "tangential and normal,";
    } else if( tool_->rbNormal->isChecked() ) {
169
      component = OpenMesh::Smoother::SmootherT< TriMesh >::Normal;
170 171
      jobDescription += "normal,";
    } else if( tool_->rbTangential->isChecked() ) {
172
      component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential;
173 174
      jobDescription += "tangential,";
    }
175

176 177 178
    // Set perObjectData
    data->component(component);

179
    OpenMesh::Smoother::SmootherT< TriMesh >::Continuity continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C0;
180
    if( tool_->rB_c0->isChecked() ) {
181
      continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C0;
182 183
      jobDescription += "C0";
    } else if( tool_->rB_c1->isChecked() ) {
184
      continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C1;
185 186
      jobDescription += "C1";
    }
187 188 189
    
    // Set perObjectData
    data->continuity(continuity);
190 191 192 193 194 195 196 197 198

    // Read maximum distance Error from lineEdit
    if ( tool_->cbDistance->isChecked() ) {
      QString value;
      value = tool_->distance->text();
      bool ok = false;

      double absoluteError = value.toDouble(&ok);

199 200 201 202
      if ( ok ) {
        data->distance(absoluteError);
        smoother.set_absolute_local_error( absoluteError );
      } else {
203
        emit log(LOGWARN , "Unable to read distance error from LineEdit");
204
      }
205 206
      
      jobDescription += ",max_error: " + QString::number(absoluteError);
207
    }
208
    
209 210 211 212 213
    // Set perObjectData
    data->features(tool_->respectFeatures->isChecked());
    data->iterations(tool_->sB_iter->value());
    
    // Initialize smoother
214 215 216 217 218 219 220

    if(tool_->cbReinitialize->isChecked() || !data->initialized())
    {
         smoother.initialize(component,continuity );
         data->initialized(true);
    }

221
    smoother.skip_features(data->features());
222

223
    smoother.smooth( data->iterations() );
224 225
    
    jobDescription +=  ") " + QString::number(tool_->sB_iter->value()) + " iterations";
226

227
    mesh->update_normals();
228

229
    emit updatedObject( o_it->id(), UPDATE_GEOMETRY );
Dirk Wilden's avatar
Dirk Wilden committed
230
    emit createBackup(o_it->id(), "Smoothing", UPDATE_GEOMETRY );
231 232
  }

Dirk Wilden's avatar
Dirk Wilden committed
233 234 235
  if ( !found )
    emit log(LOGERR , tr("Unable to smooth. No triangle mesh selected as target!") );

236 237
}

Dirk Wilden's avatar
Dirk Wilden committed
238 239 240 241 242 243 244 245 246 247 248 249 250

//-----------------------------------------------------------------------------

/** \brief  Smooth object
*
* @param _objectId Object to smooth
* @param _iterations Number of smoothing iterations
* @param _direction tangential/normal/tangential+normal
* @param _continuity C0/C1
* @param _maxDistance the maximum distance that the smoothed mesh is allowed to differ from the original mesh
*/
void SmootherPlugin::smooth(int _objectId , int _iterations , QString _direction , QString _continuity, double _maxDistance) {

Jan Möbius's avatar
Jan Möbius committed
251 252 253 254 255 256 257 258 259
  BaseObjectData* baseObjectData;
  if ( ! PluginFunctions::getObject(_objectId,baseObjectData) ) {
    emit log(LOGERR,"Unable to get Object");
    return;
  }

  if ( baseObjectData->dataType() == DATA_TRIANGLE_MESH ) {
    TriMeshObject* object = PluginFunctions::triMeshObject(baseObjectData);

260 261
    QString jobDescription = "Smoothed (";
    
Jan Möbius's avatar
Jan Möbius committed
262 263 264 265 266 267 268
    if ( object == 0 ) {
      emit log(LOGWARN , "Unable to get object ( Only Triangle Meshes supported)");
      return;
    }

    SmootherObject* data = dynamic_cast< SmootherObject* > ( object->objectData(SMOOTHER) );

269 270 271
    // Get triangle mesh
    TriMesh* mesh = PluginFunctions::triMesh(object);
    
272 273 274 275 276
    if ( mesh == NULL ) {
      emit log(LOGERR, "Unable to get mesh from object( Only Triangle Meshes supported)");
      return;
    }

Jan Möbius's avatar
Jan Möbius committed
277
    if (data == 0){
278
      data = new SmootherObject();
Jan Möbius's avatar
Jan Möbius committed
279 280
      object->setObjectData(SMOOTHER, data);
    }
281 282
    
    SmootherType smoother(*mesh);
Jan Möbius's avatar
Jan Möbius committed
283 284 285 286 287

    OpenMesh::Smoother::SmootherT< TriMesh >::Component component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential_and_Normal;
    bool tangential = _direction.contains("tangential");
    bool normal     = _direction.contains("normal");

288
    if ( tangential && normal ) {
Jan Möbius's avatar
Jan Möbius committed
289
      component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential_and_Normal;
290 291
      jobDescription += "tangential and normal,";
    } else if ( tangential ) {
Jan Möbius's avatar
Jan Möbius committed
292
      component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential;
293 294
      jobDescription += "normal,";
    } else {
Jan Möbius's avatar
Jan Möbius committed
295
      component = OpenMesh::Smoother::SmootherT< TriMesh >::Normal;
296 297 298
      jobDescription += "tangential,";
    }
    
299 300
    // Set perObjectData
    data->component(component);
Jan Möbius's avatar
Jan Möbius committed
301 302 303 304 305 306 307

    OpenMesh::Smoother::SmootherT< TriMesh >::Continuity continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C0;
    bool c0 = _continuity.contains("C0");
    bool c1 = _continuity.contains("C1");

    if ( c0 && c1 )
      std::cerr << "Continuity C0 + C1 ? Using C1" << std::endl;
308
    if( c1 ) {
Jan Möbius's avatar
Jan Möbius committed
309
      continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C1;
310 311
      jobDescription += "C1";
    } else if( c0 ) {
Jan Möbius's avatar
Jan Möbius committed
312
      continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C0;
313 314
      jobDescription += "C0";
    }
315 316 317
    
    // Set perObjectData
    data->continuity(continuity);
Jan Möbius's avatar
Jan Möbius committed
318

319
    if ( _maxDistance > 0.0) {
320 321 322
      // Set perObjectData
      data->distance(_maxDistance);
      smoother.set_absolute_local_error( _maxDistance );
323
      jobDescription += ",max_error: " + QString::number(_maxDistance);
324 325 326 327 328
    } else {
      // Set perObjectData
      data->distance( FLT_MAX );
      smoother.set_absolute_local_error( FLT_MAX );
    }
Dirk Wilden's avatar
Dirk Wilden committed
329

330
    smoother.initialize(component,continuity);
Jan Möbius's avatar
Jan Möbius committed
331

332
    smoother.smooth( _iterations );
Jan Möbius's avatar
Jan Möbius committed
333

334 335
    jobDescription +=  ") " + QString::number(_iterations) + " iterations";
    
336
    mesh->update_normals();
Jan Möbius's avatar
Jan Möbius committed
337

338
    emit updatedObject( object->id(), UPDATE_GEOMETRY );
Jan Möbius's avatar
Jan Möbius committed
339

340
    // Create backup
Dirk Wilden's avatar
Dirk Wilden committed
341
    emit createBackup(object->id(),"Smoothing", UPDATE_GEOMETRY );
342 343 344
    
    emit scriptInfo(tr("smooth(%1, %2, %3, %4, %5)").arg(QString::number(_objectId), QString::number(_iterations),
                                                    _direction, _continuity, QString::number(_maxDistance)));
Jan Möbius's avatar
Jan Möbius committed
345 346 347 348 349 350 351 352

  } else {
    emit log(LOGERR,"Unsupported object type for smoother");
    return;
  }

}

353 354
//-----------------------------------------------------------------------------

355 356 357
#if QT_VERSION < 0x050000
  Q_EXPORT_PLUGIN2( SmootherPlugin , SmootherPlugin );
#endif
358