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