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