DecimaterPlugin.cc 28.7 KB
Newer Older
1 2 3 4 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 33 34 35 36
/*===========================================================================*\
*                                                                            *
*                              OpenFlipper                                   *
*      Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen       *
*                           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/>.                                       *
*                                                                            *
\*===========================================================================*/

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


44 45 46 47 48
//=============================================================================
//
//  CLASS DecimaterPlugin - IMPLEMENTATION
//
//=============================================================================
49 50


51
//== INCLUDES =================================================================
52

53
#include <QtGui>
54
#include <memory>
55

56
#include "DecimaterPlugin.hh"
57

58 59 60 61
#include <iostream>
#include <ACG/GL/GLState.hh>
#include <QStringList>
#include <ACG/Scenegraph/ManipulatorNode.hh>
62
#include <ACG/Utils/SmartPointer.hh>
63

64
#include <OpenFlipper/BasePlugin/PluginFunctions.hh>
65

66
#define DECIMATER "DecimaterData"
67

68
//== IMPLEMENTATION ==========================================================
69

70 71 72 73 74 75 76
DecimaterPlugin::DecimaterPlugin() :
        tool_(0),
        toolIcon_(0)
{

}

77 78 79 80 81
void DecimaterPlugin::initializePlugin()
{
  tool_ = new DecimaterToolbarWidget();
  QSize size(100, 100);
  tool_->resize(size);
82

83 84
  // connect signals->slots
  connect(tool_->pbDecimate,SIGNAL(clicked() ),this,SLOT(slot_decimate()));
85

86 87
  connect(tool_->roundness,SIGNAL(valueChanged(double) ),this,SLOT(updateRoundness(double)) );
  connect(tool_->roundnessSlider,SIGNAL(valueChanged(int) ),this,SLOT(updateRoundness(int)) );
88 89
  connect(tool_->aspectRatio,SIGNAL(valueChanged(double) ),this,SLOT(updateAspectRatio(double)) );
  connect(tool_->aspectRatioSlider,SIGNAL(valueChanged(int) ),this,SLOT(updateAspectRatio(int)) );
90
  connect(tool_->distance,SIGNAL(valueChanged(double) ),this,SLOT(updateDistance()) );
91
  connect(tool_->edgeLength,SIGNAL(valueChanged(double) ),this,SLOT(updateEdgeLength()) );
92 93 94 95
  connect(tool_->normalDeviation,SIGNAL(valueChanged(int) ),this,SLOT(updateNormalDev()) );
  connect(tool_->normalDeviationSlider,SIGNAL(valueChanged(int) ),this,SLOT(updateNormalDev()) );
  connect(tool_->verticesCount,SIGNAL(valueChanged(int) ),this,SLOT(updateVertices()) );
  connect(tool_->verticesCountSlider,SIGNAL(valueChanged(int) ),this,SLOT(updateVertices()) );
96 97
  connect(tool_->trianglesCount,SIGNAL(valueChanged(int) ),this,SLOT(updateTriangles()) );
  connect(tool_->trianglesCountSlider,SIGNAL(valueChanged(int) ),this,SLOT(updateTriangles()) );
98

99 100
  // Force update if the Toolbox gets visible
  connect(tool_, SIGNAL(showing()), this, SLOT( slotUpdateNumVertices() ) );
101
  connect(tool_, SIGNAL(showing()), this, SLOT( slotUpdateNumTriangles() ) );
102 103
  connect(tool_->mixedFactorCounter, SIGNAL(valueChanged(double)), this, SLOT(slotMixedCounterValueChanged(double)) );
  connect(tool_->mixedFactorSlider, SIGNAL(valueChanged(int)), this, SLOT(slotMixedSliderValueChanged(int)) );
104

105 106
  toolIcon_ = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"decimater.png");
  emit addToolbox( tr("Decimater") , tool_, toolIcon_ );
107 108
}

109
/** \brief Initialization of the plugin when it is loaded by the core
110
 *
111
 */
112
void DecimaterPlugin::pluginsInitialized() {
113

114 115
  emit setSlotDescription("decimate(int,QVariantMap)",tr("Decimate a given object"),
                          QString(tr("objectId,constraints")).split(","),
116
                          QString(tr("ID of an object; Object that can has one or more constraint properties (decimation_order,distance,edge_length,normal_deviation,roundness,aspect_ratio,independent_sets,vertices,triangles)")).split(";"));
117 118

  tool_->decTypeOps->setVisible(false);
119 120 121 122 123
}


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

124
/** \brief sync between values of roundness slider and spinbox in the toolbox
125
 *
126
 * @param _value new roundness value
127
 */
128 129 130 131
void DecimaterPlugin::updateRoundness(int _value)
{
  tool_->roundness->setValue( (double) _value / 100.0 );
  tool_->cbRoundness->setChecked (true);
132 133
}

134 135 136 137 138 139 140 141 142 143
void DecimaterPlugin::slotMixedCounterValueChanged(double _value)
{
  tool_->mixedFactorLabel->setText(QString::number(100-_value)+QString("%"));
  tool_->mixedFactorSlider->setValue(100-_value);
}
void DecimaterPlugin::slotMixedSliderValueChanged(int _value)
{
  tool_->mixedFactorLabel->setText(QString::number(_value)+QString("%"));
  tool_->mixedFactorCounter->setValue(100.0-_value);
}
144 145 146

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

147
/** \brief sync between values of roundness slider and spinbox in the toolbox
148
 *
149
 * @param _value new roundness value
150
 */
151 152 153 154
void DecimaterPlugin::updateRoundness(double _value)
{
  tool_->roundnessSlider->setValue( (int) (_value * 100) );
  tool_->cbRoundness->setChecked (true);
155 156 157 158
}

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

159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183

/** \brief sync between values of aspect ratio slider and spinbox in the toolbox
 *
 * @param _value new aspect ratio value
 */
void DecimaterPlugin::updateAspectRatio(int _value)
{
  tool_->aspectRatio->setValue( (double) _value / 100.0 );
  tool_->cbAspectRatio->setChecked (true);
}


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

/** \brief sync between values of aspect ratio slider and spinbox in the toolbox
 *
 * @param _value new aspect ratio value
 */
void DecimaterPlugin::updateAspectRatio(double _value)
{
  tool_->aspectRatioSlider->setValue( (int) (_value * 100) );
  tool_->cbAspectRatio->setChecked (true);
}

//-----------------------------------------------------------------------------
184
/** \brief Decimation called by toolbox
185 186
 *
 */
187
void DecimaterPlugin::slot_decimate()
188
{
189 190
  for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DATA_TRIANGLE_MESH) ;
                                        o_it != PluginFunctions::objectsEnd(); ++o_it)  {
191

192 193
    //initialize
    TriMeshObject* object = PluginFunctions::triMeshObject(*o_it);
194

195 196
    if ( object == 0 )
      emit log(LOGWARN , tr("Unable to get object"));
197

198
    DecimaterInfo* decimater = dynamic_cast< DecimaterInfo* > ( o_it->objectData(DECIMATER) );
199

200
    TriMesh* mesh = PluginFunctions::triMesh(*o_it);
201

202 203 204 205
    if (decimater == 0){
      decimater = new DecimaterInfo();
      o_it->setObjectData(DECIMATER, decimater);
    }
206

207 208 209 210 211 212 213 214 215
    // constraint handles for decimation
    ModAspectRatioH     hModAspectRatio;
    ModEdgeLengthH      hModEdgeLength;
    ModHausdorffH       hModHausdorff;
    ModIndependentH     hModIndependent;
    ModNormalDeviationH hModNormalDeviation;
    ModNormalFlippingH  hModNormalFlipping;
    ModQuadricH         hModQuadric;
    ModRoundnessH       hModRoundness;
216

217
    // Create decimater
218 219 220 221 222 223 224 225 226

    ptr::shared_ptr<BaseDecimaterType> decimater_object;
    if (tool_->rbUseDecimater->isChecked())
      decimater_object = ptr::shared_ptr<DecimaterType>(new DecimaterType(*mesh));
    else if(tool_->rbUseMC->isChecked())
      decimater_object = ptr::shared_ptr<McDecimaterType>(new McDecimaterType(*mesh));
    else if(tool_->rbUseMixed->isChecked())
      decimater_object = ptr::shared_ptr<MixedDecimaterType>(new MixedDecimaterType(*mesh));

227

228 229 230
    // Remove old constraints
    if(decimater->distance()) {
        decimater->removeDistanceConstraint();
231
        decimater_object->remove(hModHausdorff);
232 233 234
    }
    if(decimater->normalDeviation()) {
        decimater->removeNormalDeviationConstraint();
235
        decimater_object->remove(hModNormalDeviation);
236 237 238
    }
    if(decimater->normalFlipping()) {
        decimater->removeNormalFlippingConstraint();
239
        decimater_object->remove(hModNormalFlipping);
240 241 242
    }
    if(decimater->roundness()) {
        decimater->removeRoundnessConstraint();
243
        decimater_object->remove(hModRoundness);
244
    }
245 246
    if(decimater->aspectRatio()) {
      decimater->removeAspectRatioConstraint();
247
      decimater_object->remove(hModAspectRatio);
248 249 250
    }
    if(decimater->edgeLength()) {
      decimater->removeEdgeLengthConstraint();
251
      decimater_object->remove(hModEdgeLength);
252 253 254
    }
    if(decimater->independentSets()) {
      decimater->removeIndependentSetsConstraint();
255
      decimater_object->remove(hModIndependent);
256 257 258 259 260
    }

    // set priority module: quadric, normal deviation or edge length
    if (tool_->rbByDistance->isChecked()) {
      decimater->setDecimationOrder(DecimaterInfo::DISTANCE);
261 262
      decimater_object->add( hModQuadric );
      decimater_object->module( hModQuadric ).unset_max_err();
263 264
    } else if (tool_->rbByNormalDeviation->isChecked()) {
      decimater->setDecimationOrder(DecimaterInfo::NORMALDEV);
265 266 267 268 269
      std::cout << "add module" << std::endl;
      decimater_object->add(hModNormalDeviation);
      std::cout << "get module" << std::endl;
      decimater_object->module(hModNormalDeviation).set_binary(false);
      std::cout << "getted module" << std::endl;
270 271
    } else if (tool_->rbByEdgeLength->isChecked()) {
      decimater->setDecimationOrder(DecimaterInfo::EDGELENGTH);
272 273
      decimater_object->add(hModEdgeLength);
      decimater_object->module(hModEdgeLength).set_binary(false);
274
    }
275

276
    // and set new constraints
277
    if ( tool_->cbDistance->isChecked() ) {
278
      if (  decimater_object->add( hModHausdorff ) || tool_->rbConstraintsOnly->isChecked() ) {
279
          decimater->setDistanceConstraint( tool_->distance->value() );
280
          decimater_object->module( hModHausdorff ).set_tolerance( decimater->distanceValue() );
281 282
      }
    }
283

284
    if ( tool_->cbNormalDev->isChecked() ) {
285
      if (  decimater_object->add( hModNormalDeviation ) || tool_->rbConstraintsOnly->isChecked() ) {
286
          decimater->setNormalDeviationConstraint( tool_->normalDeviation->value() );
287
          decimater_object->module( hModNormalDeviation ).set_normal_deviation( decimater->normalDeviationValue() );
288 289
      }
    } else {
290
      if ( decimater_object->add( hModNormalFlipping ) || tool_->rbConstraintsOnly->isChecked() ) {
291
          decimater->setNormalFlippingConstraint();
292 293
      }
    }
294

295
    if ( tool_->cbRoundness->isChecked() ) {
296
      if (  decimater_object->add( hModRoundness ) || tool_->rbConstraintsOnly->isChecked() ) {
297
          decimater->setRoundnessConstraint( tool_->roundness->value() );
298
          decimater_object->module( hModRoundness ).set_min_roundness( decimater->roundnessValue(), true );
299 300
      }
    }
301

302
    if ( tool_->cbAspectRatio->isChecked() ) {
303
      if ( decimater_object->add( hModAspectRatio ) || tool_->rbConstraintsOnly->isChecked() ) {
304
          decimater->setAspectRatioConstraint( tool_->aspectRatio->value() );
305
          decimater_object->module( hModAspectRatio ).set_aspect_ratio( decimater->aspectRatioValue() );
306 307 308 309
      }
    }

    if ( tool_->cbEdgeLength->isChecked() ) {
310
      if ( decimater_object->add( hModEdgeLength ) || tool_->rbConstraintsOnly->isChecked() ) {
311
          decimater->setEdgeLengthConstraint( tool_->edgeLength->value() );
312
          decimater_object->module( hModEdgeLength ).set_edge_length( decimater->edgeLengthValue() );
313 314 315 316
      }
    }

    if ( tool_->cbIndependentSets->isChecked() ) {
317
      if ( decimater_object->add( hModIndependent ) || tool_->rbConstraintsOnly->isChecked() ) {
318 319 320 321
          decimater->setIndependentSetsConstraint();
      }
    }

322

323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
    if (tool_->rbUseDecimater)
    {
      // Initialize the decimater
      if( ! decimater_object->initialize() ){
        emit log(LOGWARN, tr("Decimater could not be initialized"));
        continue;
      }

      //decimate
      if(tool_->rbUseDecimater->isChecked())
      {
        DecimaterType* dec = dynamic_cast<DecimaterType*>(decimater_object.get());
        if ( tool_->rbVertices->isChecked() )
          dec->decimate_to(tool_->verticesCount->value());
        else if (tool_->rbTriangles->isChecked() )
          dec->decimate_to_faces(0, tool_->trianglesCount->value());
        else // constraints only
          dec->decimate_to_faces(0, 1);
      }
      else if (tool_->rbUseMC)
      {
        McDecimaterType* dec = dynamic_cast<McDecimaterType*>(decimater_object.get());
        dec->set_samples(tool_->randomSamplesCounter->value());
        if ( tool_->rbVertices->isChecked() )
          dec->decimate_to(tool_->verticesCount->value());
        else if (tool_->rbTriangles->isChecked() )
          dec->decimate_to_faces(0, tool_->trianglesCount->value());
        else // constraints only
          dec->decimate_to_faces(0, 1);
      }
      else if (tool_->rbUseMixed)
      {
        MixedDecimaterType* dec = dynamic_cast<MixedDecimaterType*>(decimater_object.get());
        float mc_factor = 1.0 - (tool_->mixedFactorCounter->value()*0.01);
        dec->set_samples(tool_->randomSamplesCounter->value());

        if ( tool_->rbVertices->isChecked() )
          dec->decimate_to(tool_->verticesCount->value(),mc_factor);
        else if (tool_->rbTriangles->isChecked() )
          dec->decimate_to_faces(0, tool_->trianglesCount->value(),mc_factor);
        else // constraints only
        dec->decimate_to_faces(0, 1,mc_factor);
      }
    }
367 368 369 370

    object->mesh()->garbage_collection();
    object->mesh()->update_normals();
    object->update();
371

372 373 374 375
    // Create backup
    emit createBackup(o_it->id(), "Decimation");
    emit updatedObject( o_it->id() , UPDATE_TOPOLOGY );
  }
376

377
  emit updateView();
378 379
}

Jan Möbius's avatar
Jan Möbius committed
380 381 382

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

383
void DecimaterPlugin::decimate(int _objID, QVariantMap _constraints) {
384

385 386 387 388 389 390 391 392
  BaseObjectData* baseObjectData;
  if ( ! PluginFunctions::getObject(_objID,baseObjectData) ) {
    emit log(LOGERR,tr("Unable to get Object"));
    return;
  }

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

394 395 396 397
    if ( object == 0 ) {
      emit log(LOGWARN , tr("Unable to get object ( Only Triangle Meshes supported)"));
      return;
    }
398

399
    DecimaterInfo* decimater = dynamic_cast< DecimaterInfo* > ( object->objectData(DECIMATER) );
400

401
    TriMesh* mesh = PluginFunctions::triMesh(baseObjectData);
402

403 404 405 406
    if (decimater == 0){
      decimater = new DecimaterInfo();
      object->setObjectData(DECIMATER, decimater);
    }
407

408
    // constraint handles for decimation
Jan Möbius's avatar
Jan Möbius committed
409 410 411 412
    ModAspectRatioH     hModAspectRatio;
    ModEdgeLengthH      hModEdgeLength;
    ModHausdorffH       hModHausdorff;
    ModIndependentH     hModIndependent;
413
    ModNormalDeviationH hModNormalDeviation;
Jan Möbius's avatar
Jan Möbius committed
414 415 416
    ModNormalFlippingH  hModNormalFlipping;
    ModQuadricH         hModQuadric;
    ModRoundnessH       hModRoundness;
417

418 419 420 421 422
    // Create decimater
    DecimaterType decimater_object( *mesh );

    // Remove old constraints
    if(decimater->distance()) {
423 424
      decimater->removeDistanceConstraint();
      decimater_object.remove(hModHausdorff);
425 426
    }
    if(decimater->normalDeviation()) {
427 428 429 430 431 432
      decimater->removeNormalDeviationConstraint();
      decimater_object.remove(hModNormalDeviation);
    }
    if(decimater->normalFlipping()) {
      decimater->removeNormalFlippingConstraint();
      decimater_object.remove(hModNormalFlipping);
433 434
    }
    if(decimater->roundness()) {
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
      decimater->removeRoundnessConstraint();
      decimater_object.remove(hModRoundness);
    }
    if(decimater->aspectRatio()) {
      decimater->removeAspectRatioConstraint();
      decimater_object.remove(hModAspectRatio);
    }
    if(decimater->edgeLength()) {
      decimater->removeEdgeLengthConstraint();
      decimater_object.remove(hModEdgeLength);
    }
    if(decimater->independentSets()) {
      decimater->removeIndependentSetsConstraint();
      decimater_object.remove(hModIndependent);
    }

    // set priority module: quadric, normal deviation or edge length
    if ( _constraints.contains("decimation_order") ){
      bool ok;

      int value = _constraints["decimation_order"].toInt(&ok);

      if (ok) {
        switch (value) {
        case 0:
          decimater->setDecimationOrder(DecimaterInfo::DISTANCE);
          decimater_object.add( hModQuadric );
462
          decimater_object.module( hModQuadric ).unset_max_err();
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
          break;
        case 1:
          decimater->setDecimationOrder(DecimaterInfo::NORMALDEV);
          decimater_object.add(hModNormalDeviation);
          decimater_object.module(hModNormalDeviation).set_binary(false);
          break;
        case 2:
          decimater->setDecimationOrder(DecimaterInfo::EDGELENGTH);
          decimater_object.add(hModEdgeLength);
          decimater_object.module(hModEdgeLength).set_binary(false);
          break;
        default:
          emit log(LOGERR,tr("Invalid Decimation Order"));
          return;
        }
      }
    } else {
      emit log(LOGERR,tr("No Decimation Order set"));
      return;
    }

    // stock options (triangle and vertices count) constraint
    bool verticesCount = false;
    bool trianglesCount = false;
    int vertices = 0;
    int triangles = 0;

    if ( _constraints.contains("vertices") ){

      bool ok;

      int value = _constraints["vertices"].toInt(&ok);

      if (ok){
        verticesCount = true;
        vertices = value;
      }
    } else if ( _constraints.contains("triangles") ){

      bool ok;

      int value = _constraints["triangles"].toInt(&ok);

      if (ok){
        trianglesCount = true;
        triangles = value;
      }
510
    }
Jan Möbius's avatar
Jan Möbius committed
511

512 513
    //distance constraint
    if ( _constraints.contains("distance") ){
514

515 516 517 518 519
      bool ok;

      double value = _constraints["distance"].toDouble(&ok);

      if (ok) {
520
        if (  decimater_object.add( hModHausdorff ) || (!verticesCount && !trianglesCount)  ) {
521 522 523 524
            decimater->setDistanceConstraint( value );
            decimater_object.module( hModHausdorff ).set_tolerance( decimater->distanceValue() );
        }
      }
525 526
    }

527 528
    //normal deviation constraint
    if ( _constraints.contains("normal_deviation") ){
529

530
      bool ok;
531

532
      int value = _constraints["normal_deviation"].toInt(&ok);
533

534
      if (ok) {
535
        if (  decimater_object.add( hModNormalDeviation ) || (!verticesCount && !trianglesCount)  ) {
536
            decimater->setNormalDeviationConstraint( value );
537
            decimater_object.module( hModNormalDeviation ).set_normal_deviation( decimater->normalDeviationValue() );
538 539
        }
      }
540 541 542 543 544
    } else { // flipping constraint
      if (  decimater_object.add( hModNormalFlipping ) || (!verticesCount && !trianglesCount)  ) {
        decimater->setNormalFlippingConstraint();
        // decimater_object.module( hModNormalFlipping ).set_max_normal_deviation( decimater->normalDeviationValue() ); ?
      }
545 546
    }

547 548 549 550 551 552 553 554
    //roundness constraint
    if ( _constraints.contains("roundness") ){

      bool ok;

      double value = _constraints["roundness"].toDouble(&ok);

      if (ok) {
555
        if (  decimater_object.add( hModRoundness ) || (!verticesCount && !trianglesCount)  ) {
556 557 558
            decimater->setRoundnessConstraint( value );
            decimater_object.module( hModRoundness ).set_min_roundness( decimater->roundnessValue(), true );
        }
559 560 561
      }
    }

562 563
    //aspect ratio constraint
    if ( _constraints.contains("aspect_ratio") ){
564

565 566 567 568 569 570 571 572 573 574 575 576 577 578
      bool ok;

      double value = _constraints["aspect_ratio"].toDouble(&ok);

      if (ok) {
        if (  decimater_object.add( hModAspectRatio ) || (!verticesCount && !trianglesCount)  ) {
            decimater->setAspectRatioConstraint( value );
            decimater_object.module( hModAspectRatio ).set_aspect_ratio( decimater->aspectRatioValue() );
        }
      }
    }

    //edge length constraint
    if ( _constraints.contains("edge_length") ){
579

580
      bool ok;
581

582
      double value = _constraints["edge_length"].toDouble(&ok);
583

584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600
      if (ok) {
        if (  decimater_object.add( hModEdgeLength ) || (!verticesCount && !trianglesCount)  ) {
            decimater->setEdgeLengthConstraint( value );
            decimater_object.module( hModEdgeLength ).set_edge_length( decimater->edgeLengthValue() );
        }
      }
    }

    //independent sets constraint
    if ( _constraints.contains("independent_sets") ){

      bool value = _constraints["independent_sets"].toBool();

      if (value) {
        if (  decimater_object.add( hModIndependent ) || (!verticesCount && !trianglesCount)  ) {
            decimater->setIndependentSetsConstraint();
        }
601 602 603 604 605 606 607 608 609 610
      }
    }

    //init the decimater
    if( ! decimater_object.initialize() ){
      emit log(LOGWARN, tr("Decimater could not be initialized"));
      return;
    }

    //decimate
611 612 613 614
    if ( verticesCount )
      decimater_object.decimate_to( vertices ); // do decimation (vertices)
    else if (trianglesCount )
      decimater_object.decimate_to_faces(0, triangles); // do decimation (triangles)
615
    else
616
      decimater_object.decimate_to_faces(0, 1); // do decimation
617 618 619 620 621 622 623

    object->mesh()->garbage_collection();
    object->mesh()->update_normals();
    object->update();

    // Create backup
    emit createBackup(_objID, "Decimation");
624

625
    // Create QVariantMap parameter string
626 627
    QString param = "("  + (_constraints.contains("decimation_order") ? tr("decimation_order =  %1").arg(_constraints["decimation_order"].toString()) : "") +
                    ", " + (_constraints.contains("distance") ? tr("distance = %1").arg(_constraints["distance"].toString()) : "") +
628
                    ", " + (_constraints.contains("normal_deviation") ? tr("normal_deviation = %1").arg(_constraints["normal_deviation"].toString()) : "") +
629
                    ", " + (_constraints.contains("edge_length") ? tr("edge_length = %1").arg(_constraints["edge_length"].toString()) : "") +
630
                    ", " + (_constraints.contains("roundness") ? tr("roundness = %1").arg(_constraints["roundness"].toString()) : "") +
631 632 633
                    ", " + (_constraints.contains("aspect_ratio") ? tr("aspect_ratio = %1").arg(_constraints["aspect_ratio"].toString()) : "") +
                    ", " + (_constraints.contains("independent_sets") ? tr("independent_sets = %1").arg(_constraints["independent_sets"].toString()) : "") +
                    ", " + (_constraints.contains("triangles") ? tr("triangles = %1").arg(_constraints["triangles"].toString()) : "") +
634
                    ", " + (_constraints.contains("vertices") ? tr("vertices = %1").arg(_constraints["vertices"].toString()) : "") + ")";
635

636
    emit scriptInfo( "decimate(" + QString::number(_objID) + ", " + param + ")" );
637

638 639 640 641 642
    emit updatedObject( baseObjectData->id() , UPDATE_TOPOLOGY);

  } else {
    emit log(LOGERR,tr("Unsupported object type for decimater"));
    return;
643 644 645 646 647 648 649
  }

  emit updateView();
}

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

650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
void DecimaterPlugin::slotUpdateNumVertices()
{
  // Only update if tool is visible
  if ( !tool_->isVisible() ) {
    return;
  }

  int max = 0;
  int div = 0;

  bool ok;
  emit functionExists( "infomeshobject" , "vertexCount(int)", ok  ) ;
  if (!ok)
  {
    tool_->currentNumVertices->setText ("<not available>");
    return;
  }

  for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType(DATA_TRIANGLE_MESH)) ;
                                        o_it != PluginFunctions::objectsEnd(); ++o_it)  {


    max = std::max( RPC::callFunctionValue<int>   ("infomeshobject" , "vertexCount",o_it->id()) , max );
    div++;
  }

  if (div <= 0)
    tool_->currentNumVertices->setText ("<not available>");
  else {
679 680 681
    tool_->verticesCount->blockSignals(true);
    tool_->verticesCountSlider->blockSignals(true);

682 683 684
    tool_->currentNumVertices->setText (QString::number(max));
    tool_->verticesCount->setMaximum(max);
    tool_->verticesCountSlider->setMaximum(max);
685

686
    if ( tool_->verticesCount->value() < 2 )
687
    {
688
      tool_->verticesCount->setValue( max / 2 );
689 690
      tool_->verticesCountSlider->setValue( max / 2);
    }
691 692 693

    tool_->verticesCount->blockSignals(false);
    tool_->verticesCountSlider->blockSignals(false);
694 695 696 697 698
  }
}

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

699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716
/** \brief gets and sets the current maximum number of triangles
 *
 */
void DecimaterPlugin::slotUpdateNumTriangles() {
  // only update if the tool is visible
  if (!tool_->isVisible())
    return;

  uint max = 0;
  int meshN = 0;

  for (PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DataType(DATA_TRIANGLE_MESH));
                                       o_it != PluginFunctions::objectsEnd(); ++o_it) {
    TriMesh* mesh = PluginFunctions::triMesh(o_it->id());
    max = std::max(mesh->n_faces(), max);
    meshN++;
  }

717 718 719
  tool_->trianglesCount->blockSignals(true);
  tool_->trianglesCountSlider->blockSignals(true);

720 721 722 723 724 725
  tool_->trianglesCount->setMinimum(1);
  tool_->trianglesCount->setMaximum(max);
  tool_->trianglesCountSlider->setMinimum(1);
  tool_->trianglesCountSlider->setMaximum(max);

  if (tool_->trianglesCount->value() < 2)
726 727 728 729
  {
    tool_->trianglesCount->setValue (max / 2 );
    tool_->trianglesCountSlider->setValue( max / 2);
  }
730 731 732

  tool_->trianglesCount->blockSignals(false);
  tool_->trianglesCountSlider->blockSignals(false);
733 734 735 736
}

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

737 738 739
void DecimaterPlugin::slotObjectSelectionChanged(int /*_identifier*/)
{
  slotUpdateNumVertices ();
740
  slotUpdateNumTriangles ();
741 742 743 744
}

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

745
void DecimaterPlugin::slotObjectUpdated(int /*_identifier*/ , const UpdateType& _type )
746
{
747
  if ( _type.contains(UPDATE_TOPOLOGY) ) {
748
    slotUpdateNumVertices ();
749 750
    slotUpdateNumTriangles ();
  }
751 752 753 754 755 756 757
}

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

// activate checkbox if value has changed
void DecimaterPlugin::updateVertices()
{
758 759 760 761 762 763 764 765 766
  tool_->rbVertices->setChecked (true);
}

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

// activate checkbox if value has changed
void DecimaterPlugin::updateTriangles()
{
  tool_->rbTriangles->setChecked (true);
767 768 769 770 771 772 773 774 775 776 777 778
}

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

// activate checkbox if value has changed
void DecimaterPlugin::updateNormalDev()
{
  tool_->cbNormalDev->setChecked (true);
}

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

779 780 781 782 783 784 785 786
// activate checkbox if value has changed
void DecimaterPlugin::updateEdgeLength()
{
  tool_->cbEdgeLength->setChecked (true);
}

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

787 788 789 790 791 792 793 794 795 796
// activate checkbox if value has changed
void DecimaterPlugin::updateDistance()
{
  tool_->cbDistance->setChecked (true);
}

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

Q_EXPORT_PLUGIN2(DecimaterPlugin , DecimaterPlugin );