Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
HoleFillerPlugin.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 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 #include "HoleFillerPlugin.hh"
51 
53 
54 #if QT_VERSION >= 0x050000
55 #else
56 #include <QtGui>
57 #endif
58 
59 #include "HoleInfoT.hh"
60 
61 #define HOLEINFO "HoleInfoData"
62 
65  tool_(0)
66 {
67 
68 }
69 
72 {
74  QSize size(300, 300);
75  tool_->resize(size);
76 
77  connect(tool_->tableWidget,SIGNAL(itemSelectionChanged()),this,SLOT(slotItemSelectionChanged()));
78 
79  connect(tool_->tableWidget,SIGNAL(cellDoubleClicked(int,int)),this,SLOT(slotCellDoubleClicked(int,int)));
80 
81  connect(tool_->detect,SIGNAL(clicked()),this,SLOT(detectButton()));
82  connect(tool_->fillButton, SIGNAL(clicked()), this, SLOT(slotFillSelection()) );
83 
84  QIcon* toolIcon = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"holefilling.png");
85 
86  emit addToolbox( tr("Hole Filler") , tool_ , toolIcon);
87 }
88 
91 {
92  emit addPickMode("Separator");
93  emit addPickMode("Hole Filler");
94 
95  emit setSlotDescription("fillAllHoles(int)", tr("Fill all holes from a given Mesh"),
96  QString("objectId").split(","), QString("Id of the mesh").split(","));
97 
98  emit setSlotDescription("fillHole(int,int)", tr("Fill a holes from a given Mesh where edgeHandle is on the boundary"),
99  QString("objectId,edgeHandle").split(","), QString("Id of the mesh,Handle of one boundary edge of the hole").split(","));
100 
101  //build the tableWidget with headers
102  update_menu();
103 }
104 
105 void HoleFillerPlugin::getSelectedHoles(std::vector<int>& _holeIds, std::vector<int>& _objIds)
106 {
107  QModelIndexList indices = tool_->tableWidget->selectionModel()->selectedRows();
108 
109  //get a map from objectID to (selected) holeIDs
110  for (int i=0; i < indices.size(); i++){
111  int objID = holeMapping_[ indices[i].row() ].first;
112  int holeID = holeMapping_[ indices[i].row() ].second;
113 
114  _holeIds.push_back ( holeID );
115  _objIds.push_back( objID );
116  }
117 }
118 
121 
122  //get a map from objectID to (selected) holeIDs
123  std::vector< int > holes;
124  std::vector< int > objects;
125  getSelectedHoles(holes,objects);
126 
127  //init progressDialog
128  QProgressDialog progress(tr("Filling holes..."), tr("Abort"), 0, holes.size(), 0);
129  progress.setWindowModality(Qt::ApplicationModal);
130  progress.setValue(0);
131 
132  int counter = 0;
133 
134  //iterate over all objects with holes that should be filled
136 
137  // TYPE is TRIMESH
138  if ( o_it->dataType( DATA_TRIANGLE_MESH ) ) {
139 
140  TriMesh* mesh = PluginFunctions::triMesh(o_it);
141 
142  //get perObjectData
143  HoleInfo< TriMesh >* holeInfo = dynamic_cast< HoleInfo< TriMesh >* > ( o_it->objectData(HOLEINFO) );
144 
145  if (holeInfo == 0){
146  holeInfo = new HoleInfo< TriMesh >( mesh );
147  o_it->setObjectData(HOLEINFO, holeInfo);
148  }
149 
150  //fill the holes
151  for (uint i = 0; i < objects.size(); i++)
152  if ( objects[i] == o_it->id() ){
153  holeInfo->fillHole( holes[i]);
154 
155  if (progress.wasCanceled())
156  break;
157  else
158  progress.setValue(++counter);
159  }
160 
161  //update the object
162  emit updatedObject(o_it->id(),UPDATE_ALL);
163 
164  holeInfo->getHoles();
165 
166  update_menu();
167  emit createBackup( o_it->id(), "Hole Filling", UPDATE_GEOMETRY | UPDATE_TOPOLOGY | UPDATE_SELECTION);
168  }
169  // DATATYPE is POLYMESH
170  else if ( o_it->dataType( DATA_POLY_MESH ) ) {
171  emit log(LOGWARN, tr("HoleFilling unsupported for poly meshes") );
172  continue;
173  }
174 
175  //abort if user wants to
176  if (progress.wasCanceled())
177  break;
178  }
179 
180  progress.close();
181 
182  emit updateView();
183 }
184 
187 
188  std::vector< int > holes;
189  std::vector< int > objects;
190  getSelectedHoles(holes,objects);
191 
192  //iterate over all objects with holes that should be displayed
194 
195  // TYPE is TRIMESH
196  if ( o_it->dataType( DATA_TRIANGLE_MESH ) ) {
197 
198  TriMesh* mesh = PluginFunctions::triMesh(o_it);
199 
200  //get perObjectData
201  HoleInfo< TriMesh >* holeInfo = dynamic_cast< HoleInfo< TriMesh >* > ( o_it->objectData(HOLEINFO) );
202 
203  if (holeInfo == 0){
204  holeInfo = new HoleInfo< TriMesh >( mesh );
205  o_it->setObjectData(HOLEINFO, holeInfo);
206  }
207 
208  //clear the edge selection
209  MeshSelection::clearEdgeSelection(mesh);
210 
211  //select the holes
212  for (uint i = 0; i < objects.size(); i++)
213  if ( objects[i] == o_it->id() )
214  holeInfo->selectHole( holes[i] );
215 
216  //update the object
217  emit updatedObject(o_it->id(),UPDATE_SELECTION);
218  }
219  // DATATYPE is POLYMESH
220  else if ( o_it->dataType( DATA_POLY_MESH ) ) {
221 
222  PolyMesh* mesh = PluginFunctions::polyMesh(o_it);
223 
224  //get perObjectData
225  HoleInfo< PolyMesh >* holeInfo = dynamic_cast< HoleInfo< PolyMesh >* > ( o_it->objectData(HOLEINFO) );
226 
227  if (holeInfo == 0){
228  holeInfo = new HoleInfo< PolyMesh >( mesh );
229  o_it->setObjectData(HOLEINFO, holeInfo);
230  }
231 
232  //clear the edge selection
233  MeshSelection::clearEdgeSelection(mesh);
234 
235  //select the holes
236  for (uint i = 0; i < objects.size(); i++)
237  if ( objects[i] == o_it->id() )
238  holeInfo->selectHole( holes[i] );
239 
240  //update the object
241  emit updatedObject(o_it->id(),UPDATE_SELECTION);
242 
243  }
244  }
245 
246  emit updateView();
247 }
248 
250 void HoleFillerPlugin::slotCellDoubleClicked(int _row , int /*_col*/) {
251 
252  if ( _row > (int)holeMapping_.size() ) {
253  emit log(LOGWARN, tr("Error for holeMapping_ vector size") );
254  return;
255  }
256 
257  BaseObjectData* object;
258  int objID = holeMapping_[_row].first;
259  int holeID = holeMapping_[_row].second;
260 
261  if ( !PluginFunctions::getObject( objID, object ) ) {
262  emit log(LOGWARN, tr("Unable to find object for hole (should not happen!!)") );
263  return;
264  }
265 
266  // TYPE is TRIMESH
267  if ( object->dataType( DATA_TRIANGLE_MESH ) ) {
268 
269  TriMesh* mesh = PluginFunctions::triMesh(object);
270 
271  //get perObjectData
272  HoleInfo< TriMesh >* holeInfo = dynamic_cast< HoleInfo< TriMesh >* > ( object->objectData(HOLEINFO) );
273 
274  if (holeInfo == 0){
275  holeInfo = new HoleInfo< TriMesh >( mesh );
276  object->setObjectData(HOLEINFO, holeInfo);
277  }
278 
279  //fill the hole
280  holeInfo->fillHole( holeID );
281 
282  emit updatedObject(object->id(),UPDATE_ALL);
283 
284  holeInfo->getHoles();
285 
286  update_menu();
287 
288  emit updateView();
289  }
290  // DATATYPE is POLYMESH
291  else if ( object->dataType( DATA_POLY_MESH ) ) {
292 
293 // PolyMesh* mesh = PluginFunctions::polyMesh(object);
294 //
295 // HoleInfo< PolyMesh >* holeInfo = dynamic_cast< HoleInfo< PolyMesh >* > ( object->objectData(HOLEINFO) );
296 //
297 // if (holeInfo == 0){
298 // holeInfo = new HoleInfo< PolyMesh >( mesh );
299 // object->setObjectData(HOLEINFO, holeInfo);
300 // }
301 //
302 // holeInfo->getHoles();
303 
304  emit log(LOGWARN,tr("HoleFilling unsupported for poly meshes"));
305  return;
306  }
307 }
308 
311 {
313 
314  //case TRIMESH
315  if ( o_it->dataType( DATA_TRIANGLE_MESH ) ) {
316 
317  HoleInfo< TriMesh >* holeInfo = dynamic_cast< HoleInfo< TriMesh >* > ( o_it->objectData(HOLEINFO) );
318 
319  if ( holeInfo == 0 ){
320  TriMesh* mesh = PluginFunctions::triMesh(*o_it);
321  holeInfo = new HoleInfo< TriMesh >( mesh );
322  o_it->setObjectData(HOLEINFO, holeInfo);
323  }
324 
325  holeInfo->getHoles();
326  }
327 
328 // //case POLYMESH
329 // if ( o_it->dataType( DATA_POLY_MESH ) ) {
330 //
331 // HoleInfo< PolyMesh >* holeInfo = dynamic_cast< HoleInfo< PolyMesh >* > ( o_it->objectData(HOLEINFO) );
332 //
333 // if (holeInfo == 0){
334 // PolyMesh* mesh = PluginFunctions::polyMesh(*o_it);
335 // holeInfo = new HoleInfo< PolyMesh >( mesh );
336 // o_it->setObjectData(HOLEINFO, holeInfo);
337 // }
338 //
339 // holeInfo->getHoles();
340 // }
341  }
342 
343  update_menu();
344 }
345 
347 void HoleFillerPlugin::slotObjectUpdated( int _identifier, const UpdateType& _type ) {
348 
349  BaseObjectData* object;
350 
351  // Check if this is a usable Object
352  if ( !PluginFunctions::getObject(_identifier,object) )
353  return;
354 
355  bool updated = false;
356 
357  if ( _type.contains(UPDATE_TOPOLOGY) ) {
358 
359  // get holes for TRIMESH
360  if ( object->dataType( DATA_TRIANGLE_MESH ) ) {
361 
362  HoleInfo< TriMesh >* holeInfo = dynamic_cast< HoleInfo< TriMesh >* > ( object->objectData(HOLEINFO) );
363 
364  if ( holeInfo ) {
365  holeInfo->getHoles();
366  updated = true;
367  }
368  }
369 
370  // get holes for POLYMESH
371  else if ( object->dataType( DATA_POLY_MESH ) ) {
372 
373  HoleInfo< PolyMesh >* holeInfo = dynamic_cast< HoleInfo< PolyMesh >* > ( object->objectData(HOLEINFO) );
374 
375  if ( holeInfo ) {
376  holeInfo->getHoles();
377  updated = true;
378  }
379  }
380  }
381 
382  // Only update if something has changed!
383  if ( updated )
384  update_menu();
385 }
386 
389 
390  holeMapping_.clear();
391 
392  tool_->tableWidget->clear();
393 
394  tool_->tableWidget->setRowCount ( 0 );
395  tool_->tableWidget->setColumnCount ( 4 );
396 
397  QStringList headerdata;
398  headerdata << "Object" << "Edges" << "Boundary Length" << "BB Diagonal";
399 
400  tool_->tableWidget->setHorizontalHeaderLabels(headerdata);
401  tool_->updateGeometry();
402 
403  int elements = 0;
404  int count = 0;
405 
406  //iterate over all objects
408 
409  // DATATYPE is TRIMESH
410  if ( o_it->dataType( DATA_TRIANGLE_MESH ) ) {
411 
412  //get perObjectData
413  HoleInfo< TriMesh >* holeInfo = dynamic_cast< HoleInfo< TriMesh >* > ( o_it->objectData(HOLEINFO) );
414 
415  if (holeInfo != 0){
416  elements += holeInfo->holes()->size();
417  tool_->tableWidget->setRowCount ( elements );
418 
419  //add holes to the table
420  for (uint i = 0 ; i < holeInfo->holes()->size() ; ++i ) {
421  // Set Name of the object
422  QTableWidgetItem* name = new QTableWidgetItem( o_it->name() );
423  name->setFlags( 0 );
424  name->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled);
425  tool_->tableWidget->setItem(count,0,name);
426 
427  // Set Number of the edges
428  QTableWidgetItem* size = new QTableWidgetItem( QString::number( (*holeInfo->holes())[i].size() ) );
429  size->setFlags( 0 );
430  size->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled);
431  tool_->tableWidget->setItem(count,1,size);
432 
433  // Set boundary Length
434  std::vector< TriMesh::EdgeHandle >::iterator endIter = (*holeInfo->holes())[i].end();
435  double boundaryLength = 0.0;
436  TriMesh* mesh = 0;
437  PluginFunctions::getMesh(o_it->id(),mesh);
438  for (std::vector< TriMesh::EdgeHandle >::iterator edgeIter = (*holeInfo->holes())[i].begin(); edgeIter != endIter; ++edgeIter)
439  boundaryLength += mesh->calc_edge_length(*edgeIter);
440  QTableWidgetItem* boundaryLengthWidget = new QTableWidgetItem( QString::number(boundaryLength) );
441  boundaryLengthWidget->setFlags( 0 );
442  boundaryLengthWidget->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled);
443  tool_->tableWidget->setItem(count,2,boundaryLengthWidget);
444 
445  //compute bounding box
446  TriMesh::Point minCoord = TriMesh::Point(std::numeric_limits<TriMesh::Scalar>::max(),std::numeric_limits<TriMesh::Scalar>::max(),std::numeric_limits<TriMesh::Scalar>::max());
447  TriMesh::Point maxCoord = TriMesh::Point(-std::numeric_limits<TriMesh::Scalar>::max(),-std::numeric_limits<TriMesh::Scalar>::max(),-std::numeric_limits<TriMesh::Scalar>::max());
448  for (std::vector< TriMesh::EdgeHandle >::iterator edgeIter = (*holeInfo->holes())[i].begin(); edgeIter != endIter; ++edgeIter)
449  {
450  TriMesh::Point pos = mesh->point(mesh->from_vertex_handle(mesh->halfedge_handle(*edgeIter,0)));
451  minCoord[0] = std::min(minCoord[0],pos[0]);
452  minCoord[1] = std::min(minCoord[1],pos[1]);
453  minCoord[2] = std::min(minCoord[2],pos[2]);
454 
455  maxCoord[0] = std::max(maxCoord[0],pos[0]);
456  maxCoord[1] = std::max(maxCoord[1],pos[1]);
457  maxCoord[2] = std::max(maxCoord[2],pos[2]);
458  }
459 
460  TriMesh::Scalar bbDiagonal = (minCoord-maxCoord).length();
461 
462  QTableWidgetItem* bbDiagonalWidget = new QTableWidgetItem( QString::number(bbDiagonal) );
463  bbDiagonalWidget->setFlags( 0 );
464  bbDiagonalWidget->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled);
465  tool_->tableWidget->setItem(count,3,bbDiagonalWidget);
466 
467  // remember the id for the hole
468  holeMapping_.push_back( std::pair<int , int>( o_it->id() , i ) );
469 
470  ++count;
471  }
472  }
473  }
474  // DATATYPE is POLYMESH
475  else if ( o_it->dataType( DATA_POLY_MESH ) ) {
476 
477  //get perObjectData
478  HoleInfo< PolyMesh >* holeInfo = dynamic_cast< HoleInfo< PolyMesh >* > ( o_it->objectData(HOLEINFO) );
479 
480  if (holeInfo != 0){
481  elements += holeInfo->holes()->size();
482  tool_->tableWidget->setRowCount ( elements );
483 
484  //add holes to the table
485  for (uint i = 0 ; i < holeInfo->holes()->size() ; ++i ) {
486  // Set Name of the object
487  QTableWidgetItem* name = new QTableWidgetItem( o_it->name() );
488  name->setFlags( 0 );
489  name->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled);
490  tool_->tableWidget->setItem(count,0,name);
491 
492  // Set Number of the edges
493  QTableWidgetItem* size = new QTableWidgetItem( QString::number( (*holeInfo->holes())[i].size() ) );
494  size->setFlags( 0 );
495  size->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled);
496  tool_->tableWidget->setItem(count,1,size);
497 
498  // Set radius
499  QTableWidgetItem* radius = new QTableWidgetItem( "TODO" );
500  radius->setFlags( 0 );
501  radius->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled);
502  tool_->tableWidget->setItem(count,2,radius);
503 
504  // remember the id for the hole
505  holeMapping_.push_back( std::pair<int , int>( o_it->id() , i ) );
506 
507  ++count;
508  }
509  }
510  }
511  }
512 
513  tool_->tableWidget->resizeColumnToContents ( 1 );
514 }
515 
517 void HoleFillerPlugin::fillAllHoles(int _objectID){
518  BaseObjectData* object = 0;
519  PluginFunctions::getObject( _objectID , object );
520 
521  if (object == 0){
522  emit log(LOGERR, tr("Could not get object from ID.") );
523  return;
524  }
525 
526  emit scriptInfo( "fillAllHoles( ObjectId )" );
527 
528 
529  // TYPE is TRIMESH
530  if ( object->dataType( DATA_TRIANGLE_MESH ) ) {
531 
532  TriMesh* mesh = PluginFunctions::triMesh(object);
533 
534  //get perObjectData
535  HoleInfo< TriMesh >* holeInfo = dynamic_cast< HoleInfo< TriMesh >* > ( object->objectData(HOLEINFO) );
536 
537  if (holeInfo == 0){
538  holeInfo = new HoleInfo< TriMesh >( mesh );
539  object->setObjectData(HOLEINFO, holeInfo);
540  }
541 
542  //fill the hole
543  holeInfo->fillAllHoles();
544 
545  //and update everything
546  emit updatedObject(object->id(),UPDATE_ALL);
547 
548  holeInfo->getHoles();
549 
550  update_menu();
551 
552  emit updateView();
553  }
554  // DATATYPE is POLYMESH
555  else if ( object->dataType( DATA_POLY_MESH ) ) {
556  emit log(LOGERR, tr("HoleFilling unsopported for poly meshes.") );
557  return;
558  }
559 }
560 
561 
563 void HoleFillerPlugin::fillHole(int _objectID, int _edgeHandle){
564  BaseObjectData* object = 0;
565  PluginFunctions::getObject( _objectID , object );
566 
567  if (object == 0){
568  emit log(LOGERR, tr("Could not get object from ID.") );
569  return;
570  }
571 
572  emit scriptInfo( "fillHole( ObjectId , EdgeHandle )" );
573 
574 
575  // TYPE is TRIMESH
576  if ( object->dataType( DATA_TRIANGLE_MESH ) ) {
577 
578  TriMesh* mesh = PluginFunctions::triMesh(object);
579 
580  //get perObjectData
581  HoleInfo< TriMesh >* holeInfo = dynamic_cast< HoleInfo< TriMesh >* > ( object->objectData(HOLEINFO) );
582 
583  if (holeInfo == 0){
584  holeInfo = new HoleInfo< TriMesh >( mesh );
585  object->setObjectData(HOLEINFO, holeInfo);
586  }
587 
588  //check edgeHandle
589  TriMesh::EdgeHandle eh(_edgeHandle);
590 
591  if ( !eh.is_valid() || !mesh->is_boundary(eh) ){
592  emit log(LOGERR, tr("Invalid edge handle.") );
593  return;
594  }
595 
596  //fill the hole
597  holeInfo->fillHole( eh );
598 
599  //and update everything
600  emit updatedObject(object->id(),UPDATE_ALL);
601 
602  holeInfo->getHoles();
603 
604  update_menu();
605 
606  emit updateView();
607  }
608  // DATATYPE is POLYMESH
609  else if ( object->dataType( DATA_POLY_MESH ) ) {
610  emit log(LOGERR, tr("HoleFilling unsopported for poly meshes.") );
611  return;
612  }
613 }
614 
615 #if QT_VERSION < 0x050000
616 Q_EXPORT_PLUGIN2( holefillerplugin , HoleFillerPlugin );
617 #endif
618 
void pluginsInitialized()
add PickModes after initialization
const QStringList ALL_OBJECTS
Iterable object range.
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
void selectHole(int _index)
select a hole with given index
Definition: HoleInfoT.cc:225
void slotItemSelectionChanged()
slot for displaying selected holes
bool getMesh(int _identifier, PolyMesh *&_mesh)
Get the Poly Mesh which has the given identifier.
void slotFillSelection()
Fill all selected holes.
bool contains(const UpdateType &_type) const
Check if this update contains the given UpdateType.
Definition: UpdateType.cc:111
Update type class.
Definition: UpdateType.hh:70
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
void slotCellDoubleClicked(int _row, int _col)
Slot for filling holes from double-clicked rows.
std::vector< std::vector< typename MeshT::EdgeHandle > > * holes()
get the holes vector
Definition: HoleInfoT.cc:241
bool getObject(int _identifier, BSplineCurveObject *&_object)
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
void detectButton()
detect holes on all objects
void update_menu()
update the entries in the tableWidget
void fillAllHoles(int _stages=3)
fill all holes of the mesh
Definition: HoleInfoT.cc:213
bool dataType(DataType _type) const
Definition: BaseObject.cc:232
HoleFillerPlugin()
Constructor.
const UpdateType UPDATE_SELECTION(UpdateTypeSet(1)<< 4)
Selection updated.
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
std::vector< std::pair< int, int > > holeMapping_
map from the index in the table to (object-id, hole-id)
void slotObjectUpdated(int _identifier, const UpdateType &_type)
check for holes if an object has changed
void fillHole(int _objectID, int _edgeHandle)
fill a hole in given object where _edgeHandle is on the boundary
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
void getHoles()
get all holes and store them internally
Definition: HoleInfoT.cc:73
#define DATA_POLY_MESH
Definition: PolyMesh.hh:65
const UpdateType UPDATE_TOPOLOGY(UpdateTypeSet(1)<< 3)
Topology updated.
QString name()
Return a name for the plugin.
Functions for selection on a mesh.
void fillAllHoles(int _objectID)
fill all holes from a given object
void getSelectedHoles(std::vector< int > &_holeIds, std::vector< int > &_objIds)
get a map from objectID to (selected) holeIDs
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:66
void fillHole(int _index, int _stages=3)
fill hole with given index
Definition: HoleInfoT.cc:175
int id() const
Definition: BaseObject.cc:201
HoleFillerToolbarWidget * tool_
Widget for Toolbox.
void initializePlugin()
Initialize the toolbox widget.