IsotropicRemesherPlugin.cc 10 KB
Newer Older
Jan Möbius's avatar
Jan Möbius committed
1
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
33
34
35
36
37
38
39
40
41
42
*                           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/>.                                       *
*                                                                            *
\*===========================================================================*/

/*===========================================================================*\
*                                                                            *
*   $Revision$                                                       *
*   $LastChangedBy$                                                *
*   $Date$                     *
*                                                                            *
\*===========================================================================*/

Jan Möbius's avatar
 
Jan Möbius committed
43
44
45
46
47
#include "IsotropicRemesherPlugin.hh"
#include "IsotropicRemesherT.hh"

#include <OpenFlipper/BasePlugin/PluginFunctions.hh>

Jan Möbius's avatar
Jan Möbius committed
48
49
50
51
52
IsotropicRemesherPlugin::IsotropicRemesherPlugin() :
tool_(0),
toolIcon_(0),
edgeLength_(0),
thread_(0)
53
54
55
{
}

Jan Möbius's avatar
 
Jan Möbius committed
56
/// init the Toolbox
Jan Möbius's avatar
Jan Möbius committed
57
void IsotropicRemesherPlugin::initializePlugin() {
Matthias Möller's avatar
Matthias Möller committed
58
59
  if ( OpenFlipper::Options::gui() ) {
    tool_ = new IsotropicRemesherToolBox();
Jan Möbius's avatar
 
Jan Möbius committed
60

Matthias Möller's avatar
Matthias Möller committed
61
62
    QSize size(300, 300);
    tool_->resize(size);
Jan Möbius's avatar
 
Jan Möbius committed
63

Matthias Möller's avatar
Matthias Möller committed
64
    connect(tool_->remeshButton, SIGNAL(clicked()), this, SLOT(slotRemeshButtonClicked()) );
Jan Möbius's avatar
 
Jan Möbius committed
65

Matthias Möller's avatar
Matthias Möller committed
66
67
68
    connect(tool_->minEdgeLength, SIGNAL(clicked()), this, SLOT(slotSetMinLength()) );
    connect(tool_->maxEdgeLength, SIGNAL(clicked()), this, SLOT(slotSetMaxLength()) );
    connect(tool_->meanEdgeLength, SIGNAL(clicked()), this, SLOT(slotSetMeanLength()) );
Jan Möbius's avatar
 
Jan Möbius committed
69

Matthias Möller's avatar
Matthias Möller committed
70
71
72
    toolIcon_ = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"remesher.png");
    emit addToolbox( tr("Isotropic Remesher") , tool_, toolIcon_ );
  }
Jan Möbius's avatar
 
Jan Möbius committed
73
74
}

75
76
77
void IsotropicRemesherPlugin::slotRemeshButtonClicked() {
  edgeLength_ = tool_->targetEdgeLength->value();
  
78
79
80
81
82
83
84
  if ( thread_ == 0){
    thread_ = new OpenFlipperThread(name() + "IsotropicRemesh");                         // Create your thread containing a unique id \n
    connect(thread_,SIGNAL( finished(QString)), this,SIGNAL(finishJob(QString)));                           // connect your threads finish info to the global one ( you can do the same for a local one ) \n
    connect(thread_,SIGNAL( function() ), this,SLOT(slotRemesh()),Qt::DirectConnection);           // You can directly give a slot of your app that gets called \n
    connect(this,SIGNAL( finishJob(QString)), this, SLOT(threadFinished(QString)), Qt::QueuedConnection);
  }

85
86
  emit startJob( name() + "IsotropicRemesh", "Isotropic remeshing" , 0 , 100 , true);  // As long as meshes cannot be locked, this thread has to be blocking. Otherwise, during operation the mesh could be deleted. We don't want that!

87
88
  thread_->start();                                                                                       // start thread
  thread_->startProcessing();                                                                             // start processing
89
90
}

Jan Möbius's avatar
 
Jan Möbius committed
91
92
93
94
95
96
97
98
99
100
101

void IsotropicRemesherPlugin::slotRemesh(){

  //read one target objects
  for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType(DATA_TRIANGLE_MESH | DATA_POLY_MESH)) ;
                                        o_it != PluginFunctions::objectsEnd(); ++o_it)  {

    //check dataType
    if ( o_it->dataType(DATA_TRIANGLE_MESH) ) {
      TriMesh* mesh = PluginFunctions::triMesh(o_it);

102
103
104
105
      ProgressEmitter prgEmt(name() + "IsotropicRemesh");
      connect (&prgEmt, SIGNAL(changeDescription(QString,QString)), this, SIGNAL(setJobDescription(QString,QString)) );
      connect (&prgEmt, SIGNAL(signalJobState(QString,int)), this, SIGNAL(setJobState(QString,int)) );
      IsotropicRemesher< TriMesh > remesher(&prgEmt);
Jan Möbius's avatar
 
Jan Möbius committed
106

107
      remesher.remesh(*mesh, edgeLength_);
Jan Möbius's avatar
 
Jan Möbius committed
108
109
110
111
112
113
114
115
116

      mesh->update_normals();

    }else{
      emit log("Remeshing currently only implemented for triangle Meshes");
    }
  }
}

Dirk Wilden's avatar
Dirk Wilden committed
117
void IsotropicRemesherPlugin::threadFinished(QString /*_jobId*/) {
118
119
120
  
  std::cerr << "threadFinished() called" << std::endl;
  
121
122
123
  for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType(DATA_TRIANGLE_MESH | DATA_POLY_MESH)) ;
                                        o_it != PluginFunctions::objectsEnd(); ++o_it)  {

Jan Möbius's avatar
Jan Möbius committed
124
      emit updatedObject( o_it->id(), UPDATE_ALL );
125
126

      emit createBackup(o_it->id(),"Isotropic Remeshing");
Jan Möbius's avatar
Jan Möbius committed
127
  
128
129
130
131
132
      emit updateView();
    
  }
}

Jan Möbius's avatar
 
Jan Möbius committed
133
134
135
136
137
138
void IsotropicRemesherPlugin::slotSetMinLength()
{
  double current = 0.0;
  bool first = true;

  bool ok;
Jan Möbius's avatar
Jan Möbius committed
139
  emit functionExists( "infomeshobject" , "minEdgeLength(int)", ok  ) ;
Jan Möbius's avatar
 
Jan Möbius committed
140
141
142
143
144
145
146
147
  if (!ok)
    return;

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

    if (first)
    {
Jan Möbius's avatar
Jan Möbius committed
148
      current = RPC::callFunctionValue<double>("infomeshobject" , "minEdgeLength",o_it->id() );
Jan Möbius's avatar
 
Jan Möbius committed
149
150
151
      first = false;
    }
    else
Jan Möbius's avatar
Jan Möbius committed
152
      current = qMin (current, RPC::callFunctionValue<double>("infomeshobject" , "minEdgeLength",o_it->id() ));
Jan Möbius's avatar
 
Jan Möbius committed
153
154
155
156
157
158
159
160
161
162
163
164
165
    
  }

  if (!first)
    tool_->targetEdgeLength->setValue (current);
}

void IsotropicRemesherPlugin::slotSetMaxLength()
{
  double current = 0.0;
  bool first = true;

  bool ok;
Jan Möbius's avatar
Jan Möbius committed
166
  emit functionExists( "infomeshobject" , "maxEdgeLength(int)", ok  ) ;
Jan Möbius's avatar
 
Jan Möbius committed
167
168
169
170
171
172
173
174
  if (!ok)
    return;

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

    if (first)
    {
Jan Möbius's avatar
Jan Möbius committed
175
      current = RPC::callFunctionValue<double>("infomeshobject" , "maxEdgeLength",o_it->id() );
Jan Möbius's avatar
 
Jan Möbius committed
176
177
178
      first = false;
    }
    else
Jan Möbius's avatar
Jan Möbius committed
179
      current = qMax (current, RPC::callFunctionValue<double>("infomeshobject" , "maxEdgeLength",o_it->id() ));
Jan Möbius's avatar
 
Jan Möbius committed
180
181
182
183
184
185
186
187
188
189
190
191
192
    
  }

  if (!first)
    tool_->targetEdgeLength->setValue (current);
}

void IsotropicRemesherPlugin::slotSetMeanLength()
{
  double current = 0.0;
  int  div = 0;

  bool ok;
Jan Möbius's avatar
Jan Möbius committed
193
  emit functionExists( "infomeshobject" , "edgeCount(int)", ok  ) ;
Jan Möbius's avatar
 
Jan Möbius committed
194
195
196
197
198
199
200
  if (!ok)
    return;

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


Jan Möbius's avatar
Jan Möbius committed
201
202
203
    current += RPC::callFunctionValue<int>   ("infomeshobject" , "edgeCount",o_it->id()) *
               RPC::callFunctionValue<double>("infomeshobject" , "meanEdgeLength",o_it->id() );
    div     += RPC::callFunctionValue<int>   ("infomeshobject" , "edgeCount",o_it->id()      );
Jan Möbius's avatar
 
Jan Möbius committed
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
  }

  if (div > 0)
    tool_->targetEdgeLength->setValue (current / div);
}


/// Initialize the plugin
void IsotropicRemesherPlugin::pluginsInitialized(){

  emit setSlotDescription("isotropicRemesh(int,double)", "Isotropic Remeshing",
                          QString("object_id,targetEdgeLength").split(","),
                          QString("id of an object, target edge length").split(","));
}


void IsotropicRemesherPlugin::isotropicRemesh(int _objectID, double _targetEdgeLength ){
  BaseObjectData* object  = 0;


  if ( PluginFunctions::getObject(_objectID, object) ){

    //check dataType
    if ( object->dataType(DATA_TRIANGLE_MESH)) {

      TriMesh* mesh = PluginFunctions::triMesh(object);

      IsotropicRemesher< TriMesh > remesher;

      remesher.remesh(*mesh, _targetEdgeLength);

      mesh->update_normals();

Jan Möbius's avatar
Jan Möbius committed
237
      emit updatedObject( object->id(), UPDATE_ALL );
Jan Möbius's avatar
Jan Möbius committed
238
      
239
      emit scriptInfo("isotropicRemesh(" + QString::number(_objectID) + ", " + QString::number(_targetEdgeLength) + ")");
Jan Möbius's avatar
 
Jan Möbius committed
240
241
242
243
244
245
246
247
248
249
250
251
252
253

      emit updateView();

      return;

    }else{
      emit log("Remeshing currently only implemented for triangle Meshes");
      return;
    }
  }else{
    emit log("Unable to get object");
  }
}

Matthias Möller's avatar
Matthias Möller committed
254
255
256
257
258
#if QT_VERSION < 0x050000
  Q_EXPORT_PLUGIN2( isotropicRemesherPlugin , IsotropicRemesherPlugin );
#endif


Jan Möbius's avatar
 
Jan Möbius committed
259