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