SmootherPlugin.cc 12.5 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-2011 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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
//=============================================================================
//
//  CLASS SmootherPlugin - IMPLEMENTATION
//
//=============================================================================


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

#include <QtGui>

#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
69 70 71 72 73 74 75
SmootherPlugin::SmootherPlugin() :
        tool_(0),
        toolIcon_(0)
{
}

//-----------------------------------------------------------------------------
76

Jan Möbius's avatar
Jan Möbius committed
77
void
78
SmootherPlugin::
Jan Möbius's avatar
Jan Möbius committed
79
initializePlugin()
80
{
81 82 83 84
  if ( OpenFlipper::Options::gui() ) {
    tool_ = new SmootherToolbarWidget();
    QSize size(100, 100);
    tool_->resize(size);
85

86 87
    // connect signals->slots
    connect(tool_->pB_smooth,SIGNAL(clicked() ),this,SLOT(slot_smooth()));
88

89 90 91
    toolIcon_ = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"smoother2.png");
    emit addToolbox( tr("Smoother") , tool_, toolIcon_ );
  }
92 93 94 95
}

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

Dirk Wilden's avatar
Dirk Wilden committed
96
/** \brief Set the scripting slot descriptions
97
 *
Dirk Wilden's avatar
Dirk Wilden committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
 */
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(","));

}


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

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

129 130
    QString jobDescription = "Smoothed (";
  
131 132 133 134 135 136 137
    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
138 139
    found = true;

140 141
    SmootherObject* data = dynamic_cast< SmootherObject* > ( o_it->objectData(SMOOTHER) );

142 143 144
    // Get triangle mesh
    TriMesh* mesh = PluginFunctions::triMesh(*o_it);
    
145
    if (data == 0){
146
      data = new SmootherObject();
147 148
      o_it->setObjectData(SMOOTHER, data);
    }
149 150 151
    
    // Create smoother
    SmootherType smoother(*mesh);
152 153

    OpenMesh::Smoother::SmootherT< TriMesh >::Component component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential_and_Normal;
154
    if( tool_->rbTangential_and_Normal->isChecked() ) {
155
      component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential_and_Normal;
156 157
      jobDescription += "tangential and normal,";
    } else if( tool_->rbNormal->isChecked() ) {
158
      component = OpenMesh::Smoother::SmootherT< TriMesh >::Normal;
159 160
      jobDescription += "normal,";
    } else if( tool_->rbTangential->isChecked() ) {
161
      component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential;
162 163
      jobDescription += "tangential,";
    }
164

165 166 167
    // Set perObjectData
    data->component(component);

168
    OpenMesh::Smoother::SmootherT< TriMesh >::Continuity continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C0;
169
    if( tool_->rB_c0->isChecked() ) {
170
      continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C0;
171 172
      jobDescription += "C0";
    } else if( tool_->rB_c1->isChecked() ) {
173
      continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C1;
174 175
      jobDescription += "C1";
    }
176 177 178
    
    // Set perObjectData
    data->continuity(continuity);
179 180 181 182 183 184 185 186 187

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

      double absoluteError = value.toDouble(&ok);

188 189 190 191
      if ( ok ) {
        data->distance(absoluteError);
        smoother.set_absolute_local_error( absoluteError );
      } else {
192
        emit log(LOGWARN , "Unable to read distance error from LineEdit");
193
      }
194 195
      
      jobDescription += ",max_error: " + QString::number(absoluteError);
196
    }
197
    
198 199 200 201 202
    // Set perObjectData
    data->features(tool_->respectFeatures->isChecked());
    data->iterations(tool_->sB_iter->value());
    
    // Initialize smoother
203 204 205 206 207 208 209

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

210
    smoother.skip_features(data->features());
211

212
    smoother.smooth( data->iterations() );
213 214
    
    jobDescription +=  ") " + QString::number(tool_->sB_iter->value()) + " iterations";
215 216

    if (mesh != 0)
217 218
//      mesh->garbage_collection();
      mesh->update_normals();
219

220
    emit updatedObject( o_it->id(), UPDATE_GEOMETRY );
Dirk Wilden's avatar
Dirk Wilden committed
221
    emit createBackup(o_it->id(), "Smoothing", UPDATE_GEOMETRY );
222 223
  }

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

227 228
}

Dirk Wilden's avatar
Dirk Wilden committed
229 230 231 232 233 234 235 236 237 238 239 240 241

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

/** \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
242 243 244 245 246 247 248 249 250
  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);

251 252
    QString jobDescription = "Smoothed (";
    
Jan Möbius's avatar
Jan Möbius committed
253 254 255 256 257 258 259
    if ( object == 0 ) {
      emit log(LOGWARN , "Unable to get object ( Only Triangle Meshes supported)");
      return;
    }

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

260 261 262
    // Get triangle mesh
    TriMesh* mesh = PluginFunctions::triMesh(object);
    
Jan Möbius's avatar
Jan Möbius committed
263
    if (data == 0){
264
      data = new SmootherObject();
Jan Möbius's avatar
Jan Möbius committed
265 266
      object->setObjectData(SMOOTHER, data);
    }
267 268
    
    SmootherType smoother(*mesh);
Jan Möbius's avatar
Jan Möbius committed
269 270 271 272 273

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

274
    if ( tangential && normal ) {
Jan Möbius's avatar
Jan Möbius committed
275
      component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential_and_Normal;
276 277
      jobDescription += "tangential and normal,";
    } else if ( tangential ) {
Jan Möbius's avatar
Jan Möbius committed
278
      component = OpenMesh::Smoother::SmootherT< TriMesh >::Tangential;
279 280
      jobDescription += "normal,";
    } else {
Jan Möbius's avatar
Jan Möbius committed
281
      component = OpenMesh::Smoother::SmootherT< TriMesh >::Normal;
282 283 284
      jobDescription += "tangential,";
    }
    
285 286
    // Set perObjectData
    data->component(component);
Jan Möbius's avatar
Jan Möbius committed
287 288 289 290 291 292 293

    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;
294
    if( c1 ) {
Jan Möbius's avatar
Jan Möbius committed
295
      continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C1;
296 297
      jobDescription += "C1";
    } else if( c0 ) {
Jan Möbius's avatar
Jan Möbius committed
298
      continuity = OpenMesh::Smoother::SmootherT< TriMesh >::C0;
299 300
      jobDescription += "C0";
    }
301 302 303
    
    // Set perObjectData
    data->continuity(continuity);
Jan Möbius's avatar
Jan Möbius committed
304

305
    if ( _maxDistance > 0.0) {
306 307 308
      // Set perObjectData
      data->distance(_maxDistance);
      smoother.set_absolute_local_error( _maxDistance );
309
      jobDescription += ",max_error: " + QString::number(_maxDistance);
310 311 312 313 314
    } else {
      // Set perObjectData
      data->distance( FLT_MAX );
      smoother.set_absolute_local_error( FLT_MAX );
    }
Dirk Wilden's avatar
Dirk Wilden committed
315

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

318
    smoother.smooth( _iterations );
Jan Möbius's avatar
Jan Möbius committed
319

320 321
    jobDescription +=  ") " + QString::number(_iterations) + " iterations";
    
Jan Möbius's avatar
Jan Möbius committed
322 323 324 325 326
    if (mesh != 0) {
      mesh->garbage_collection();
      mesh->update_normals();
    }

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

329
    // Create backup
Dirk Wilden's avatar
Dirk Wilden committed
330
    emit createBackup(object->id(),"Smoothing", UPDATE_GEOMETRY );
331 332 333
    
    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
334 335 336 337 338 339 340 341

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

}

342 343 344 345
//-----------------------------------------------------------------------------

Q_EXPORT_PLUGIN2( SmootherPlugin , SmootherPlugin );